A SharePoint list can hold 30 million items and still feel broken at 3,000, or sit at 3,000 rows for years without a single problem. The 5,000-item list view threshold everyone quotes is the cheapest limit to work around: an indexed column and a filtered view let a big list keep working, as long as the filter returns fewer than 5,000 items. An index on its own does not make every view safe. What stops a list working as a database is lookups, concurrency, delegation and reporting, and none of them throw an error until the damage is done. They show up about eighteen months in. Checked by Balu at Kove (kove.nz). If you are an admin hitting these limits, SharePoint or Dataverse is the next read, or book a free 30-minute call if you are deciding what to move the list to.
| Limit | What it means in practice |
|---|---|
| List view threshold | 5,000 items per query. An indexed filter that returns fewer than 5,000 items keeps a bigger list usable. A filter that returns more still fails. |
| Indexed columns per list | 20, with SharePoint adding some automatically as a list grows |
| Lookup-type columns per view | 12, and Person/Group and Managed Metadata columns count toward it too |
| Absolute list size | Around 30 million items, though it slows well before that point |
| Power Apps non-delegable record limit | 500 by default, adjustable up to 2,000 |
| Power Automate Get items, paginated | Up to 100,000 with pagination on (5,000 on a Low-profile licence such as the one seeded with Microsoft 365), but still needs an indexed column for any filter past 5,000 |
If the list in question started life as a SQL Server or Access database, the limits below are the reason the home decision matters: moving a SQL Server database into Microsoft 365 and moving an Access database off the shared drive both use them as the SharePoint-or-Dataverse test.
If the answer is to move the list to Dataverse, the import method and its gotchas are on the Power Platform migration hub.
Before the list needs an app at all, Microsoft Lists, a Power App, or a Form sorts which of the three the register actually needs.
What the list view threshold does
The threshold blocks a query the moment it can't lean on an index, which is a different event from a list passing 5,000 rows. Filter a view by an indexed column, and as long as the filtered result comes back under 5,000 items, the query runs fine no matter how big the underlying list is. SharePoint Online now adds indexes automatically as a list grows, and a maker can add up to 20 manually. What still fails is an unfiltered "all items" view, or sorting and grouping on a column that isn't indexed, since neither can be pushed down to an index the way a filter can.
There's a separate, harder ceiling further out: a SharePoint list technically holds up to around 30 million items before you hit an absolute wall, and even that doesn't throw a clean error so much as get progressively slower to work with. Microsoft has no plans to raise the 5,000-item threshold itself, because it exists to protect a shared, multi-tenant environment. Building around it with indexes is the normal way of working.
Where SharePoint holds up better than its reputation
A job register, an asset list, a quote log, a simple approval queue: these are the things people build on SharePoint constantly, and for good reason. It's included in the Microsoft 365 seat a firm already pays for, gives sortable views, choice fields, people pickers and alerts out of the box, and Power Automate can watch it and fire off a reminder or a Teams message without anyone writing code. For a firm under 20 staff running a few thousand rows through a list, that's a solid, low-maintenance setup that will hold for years.
The built-in conflict handling is better than its reputation too. Two people editing the same item through the standard list form get a proper save conflict warning, not a silent overwrite, and version history makes recovering from a bad edit a few clicks, not a support ticket. Most of the dismissiveness aimed at SharePoint lists online is aimed at the SharePoint of a decade ago rather than the indexed, threshold-aware version most firms run today.
Limits beyond the list view threshold
None of the following show up when a list is small. All of them show up once it's doing real work.
Lookups and relationships
A single view can carry at most 12 lookup-type columns, and that cap includes Person/Group and Managed Metadata columns, plus the built-in Created By and Modified By fields. A list with a handful of people-picker columns and a couple of lookups to other lists blows past that limit faster than most people expect. SharePoint does have a real referential integrity feature, enforce relationship behaviour, letting a lookup column cascade or restrict a delete, but it needs an indexed, single-value lookup column and Manage Lists permission to turn on, caps cascade delete at 1,000 items per operation, and can't be enabled at all once the parent list has already passed the view threshold. The one feature meant to protect data integrity switches itself off exactly when a list is large enough to need it.
Concurrency
The built-in save-conflict warning only covers a person typing into the native list form. A flow, a Power App or an API call has no lock on the item. Unless the writer sends the item's version (the ETag, through the REST API), SharePoint just takes the last write, so two automated processes updating the same item close together can overwrite each other without an error. A job register touched by a handful of people a few times a day is fine. Put several automated writers on the same rows and you have a race condition.
Delegation limits
This is the limit that catches people out, because nothing fails loudly. Power Apps only pushes some functions down to SharePoint to run server-side, that's delegation. Anything it can't push down gets pulled back and processed locally instead, capped at 500 records by default and 2,000 at the outside if a maker raises it. Common non-delegable culprits against SharePoint include the Search() function, several nested Or() conditions across mixed column types, and sorting on certain computed or multi-value columns. The app still runs, the screen still looks fine, it's just quietly working off a slice of the list once that list grows past the cap, with nothing louder than a small warning icon most people learn to ignore. The Power Apps delegation limit post covers the default cap, the maximum you can raise it to, and why raising it does not fix the underlying problem.
Power Automate has the same mechanism under a different name. The Get items action defaults to a small batch, but pagination can be enabled to retrieve up to 100,000 items across batches (5,000 on a Low-profile licence such as the one seeded with Microsoft 365), still depending on an indexed column for any OData filter once the list passes 5,000 items. Filter on a column that isn't indexed and the flow gets refused at the same threshold that blocks a view.
Reporting
Power BI's SharePoint list connectors inherit the same ceilings rather than sidestepping them. A report built against an unfiltered "all items" query slows down or times out as the list grows, and there's no native join across two lists the way a relational data source handles it. It's workable with the newer connector, indexed OData filters, or landing data into a proper reporting table on a schedule instead of live-querying the list every refresh, but each of those is a deliberate engineering decision someone has to make and maintain. Whether the report belongs in Power BI at all is a separate call, worked through in Power BI against Excel for job profitability.
Patterns that buy you another year
Hitting one of these is not a reason to rebuild tomorrow. A few habits keep a list working well past the point where the threshold would otherwise start biting.
- Archive instead of accumulating. Move closed or old rows into a separate archive list on a schedule so the working list stays small and every index stays useful.
- Index the columns you filter or sort by, ahead of time. Waiting for the threshold error to tell you which column needs an index is the expensive way to find out.
- Route writes through one flow rather than several people, apps or scripts writing to the list directly, and set that flow's trigger concurrency to 1 so runs queue instead of overlapping. One flow on its own does not serialise anything, because flows run in parallel by default. This also does nothing about other apps or flows that still write to the list on their own.
- Make the default view a filtered, indexed one rather than "All items", so nobody triggers the threshold by accident just opening the list.
- Land data for reporting instead of live-querying it. A scheduled flow that copies rows into a purpose-built reporting table beats pointing Power BI straight at the list on every refresh.
Where Dataverse stops being optional
Watch what starts breaking, not the row count. Once relationship behaviour won't turn on because the list already ran past the view threshold, once a Power Apps screen is serving incomplete results from a non-delegable query no one flagged, or once two systems are racing to write the same item with no lock between them, the engineering time spent working around the platform starts costing more than moving the data would. That's the point where Dataverse pays for itself. SharePoint didn't get worse; the job outgrew what a list was designed to do.
The choice between the two platforms, including what Dataverse costs to license, is covered in SharePoint or Dataverse, ask this one question first. This post is only about which side of that line a specific list is already sitting on. If the move to Dataverse is the outcome, the next question is usually who can see what once it's there, which a worked example of Dataverse security roles covers. If you want that read on your own setup, that's most of what a Workflow Review covers.
Common questions
Does the SharePoint list view threshold apply to every query?
Not directly. The threshold blocks any query that can't use an index, and any indexed query that still returns more than 5,000 items. Filter a view on an indexed column and return fewer than 5,000 matching items and it runs fine however big the list is. SharePoint Online adds indexed columns automatically as a list grows, and a maker can add up to 20 manually. What still fails: sorting or grouping on a column that isn't indexed, or an unfiltered 'all items' view on a large list.
What is the real limit before a SharePoint list needs Dataverse?
The raw item count is rarely the trigger. The more common ones are a Power Apps screen quietly returning incomplete results because a query wasn't delegable and got capped at 500 or 2,000 records, a lookup relationship that won't enforce cascade or restrict delete because the list already passed the view threshold, or two systems writing to the same item with no lock between them. Any of those is a stronger signal than the number of rows.
Can Power Automate read more than 5,000 items from a SharePoint list?
Yes, with pagination turned on in the Get items action, which can retrieve up to 100,000 items across batches (5,000 on a Low-profile licence such as the one seeded with Microsoft 365). That still depends on an indexed column for any filter once the list is over 5,000 items. An OData filter on a non-indexed column gets refused at exactly the same threshold that blocks a view.

Is your list close to a real ceiling?
Free 30-minute call. I'll look at what the list does and who writes to it, then tell you whether it's fine, fixable or due for Dataverse.
Running a small firm and not sure this applies to you?
Send me what you have been quoted or what you plan to build, and I will give you a free written second opinion within two working days.