If you’ve been building apps on SharePoint lists for a while, there comes a point where you start hitting walls — performance, security roles, relationships between tables, or just the general feeling that you’ve outgrown lists. That’s usually when Dataverse starts looking very attractive.
I’ve been through this migration more than once, and in this tutorial, I’ll walk you through exactly how to move your SharePoint Online list data into Dataverse. I’ll cover three methods so you can pick the one that best fits your situation.
Why Move from SharePoint Lists to Dataverse?
Before we get into the how, let me quickly explain why you’d want to do this in the first place.
SharePoint lists are great for simple scenarios — tracking tasks, logging requests, storing basic data. But they have limits:
- No real relationships — you can use lookup columns, but it’s not true relational data
- Limited row capacity — performance degrades noticeably past 5,000 items (the list view threshold)
- Weak security model — you can control access at the list level, but fine-grained, row-level security is painful to implement
- No server-side business logic — business rules, calculated rollups, and validations are hard to enforce
- Not ideal for model-driven apps — if you want to build enterprise-grade apps in Power Apps, Dataverse is the right foundation
Dataverse solves all of these. You get proper table relationships, row-level security, server-side business rules, and native support for model-driven Power Apps. Once you migrate, you’ll also unlock full Copilot Studio integration and better AI features across the Power Platform.
What You Need Before You Start
Let me save you some frustration. Before you begin the migration, make sure you have:
- A Power Apps environment — you need at least an environment with Dataverse enabled (not just Dataverse for Teams)
- The right permissions — you need the Environment Maker role or higher, plus write access to Dataverse
- Your SharePoint site URL handy — you’ll need it in every method
- A clean, well-structured list — if your SharePoint list has messy data, duplicate columns, or inconsistent values, clean it up first. Garbage in, garbage out.
- A Microsoft 365 or Power Platform license that includes Dataverse storage
Also, take a few minutes to map out your SharePoint columns to their Dataverse equivalents. Text columns map easily, but things like Person fields, Lookup columns, and Managed Metadata need special handling. I’ll flag those as we go.
Migrate SharePoint Online List to Dataverse
Here, I will show you two ways to migrate a SharePoint list to Dataverse, so you can choose the one that best suits your availability.
Method 1: Use “Create with SharePoint List” (The Quickest Way)
Microsoft added a really slick feature to Power Apps that lets you import a SharePoint list and create a Dataverse table—and a canvas app—in one go. If you’re starting fresh and just want to get your data into Dataverse quickly, this is the method I’d use first.
For this method i am using the Training Programs SharePoint list:

Here’s how to do it:
- Go to make.powerapps.com and make sure you’re in the right environment
- From the left-hand menu, select Tables.
- Select Create with SharePoint List

Note:
This is not the only way to reach this screen. There is another way: go to Apps in the left-hand menu, then click + New app. From the dropdown, select Start with data → Create new tables → Import a SharePoint list.
- Choose an existing SharePoint connection or create a new one
- Enter your SharePoint site URL (e.g.,
https://yourorg.sharepoint.com/sites/HR) - Pick the list you want to migrate from the dropdown

- You’ll see a preview of your table schema — review the column names and data types
- Make any edits you need (rename columns, change data types, remove columns you don’t want)
- Click Save and exit

Power Apps will do two things at once: create a Dataverse table based on your schema, and spin up a responsive canvas app using that table. It uploads the first 20 rows immediately so you can start working, and loads the remaining data in the background.
A note on Copilot: If Copilot is enabled in your environment, it will automatically suggest better data types for your columns. For example, if a column contains email-formatted text, Copilot will suggest mapping it as an email type rather than plain text. It also auto-populates choices for choice columns. This is surprisingly useful — I’d say it gets it right about 80% of the time, and the remaining 20% is easy to fix manually.
Limitations of this method:
- It works best for simple to medium-complexity lists
- Complex column types like Person/Group fields and multi-value lookups may need cleanup after import
- You can’t map to an existing Dataverse table — it always creates a new one
Method 2: Use Dataflows (The Most Reliable Method)
This is my go-to method for most real-world migrations, especially when you have a large list, complex column types, or you want to migrate data into an existing Dataverse table.
Dataflows use Power Query under the hood, which means you can transform, filter, and reshape your data before it lands in Dataverse. You have full control.
Step 1: Create a New Dataflow
- Log in to make.powerapps.com
- In the left navigation, click More if needed, then select Dataflows
- Click + New dataflow and give it a name (e.g., “HR Requests Migration”)
- On the data source screen, scroll down and select SharePoint Online List

Step 2: Connect to Your SharePoint List
- Enter your SharePoint site URL and click Next
- Choose Organizational account as the authentication method and sign in
- Click Next

- You’ll see all the lists available on that site — check the one you want to migrate.
- Click on Transform data.

Step 3: Clean Up Your Data in Power Query
This is where Dataflows shine. You’re now inside the Power Query editor, and you can see all your SharePoint columns — including a bunch of internal system columns you don’t need.
Here’s what I typically do:
- Remove system columns you don’t need: columns like _UIVersionString, FileSystemObjectType, ServerRedirectedEmbedUrl — select them, right-click, and choose Remove columns
- Expand complex columns: Person/Group columns in SharePoint come in as records. Click the expand icon next to those columns and choose the field you actually want — usually
Emailfor Person fields - Handle Lookup columns: Lookup columns are also returned as records. Expand them and extract the
Value(the display text) or theLookupId, depending on how your Dataverse table is set up - Change data types as needed: if a column should be a date but came in as text, change it here

Step 4: Set the Destination
- Click Next to get to the Map tables screen
- Under Load settings, choose:
- Load to new table if you want Dataflows to create the Dataverse table for you
- Load to existing table if you already have a table in Dataverse and just want to fill it with data
- If you chose an existing table, use the Column mapping section to match your SharePoint columns to your Dataverse columns — the system will auto-map what it can, and you fix the rest
- For the primary key, map it carefully. If you have a unique ID from SharePoint that you want to preserve, map it here.

Step 5: Publish and Monitor
- Click Publish — this kicks off the migration
- Once published, find your dataflow in the list, click the three dots menu, and select Show refresh history to check if it ran successfully
- You’ll see a timestamp, row count, and any errors

Pro tip: Dataflows can be set to refresh on a schedule. This is handy if you want to sync new SharePoint data periodically rather than doing a one-time migration. Once you’re satisfied, you can disable the schedule and treat it as a completed migration.
Method 3: Use Power Automate (Best for Attachments and Complex Records)
If your SharePoint list has attachments (file uploads stored against list items), neither of the above methods will handle those. This is where Power Automate comes in.
The idea is simple: you build a flow that reads every item from the SharePoint list, creates a corresponding record in Dataverse, and then attaches any files to that new record.
Ensure all columns in the SharePoint list are properly created in the Dataverse table.

The Basic Flow Structure
- Trigger: Manually triggered (or recurrence, if you’re doing this in batches)
- Action 1: Get items from SharePoint list (use pagination — set the top count to 100 or more and enable the Odata-skiptoken to loop through all items)

- Then add Apply to each item and provide the body/value from the dynamic content of the Get items.
- Inside the Apply to each add “Add a new row” and provide below:
| Field Name | Value to Provide | Why We Give This |
|---|---|---|
| Table name | Customer Requests | This is the Dataverse table where data will be stored |
| Request ID | RequestID (dynamic from SharePoint) | To uniquely identify each request and avoid duplicates |
| Customer Name | CustomerName | Stores the name of the customer from SharePoint |
| Request Details | RequestDetails | Stores full description/details of the request |
| Request Title | RequestTitle | Stores the short title/subject of the request |
| Status | if(…) expression | Converts SharePoint text status into Dataverse numeric value |

- Then add Get attachments for the current SharePoint item.

- For each attachment: Get the attachment content, then create a note/annotation in Dataverse linked to the new record.

Handling the 5,000+ item scenario: If your list has more than 5,000 items, use a Do Until loop with a skip index variable. Start at 0, pull 100 items at a time, process them, increment the skip counter by 100, and loop until you’ve processed everything.
Handling attachments specifically:
Get attachments (SharePoint) → item ID from current loop item
Apply to each attachment:
→ Get attachment content (SharePoint)
→ Create annotation (Dataverse)
- ObjectId: [Dataverse record ID you just created]
- ObjectTypeCode: [your table's type code]
- FileName: [attachment name]
- DocumentBody: [base64 encoded content]
- MimeType: [file type]
This method takes more time to build, but it’s the most complete migration you can do. Everything comes over — data, files, and all.
Handling the Tricky Column Types
Let me call out the columns that almost always cause problems during migration, and what to do about them.
Person/Group fields
SharePoint returns these as complex objects with DisplayName, Email, LookupId, and more. In Dataverse, you’ll typically have a Lookup to the systemuser table. The cleanest approach is to extract the email from the SharePoint output and then use a lookup in Power Query or Power Automate to find the matching Dataverse user record by email.
Lookup columns
In SharePoint, a lookup column points to another list. In Dataverse, the equivalent is a relationship between two tables. Before migrating, create the related Dataverse table first and migrate that data. Then, when migrating the parent list, use the LookupId from SharePoint to find the corresponding Dataverse row ID and set the relationship.
Multi-value lookup / multi-select choice
These are the messiest. A “multi-select people” or “multi-lookup” column in SharePoint doesn’t have a direct equivalent in Dataverse. You have a couple of options: flatten the values into a multi-select choice column, or create a proper many-to-many relationship table in Dataverse. The second option is more work upfront but much cleaner long-term.
Managed Metadata (Taxonomy fields)
Dataflows don’t handle these well. Your best bet is to treat them as text values during migration and then apply proper classifications in Dataverse afterward.
Attachments
As covered above, use Power Automate for these. Neither the “Create with SharePoint List” method nor Dataflows will migrate file attachments.
After the Migration: Things to Check
Once your data is in Dataverse, don’t just assume everything is fine. Here’s my post-migration checklist:
- Verify row counts — open your Dataverse table and count the rows. Compare with the SharePoint list item count.
- Check key columns — spot-check 10–20 records manually. Confirm that text, dates, choices, and lookup values all came through correctly.
- Test lookup/relationship columns — especially if you migrated related tables. Make sure the relationships are intact.
- Set up security roles — in Dataverse, access is controlled through security roles, not SharePoint permissions. Create or update roles to give the right users access to your table.
- Update your Power Apps — if you had a canvas app pointing at the SharePoint list, you’ll need to update the data source. In Power Apps Studio, remove the SharePoint connection and add the Dataverse table as the new data source. Then re-map your controls.
- Archive or retire the SharePoint list — once you’ve confirmed the migration is good, consider making the SharePoint list read-only or archiving it. Don’t delete it immediately — keep it around for a few weeks as a backup.
Which Method Should You Use?
Here’s a quick summary to help you decide:
| Your Situation | Best Method |
|---|---|
| Quick migration, new table, small/medium list | Create with SharePoint List (Method 1) |
| Large list, complex columns, loading to existing table | Dataflows (Method 2) |
| List has attachments / file uploads | Power Automate (Method 3) |
| Mix of all the above | Dataflows for data + Power Automate for attachments |
Common Mistakes to Avoid
I’ve seen these trip people up repeatedly:
- Skipping the schema review — always check your column types before publishing. A date that comes in as text won’t cause an error, but it’ll cause pain later.
- Not creating related tables first — if you have lookup relationships, migrate the referenced tables before the parent table. Otherwise, your lookup mappings will fail.
- Ignoring duplicate detection — Dataverse has duplicate detection rules, but they don’t prevent duplicates; they only flag them. If you run a dataflow twice by accident, you could end up with doubled data. Use unique alternate keys on your table to guard against this.
- Forgetting about security roles — after migration, users who had access to the SharePoint list won’t automatically have access to the Dataverse table. You need to explicitly assign security roles.
- Migrating everything at once — for large, complex lists, migrate in phases. Start with the simpler columns, validate, then add the complex ones.
You may like the following Power Automate tutorials:
- Add Rows to Excel in Power Automate
- Check Site Permissions in SharePoint Online
- Create an HTML Table in Power Automate
- Expense Reimbursement and Approval using Power Automate
- Create Calendar Events from a SharePoint list using Power Automate
Migrating from SharePoint to Dataverse is one of those things that sounds intimidating but is very manageable once you understand the options. Start with Method 1 for a quick proof-of-concept. Use Dataflows when you need more control. And bring in Power Automate when attachments or complex transformations are involved.

Hey! I’m Bijay Kumar, founder of SPGuides.com and a Microsoft Business Applications MVP (Power Automate, Power Apps). I launched this site in 2020 because I truly enjoy working with SharePoint, Power Platform, and SharePoint Framework (SPFx), and wanted to share that passion through step-by-step tutorials, guides, and training videos. My mission is to help you learn these technologies so you can utilize SharePoint, enhance productivity, and potentially build business solutions along the way.