Migrating ASP.NET to Azure Cosmos DB w/ GitHub Copilot | Sergiy Smyrnov | Azure Cosmos DB Conf 2026

Migrating ASP.NET to Azure Cosmos DB w/ GitHub Copilot | Sergiy Smyrnov | Azure Cosmos DB Conf 2026

Microsoft Developer

0:07 Hello, welcome to my session from JOIN to JSON,

0:11 migrating the real world ASP.NET application

0:13 to Azure Cosmos DB with GitHub Copilot.

0:16 My name is Sergiy Smyrnov.

0:17 I am principal PM in Azure Cosmos DB team.

0:21 Normally, migrating relational databases and applications using relational

0:26 databases to NoSQL is naturally a hard problem.

0:31 Today we're going to talk about, example,

0:34 how to use GitHub Copilot with Cosmos DB agent kit to accelerate the journey.

0:40 We're to take a sample e-commerce workload based

0:43 on the SQL Server Adventure Works LT schema,

0:47 which is a popular sample schema in SQL Server,

0:52 which has more than 10 tables with complex joins consisting from customers,

0:59 products, categories, tags, and sales orders.

1:04 And on top of it, we're going to make it a little more challenging.

1:07 to add the actual application running along with it.

1:10 For that, we're to use Azure Samples

1:12 Adventure Works application published a long time ago.

1:14 uh And along with GitHub Copilot, we're going to use Cosmos DB Agent Kit.

1:21 ah What is Cosmos DB Agent Kit?

1:24 Cosmos DB Agent Kit is open source collection of AI

1:28 skills we built to work across GitHub Copilot, Cloud Code,

1:31 and other agent skills, compatible tools,

1:34 and CLIs to help with those complex tasks

1:37 to design data model from relational to NoSQL,

1:40 choose the right partition key, do the query optimization,

1:43 apply SDK best practices when we convert application,

1:47 and validate all the information we pass along as part of the process.

1:52 This is a link to our Cosmos DB agent kit, which is published in open source.

1:57 You're welcome to use it.

1:58 You're welcome to contribute it.

2:01 Now let's go to live demo.

2:03 I'm not going to bore you with slides.

2:04 We're going to just actually show you how to do it end to end.

2:07 So for that, I'm going to show, I mentioned the AdventureWorks uh application.

2:11 This is a link to that application.

2:14 What I did, I cloned that application to my local workstation.

2:18 uh And then on top of it,

2:21 I installed our Cosmos DB agent kit, which is an open source repo.

2:25 And the installation is very simple.

2:27 All you have to do is copy NPX skills

2:30 at Cosmos DB agent kit locally and install it.

2:35 have choices to install it to local project or globally.

2:39 So let's dive right in to our environment.

2:44 This is a local clone of the application.

2:46 ah I already pre-installed agent kit uh in my environment, agent kit skills.

2:54 You can see that I installed skills here.

2:57 All it did is it's created the dot

3:00 agents subdirectory in my environment with skills,

3:03 Cosmos DB best practices and uh created a rules folder.

3:07 This is pretty much a secret sauce of all

3:10 the brain power of Cosmos DB best practices knowledge

3:14 packaged in a small reusable skills dot MD format

3:17 for each skill type with the prefixes by category.

3:21 And those rules will be used by GitHub Copilot as part of our workflow.

3:27 Along with that, we've added a couple of things

3:31 to help GitHub Copilot to add a structure to the process.

3:36 First thing is we've created step-by-step prompts,

3:40 which does show the navigation process of what to ask Copilot at each stage.

3:48 Like if we break the application

3:51 modernization and data migration project in phases,

3:55 and also what specific outcomes or artifacts each phase need to produce.

3:59 For example, in phase one,

4:02 we produce migration assessment prompt with specific outcomes,

4:05 migration assessment uh MD file, and XS parents and volume metrics.

4:10 Those two are actually very critical to next phases because a lot of times,

4:17 converting relational schema and relational application

4:20 to NoSQL database like Cosmos require

4:23 knowledge of both access patterns and volumetrics to ensure that we pick

4:28 the right partition key and align uh queries and access patterns to access

4:33 patterns actually used in the application

4:36 and not just derive it and hallucinate.

4:38 uh For that, we created two template files

4:42 to fill those access patterns and volumetrics in the files.

4:47 The volumetric template here is uh Very simple.

4:55 uh We basically define in the schema table row counts, average row size,

5:01 some gross projected rate,

5:03 uh and project some read-write TPS with examples of the nodes.

5:08 And this is sample schema, just basically uh use feed this to copilot

5:13 to populate it based on the actual data samples.

5:17 you can then, because it's an empty file, you can actually come back and uh

5:22 update those details based on your business knowledge.

5:26 The iAccessParents template is similar structure,

5:28 but it has a little different details.

5:36 where we break the read patterns and write patterns separately,

5:40 and we annotate them with R and W for simplicity.

5:45 And then we define the pattern name,

5:47 define which tables participate in pattern names,

5:50 obviously for reads in relational world, could be multiple tables for join,

5:54 define the filter lookup fields, and then again, define the frequency TPS,

5:59 along with some latency requirements and additional notes.

6:03 Same thing for writes and if there

6:05 is any additional notes about like transactional consistency,

6:07 we can put it at the bottom.

6:09 So those two will fit into our workflow to produce additional details.

6:16 Now, uh if we look into our flow of our step-by-step prompts,

6:22 ah we basically have seven prompts.

6:25 First one is create migration assessment report.

6:29 Second one is...

6:31 do schema and access pattern conversion plan.

6:34 This is what will produce actual Cosmos DB data model.

6:39 Then uh prompts three and four are created

6:41 based on the final data model we produce.

6:44 uh We create infrastructure as a code

6:48 samples for Azure deployment as infra biceps.

6:51 Here you can plug in like Terraform for example,

6:55 if your company is doing Terraform deployments

6:57 uh or any other commands for deployments.

7:00 We specify some uh specific parameters for actual deployment like Azure region,

7:06 your account name, database name,

7:08 add principal ID for entry ID deployments or anything else.

7:12 Next step is actually deploying validates

7:15 that deployment is successful on Azure.

7:17 Or if you test in locally in uh container emulator, you can substitute it.

7:23 uh Prompt-Fi would be converting data to JSON based on the data model.

7:30 uh pre-join aggregates and then do the loading into Cosmos.

7:34 created as a data migration, basically build data migration pipeline.

7:38 ah Here for our simplicity,

7:40 we use CSV because our sample data is in CSVs for that simple demo,

7:46 but you can build EDF pipeline, can build Spark notebooks,

7:50 uh anything is possible once you have the mappings of the source and target.

7:53 uh Prompt 6 is based on the...

7:57 assessment and schema conversion, create application conversion plan.

8:02 This is where we're to take it beyond database itself.

8:04 We can actually analyze the application code,

8:08 analyze controllers, analyze methods, analyze classes, uh services,

8:12 and create a detailed plan for actual application conversion.

8:17 You can see that we've identified a few things here before to shorten the cycle,

8:23 that .NET conversion for Cosmos DB, has a Newton soft JSON dependency.

8:28 need to make sure that we account for this, update Cosmos client builder,

8:32 namespace, et cetera, and clean up some reference with the errors or warnings.

8:37 And final step is execute application diversion.

8:41 I've pre-created a lot of the steps all the way through step seven.

8:45 We're gonna go into details to look what the outcomes of those steps exist.

8:50 But for now, I wanna kick off the prompt seven.

8:54 In the prompts, folder.

8:57 And while it's running, we're going to review some of the outcomes.

8:59 So while it's turning away, we're actually going to see ah what's happening.

9:04 So let me copy and paste the prompts here.

9:11 And we're going to ask Copilot.

9:13 So as of right now, the only thing is

9:18 done is uh analyzing my SQL script DDL schema,

9:22 analyze sample files, uh analyze the application itself.

9:26 You see that in the models, uh views, controllers, everything is still original.

9:32 We have not changed actual application code.

9:34 All we've done is we've done a bunch of assessments and we

9:39 created the folders here for actual for actual uh data conversion.

9:45 And we've created infra code to load data in.

9:47 ah So now we're actually going to trigger the application migration plan here.

9:53 So this is my prompt, follow the final schema and access

9:56 pattern conversion plan and application conversion plan,

9:59 rewrite the application to Cosmos DB NoSQL,

10:01 start application, run API validation tests.

10:04 And I define three clear success criteria goals.

10:07 Successful build, application start successfully, return local URL,

10:11 and do API validation test successfully.

10:15 And then at end, we're to return the URL for manual UI validation.

10:17 I'm going to do it live at the end.

10:19 So let's kick it off.

10:26 While it's running, let's do...

10:30 a quick review of the outcomes in the earliest steps I walked through.

10:39 So the first step produce assessment.

10:49 So let's look outcomes of the assessment.

10:52 So in the assessment,

10:55 it recognized that, it analyzed that schema has 12 tables across two schemas,

11:03 sales of T and DBO, whereas migration availability is pretty high.

11:10 It mapped the application technology stack,

11:13 recognized that it has pretty old .NET Core 2.1 with ASP, .NET, and VC.

11:19 using entity framework, using SQL Server database and some front end.

11:24 uh It started doing the initial uh entity relational summary,

11:29 ah identifying key database features to use uh and start

11:34 doing data model analysis and propose some Cosmos DB container design.

11:40 So initially it's created container, let me allows this in this workspace.

11:48 um It started proposing some initial container

11:51 design with customer IDs, a partition key,

11:54 some unique key policies, and start stepping out some nest adjacent models.

11:59 uh Same thing for products and categories.

12:01 uh And identifying access pattern methods.

12:05 Then after that, we went to uh next steps, schema and access patterns.

12:13 And in that step, we...

12:17 We went little further.

12:18 We went really, really deep into container strategy, document models,

12:23 partition key design to start analyzing

12:26 our populated access patterns and volumetrics produced

12:29 from the templates based on those assessments

12:33 to annotating uh all the in-scope entities.

12:36 uh Based on the assessment, actually told it to remove the DBO.

12:41 uh tables because of what two tables which not related

12:45 to application that were related to some DBA structures for deployments,

12:49 which we do not really want to carry over to ah Cosmos NoSQL.

12:54 We put it in autoscope.

12:55 We excluded build version error log uh for metadata

12:58 uh because normally in like when we modernize application,

13:02 we actually want to move it as a database

13:05 and move it to like application insights or Azure Monitor.

13:08 um We define what's app monetization scope is.

13:12 We actually told it to add sales order controller as a new

13:17 controller because while we have the tables for sales orders,

13:20 we should not have any operational controllers in the application itself.

13:24 So we're doing application modernization as part of this migration project.

13:29 And then we uh finalize our container strategy design.

13:33 This is where you actually can iterate on the process.

13:37 uh Initially, it was uh separating customers and orders,

13:41 but because we uh we see that customers and orders

13:44 share the same partition key based on the access patterns.

13:47 We actually have uh benefit in NoSQL Cosmos DB,

13:52 combine them together uh and preserve atomic batch consistency

13:57 for create order plus patch order count in one transaction.

14:02 And we eliminate in complexity,

14:04 which require cross-container processors using change feed.

14:08 So we can see that there was design decision,

14:12 with Veridex, YWill, and a change feed combined.

14:15 And the final design is actually presented here.

14:17 So this is the final container layout where we

14:20 have customer orders container with partition key customer ID,

14:24 and then products container with partition key category ID.

14:27 Both have different dock types.

14:28 This is one of the best practices and benefits of Cosmos DB,

14:33 which allow you to store uh different entities,

14:36 ah which share the same partition key.

14:39 and discriminate them by document type

14:41 in the same container for efficiencies on application.

14:46 Um.

14:49 So let's continue.

14:50 So this is the final document model where we have customer ID ah as ID.

14:56 We're going to actually tell it

14:58 to preserve original IDs for backward compatibility.

15:01 But we're going to add prefix IDs for IDs

15:04 to maintain uniqueness for uh each customer ID.

15:07 And we're going to remove row ID from the processing.

15:10 So this schema X patterns is pretty

15:13 much continue with all the details, mapping columns.

15:16 You can see that row GUID is actually

15:18 excluded because We replaced it with Cosmos ID.

15:21 We denormalized it like nested addresses as they embedded JSON, ah et cetera.

15:28 Same thing for sales orders, similar pattern, continuous along with that.

15:37 uh Next thing is actually.

15:42 uh We've created the bicep files.

15:46 I already mentioned this.

15:48 It's pretty simple.

15:49 uh Bicep file will edit.

15:52 One of the benefits of Cosmos DB was bicep files.

15:54 We've replaced everything with entry ID and we simply grant you,

16:00 like for my demo, I'm granting two entry ID roles here.

16:07 A Cosmos DB operator role and Cosmos data contributor role.

16:10 to ensure that I can create containers and also

16:13 I can do data plan operations in Infraspace and then.

16:16 uh We, as part of the data migration,

16:23 we create data migration subfolder with converting data to a JSON file.

16:28 This is pretty much the processing of the data

16:32 for customers and also pre-processing data for sales orders here.

16:37 Let's go little further.

16:42 Yeah, this is one of the sales orders.

16:46 They also share the same customer ID partition key, but IDs or prefix order ID.

16:53 And very similar to products and product categories.

16:56 And those two files actually loaded to Cosmos

17:01 DB using the load to Cosmos DB Python script.

17:07 And this is the same thing you can actually telco pilot to convert into Again,

17:12 any ATL tools you plan to use for migration,

17:16 you can use the same logic to generate the migration scripts.

17:21 This is actually how it looks in Cosmos DB.

17:24 While the uh application conversion is processing,

17:27 we can quickly look on what's happening in Cosmos DB.

17:31 ah So my biceps script created a Cosmos DB account with following...

17:38 uh following database, adwkslt, with two containers,

17:43 customer orders and products, just like we've seen it created.

17:49 Those containers also have created custom index

17:52 policies based on all those access patterns,

17:56 which include paths, and then we exclude everything else.

18:00 And it also recognized that for some access patterns,

18:03 we need composite indexes based on type,

18:06 like last name, first name, for different order and...

18:09 ah capabilities.

18:11 So it's pretty smart and very similar to do for products.

18:15 ah is uh documents, examples already preloaded to Cosmos DB for our validation.

18:24 So we've pre-migrated the data, same documents for products.

18:27 ah And we have categories as well further down here.

18:37 And if we go back to our code, let's see where we are.

18:40 We are pretty close ah to finish.

18:45 Let's quickly watch, kind of like revert back, what it done with the code.

18:52 This is a prompt we submitted for final application changes.

18:58 You can see that it started reviewing the files and allies conversion plans.

19:03 When it got the full context, it's...

19:05 ah ah define what needs to be updated,

19:10 start updating with a project file, then went to update the...

19:14 ah document model documents for customer sales order products.

19:23 We write as a program files to update

19:26 the startup to change the F core to Cosmos DB.net.

19:29 um Created the new controller files.

19:34 um Looks like there was some errors in it.

19:40 It actually went ahead and uh find a different approach.

19:47 ah And finally, successful here.

19:52 I was waiting for me to accept.

19:55 This is where it's changing the layout.

19:58 Now it arrived to our goal one.

19:59 Build succeeded with zero errors.

20:01 means that we achieved the goal one.

20:02 Let's start with the application, start and validation.

20:06 So it started the application, home page returned 200 successful.

20:09 So it's actually, so it looks like it's troubleshooting some issues here.

20:19 And one of the issues it's reporting is actually related

20:23 to some limitations in serverless

20:25 to support the full functionality for deployment.

20:28 And it's just going through some troubleshooting cycles.

20:31 While it's doing, we can quickly review ah what it's done in the service.

20:40 So if we collapse our documentation a little bit, let's review.

20:48 the controllers.

20:49 this is, it updated the controllers with Cosmos DB actions.

20:58 Like you can see that updated Cosmos exceptions to get it

21:03 to catch the status codes from Cosmos DB ah for models.

21:08 It's pretty simple.

21:09 m Most of them are Similar, we've added some e-tagging for our JSON

21:18 property ID to replace and update models.

21:26 services are also pretty, like I think we look at it,

21:31 but this is the example of where it's

21:34 ah reusing the Cosmos client from the client builder,

21:39 getting the DB name, container name um from Cosmos client.

21:44 And then basically for each query definition,

21:49 basically defining Cosmos DB query, uh iterating on the results like here,

21:57 we get in the list and then ah

22:00 this is a pagination has more results, for example.

22:03 Here for product by ID,

22:05 this would be uh called what we call a point read in Cosmos DB.

22:09 We actually use in...

22:10 ah Container read item async where we supply an ID and a partition key.

22:19 This is a fastest way to read data in Cosmos DB because

22:23 partition key and ID always give you a unique pointer to a document.

22:26 You can see that it's point read,

22:30 what we call one RU for small documents and so on.

22:36 It updated the views based on changes we

22:40 submitted to the project and in the program itself.

22:46 You can see that it's adding the Singleton Cosmos Client

22:50 builder with serialized option ah for camel case and direct mode.

22:55 It's pretty simple.

22:57 And we are using the Entry ID for our connectivity, basically.

23:06 Let's see where we are with actual project.

23:15 All right.

23:15 Looks like our application is successfully

23:18 started and all the API checks validated.

23:21 um Let's quickly look at the application

23:24 itself to validate that everything is running.

23:27 um This is our application running on Cosmos DB.

23:33 You can see that we've updated the view

23:37 to have view links to all the main controllers.

23:41 We have categories.

23:42 We can actually look at the products.

23:44 We can look at the customers and sales orders.

23:47 ah If we want to see the details about the sales orders,

23:51 we can go inside and see the details.

23:53 So this pretty much concludes the demo part.

23:56 uh Let's go into final closing key takeaways.

24:05 As we look through the demo, I want to highlight a few important uh points

24:11 to consider when you use Copilot for migration modernization projects.

24:16 uh One thing that is important is structure your prompts as a pipeline.

24:21 uh Each step should be built on the output of the previous

24:25 one or consider multiple previous steps to feed into the next iteration.

24:29 And then let Copilot do automatic discovery and you act as a judge.

24:35 uh Second point, inject domain knowledge

24:39 the schema design step and review iterative needed.

24:42 ah Converting relational schema to NoSQL a lot

24:48 of times may require multiple ah iterations.

24:53 So use copilot uh prompts to create a first iteration and then be a judge

24:59 and a challenger to challenge it

25:02 to analyze and create alternatives and explain why.

25:05 And then if you feed the details, from the templates,

25:09 which is my next step is templates guide quality.

25:13 If you provide the real life value metrics

25:16 from your real application and access pattern details,

25:20 ah they will result in a better quality and consistent output with more

25:25 accurate conversion model and will count

25:28 for scalability risks and avoid over-engineering.

25:30 And the final uh detail to take home

25:33 is generate a plan before executing, review the plan.

25:37 ah As a checkpoint, before actual destructive rewrite,

25:41 it will save time and allow you to iterate quickly with less rework.

25:47 This is an example where we generate the prompt

25:50 6 before executing prompt 7 for actual application conversion.

25:54 You can find converted repository example and my prompt by prompt

26:01 instruction templates at aka.ms slash rdbms to Cosmos DB prompts.

26:06 A link it will...

26:08 link you to my sample repo in the document folder,

26:11 will find the templates files and prompt by prompt document sample.

26:16 Thank you for watching and happy coding.

Study with Looplines Download Captions Watch on YouTube