SharePoint Is NOT a Database: The Power Apps Lie
In this episode of the M365 Show, we unpack the most common Power Apps mistake in the Microsoft 365 ecosystem: assuming SharePoint is a “free database.” We break down why SharePoint lists look like a database, but architecturally behave like a file-centric collaboration layer—not a transactional data engine. From delegation limits to the infamous 2,000-record wall, we explain how apps built on SharePoint scale beautifully for a month… then collapse under load, concurrency, throttling and lookup chains. If you’ve ever heard “we’ll just use SharePoint for now,” this episode will save future performance pain. Learn what a real database is, how Dataverse and SQL handle indexing + relationships correctly, and why treating SharePoint like SQL is the fastest way to kill a Power App.
In today’s episode of the M365 Show Podcast, we break down one of the most expensive performance myths in the Power Platform world — the idea that SharePoint Lists are a “free database” for Power Apps.
Yes — SharePoint stores data.
No — that doesn’t make it a database.
This episode explains the false comfort of “free storage”, why citizen developers fall for it, and how apps that start simple eventually collapse under scale, delegation limits, concurrency collisions, and throttling.
In this episode you’ll learn:
• Why SharePoint ≠ a transactional engine
• What actually defines a REAL database (schema, relationships, indexing, concurrency)
• Why delegation walls (2,000+) destroy performance at scale
• Why your app slows down exponentially after a few thousand records
• How Dataverse + SQL handle relational logic correctly
• Why “it’s included in M365” is the worst architectural justification ever
Key takeaway
“SharePoint lists LOOK like a database — they’re not BUILT like one.”
SharePoint is an amazing content management & collaboration layer — not a high-speed relational back-end.
Dataverse & SQL are engines.
SharePoint is a filing cabinet.
Links
Become a supporter of this podcast:
https://www.spreaker.com/podcast/m365-show-podcast--6704921/support
Opening: The False Comfort of “Free Databases”You’ve heard this phrase before—casually dropped into Microsoft Teams calls with frightening confidence—“Oh, we’ll just use SharePoint as the database for our Power App.”And there it is. The modern cry of the overconfident citizen developer.This, right here, is the problem. People hear “data stored somewhere” and immediately conclude “database.” By that logic, your junk drawer is a supply chain management system.The confusion is forgivable, barely. SharePoint does hold data, and Power Apps can read it. But that does not make it a database any more than Excel becomes a server when you save two worksheets.Average users love the illusion. SharePoint lists look structured. They have columns and rows, fields and filters. And of course—it’s already included in Microsoft 365, so it must be good enough, right?Wrong. You’re about to see why the “free” database sitting in your tenant is a performance time bomb disguised as convenience.By the end, you’ll understand why Power Apps that begin with “just SharePoint” eventually die gasping under their own weight—and why treating it like SQL is the digital equivalent of trusting a filing cabinet to run an engine.Section 1: What a Database Actually IsLet’s reset the definitions before your app implodes. A proper database isn’t just a bucket that holds information. It’s a system built on architecture and logic. It has order, schema, indexing, relationships, and concurrency control—the invisible infrastructure that lets dozens or thousands of users read, write, and query your data without tripping over each other.SQL Server and Dataverse handle this beautifully. Schemas define the blueprint—every column type and constraint serves like support beams in a skyscraper. Indexes act as the elevator shafts that get you exactly where you need, fast. Relationships keep records consistent, ensuring that when one table sneezes, its related tables say “bless you” in perfect synchronization.Now compare that to SharePoint. SharePoint was not designed to manage transactions at scale. Its DNA is collaboration, version history, permissions, and file storage. It’s more like a glorified document librarian than a record-keeping accountant. It’s wonderful at organizing text, attachments, and metadata—but call it a database, and you might as well call your filing cabinet a “data processing engine.”Real databases think in joins, referential integrity, and execution plans. SharePoint thinks in lists, permissions, and column choices written by someone who definitely didn’t study relational theory. It’s a web layer optimized for people, not for queries.Here’s where the Power Apps confusion begins. The app happily connects to SharePoint through an OData connector. You can create forms, galleries, and dashboards. On the surface, everything looks professional. The danger is invisible—until your app grows.I once met a department that proudly built their internal CRM entirely on top of four SharePoint lists. It worked beautifully—for a month. Then came the fifth thousand record. Suddenly the app stuttered, screens froze, and every gallery took half a minute to load. Their users thought the problem was “bad Wi‑Fi.” It wasn’t Wi‑Fi. It was physics. SharePoint was trying to impersonate a relational database.The truth? Power Apps can connect to SharePoint, but that’s all it does—connect. It borrows the data source, but it doesn’t make SharePoint any smarter. There’s no hidden engine under the surface waiting to optimize your queries.Imagine trying to race with a car built from bicycle parts. Sure, it has wheels. It moves. But once you hit highway speeds, bolts start flying. The handlebars—the list structure—were never designed to steer that kind of load.Dataverse, in contrast, is a proper engine. It’s transactional, relational, optimized for delegation, and built for Power Platform from the ground up. It follows database logic, not just storage logic. That’s the difference between structured speed and unstructured sprawl.SharePoint has indexing—but limited. It has lookup columns—but no genuine referential constraints. It allows multiple users—but not graceful concurrency handling. You can write to it, but if three users edit the same record at once, one loses. Usually the intern.Essentially, a database enforces integrity while SharePoint hopes for good behavior. SQL refuses to accept invalid relationships. SharePoint accepts everything, smiles politely, and breaks quietly months later.If this still feels theoretical, don’t worry. Scale will make it painfully real. Because while architecture can be ignored for a while, performance cannot. And as your user base grows, your “database” made from friendly SharePoint lists will groan like a spreadsheet with delusions of grandeur.The next part is where the collapse begins: Microsoft’s shiny number—30 million items—and the cruel joke hiding behind it. Let’s talk about scale, the silent killer of every Power App that mistook convenience for capability.Section 2: The Scale MythMicrosoft loves big numbers. Nothing sells confidence like a glossy documentation page claiming your SharePoint list can hold—wait for it—thirty million items. Sounds impressive, doesn’t it? Thirty million entries! You could store the payroll history of an empire. The problem is that the number is marketing, not math. That limit describes what SharePoint can physically contain, not what it can functionally handle. It’s like saying a washing machine can technically fit ten bowling balls. True. Until you press start.In reality, the moment those lists creep beyond a few thousand records, Power Apps begins its slow descent into misery. Buttons take seconds to respond. Galleries forget how to scroll smoothly. You click “Filter,” and the spinning dots start an existential performance art piece. By ten thousand records, it feels like wading through syrup. Beyond that, you’re practically time‑traveling—all the way back to dial‑up.The core culprit here is a polite little concept called delegation. It’s Power Apps’ way of saying, “I can’t handle that query locally, so I’ll ask the data source to compute it for me.” SharePoint, however, isn’t fluent in that language. Its delegation capabilities are minimal. Translation: anything outside a small set of filter and sort operations is pulled locally. The data comes down the wire, record by record, so your client device ends up doing the heavy lifting a real database engine would have done in milliseconds. You built an enterprise app, and now every user’s laptop is its database server. Congratulations.The infamous 2,000‑item delegation wall isn’t a myth—it’s a design constraint. Unless you use creative (and usually fragile) pagination workarounds, Power Apps simply refuses to process more. You can raise that ceiling a little with clever queries, but eventually the data set expands faster than the platform can pretend nothing’s wrong. Even if you index your columns—the supposed magic trick—things only improve marginally. Like upgrading a rubber band with a thicker rubber band.Microsoft’s documentation hints that indexing can let you manage up to around 25,000 records if you’re “careful.” Translation: it will technically work while producing the user experience of a PowerPoint slideshow transmitted over carrier pigeons. The indexes prevent total collapse but can’t change the fact that SharePoint stores data in what is essentially a flattened web table. Each query becomes a request for a giant JSON blob, parsed piece by piece. SQL or Dataverse, by contrast, sends back neat pre‑processed chunks of matching rows. SharePoint just hands you everything and says, “Good luck sorting it.”Every extra thousand records adds latency. It’s not linear—it’s exponential. One thousand rows? Acceptable. Ten thousand? Noticeable lag. Twenty thousand? Every gallery becomes a meditation exercise. Users start clicking twice, thinking their devices froze, which of course triggers double updates and conflicting writes. That’s when someone suggests “maybe we should rebuild this in Excel,” and the circle of bad decisions completes itself.Using SharePoint as a back‑end at scale is like powering a data center with AA batteries. Each small operation works, barely. But time and concurrency amplify the load until the whole thing starts coughing. The connectors try to fetch data while maintaining security context, evaluating filters, and managing throttling—all over cloud HTTP calls that multiply faster than your patience decreases. Meanwhile, Dataverse or SQL would be compressing, caching, and delegating queries natively. SharePoint’s response to that level of complexity? A polite shrug followed by a timeout.And don’t forget throttling. Once you exceed certain thresholds in Office 365, SharePoint starts limiting the number of requests per user per minute. It doesn’t warn you nicely—it simply refuses to serve data for a few seconds. Multiply that delay by hundreds of active users, and you’ve turned your business app into a queue simulator. Remember: throttling isn’t failure; it’s SharePoint’s polite way of begging you to stop abusing it.Now, let’s add relationships into the mix. Many creators think scaling problems vanish if they just break lists apart. “We’ll have one for Customers, one for Orders, one for Products, and link them.” Fascinating optimism. Each lookup between those lists triggers its own set of API calls. So, when you open a single record, you’re actually launching dozens of hidden queries. Multiply that by hundreds of users, and your app starts behaving like a chain smoker climbing stairs. Power Apps will valiantly try to batch requests, but latency stacks faster than performance optimizers can patch it.What’s particularly cruel is how invisible the decay feels at first. Everything seems fine—until the day new data pushes you past that unseen tipping point. Then screens freeze. Connections fail silently. Eventually, developers start layer
Become a supporter of this podcast: https://www.spreaker.com/podcast/m365-show-podcast--6704921/support.
Follow us on:
LInkedIn
Substack
WEBVTT
1
00:00:00.080 --> 00:00:03.120
2
00:00:03.120 --> 00:00:06.759
3
00:00:06.799 --> 00:00:09.160
4
00:00:09.400 --> 00:00:12.199
5
00:00:12.519 --> 00:00:14.839
6
00:00:14.880 --> 00:00:18.719
7
00:00:18.800 --> 00:00:21.640
8
00:00:21.719 --> 00:00:25.239
9
00:00:25.280 --> 00:00:27.600
10
00:00:27.640 --> 00:00:30.480
11
00:00:30.559 --> 00:00:33.799
12
00:00:33.799 --> 00:00:36.640
13
00:00:36.679 --> 00:00:39.200
14
00:00:39.280 --> 00:00:41.880
15
00:00:41.880 --> 00:00:44.240
16
00:00:44.240 --> 00:00:47.679
17
00:00:47.719 --> 00:00:50.960
18
00:00:51.000 --> 00:00:53.799
19
00:00:53.880 --> 00:00:56.479
20
00:00:56.520 --> 00:00:59.759
21
00:01:00.079 --> 00:01:03.159
22
00:01:03.240 --> 00:01:05.840
23
00:01:05.879 --> 00:01:10.799
24
00:01:10.840 --> 00:01:14.439
25
00:01:14.480 --> 00:01:17.719
26
00:01:17.760 --> 00:01:20.840
27
00:01:20.879 --> 00:01:24.280
28
00:01:24.359 --> 00:01:27.640
29
00:01:27.719 --> 00:01:30.200
30
00:01:30.400 --> 00:01:34.920
31
00:01:35.280 --> 00:01:38.840
32
00:01:38.879 --> 00:01:41.680
33
00:01:41.680 --> 00:01:45.640
34
00:01:45.640 --> 00:01:48.480
35
00:01:48.519 --> 00:01:51.840
36
00:01:51.840 --> 00:01:54.760
37
00:01:54.840 --> 00:01:57.840
38
00:01:58.120 --> 00:02:01.879
39
00:02:02.040 --> 00:02:05.439
40
00:02:05.480 --> 00:02:08.599
41
00:02:08.680 --> 00:02:11.520
42
00:02:11.520 --> 00:02:15.039
43
00:02:15.039 --> 00:02:18.080
44
00:02:18.120 --> 00:02:21.120
45
00:02:21.319 --> 00:02:23.800
46
00:02:23.919 --> 00:02:26.800
47
00:02:26.800 --> 00:02:30.039
48
00:02:30.039 --> 00:02:33.719
49
00:02:33.719 --> 00:02:36.240
50
00:02:36.319 --> 00:02:39.360
51
00:02:39.400 --> 00:02:42.280
52
00:02:42.280 --> 00:02:46.000
53
00:02:46.000 --> 00:02:48.439
54
00:02:48.479 --> 00:02:51.039
55
00:02:51.039 --> 00:02:54.199
56
00:02:54.199 --> 00:02:56.400
57
00:02:56.479 --> 00:02:58.919
58
00:02:59.000 --> 00:03:02.879
59
00:03:03.159 --> 00:03:06.000
60
00:03:06.120 --> 00:03:09.759
61
00:03:09.759 --> 00:03:12.719
62
00:03:12.840 --> 00:03:16.199
63
00:03:16.240 --> 00:03:20.319
64
00:03:20.439 --> 00:03:23.360
65
00:03:23.400 --> 00:03:27.960
66
00:03:28.439 --> 00:03:30.280
67
00:03:30.319 --> 00:03:35.159
68
00:03:35.280 --> 00:03:39.039
69
00:03:39.159 --> 00:03:44.000
70
00:03:44.199 --> 00:03:47.520
71
00:03:47.560 --> 00:03:50.400
72
00:03:50.479 --> 00:03:53.159
73
00:03:53.199 --> 00:03:56.080
74
00:03:56.120 --> 00:03:59.840
75
00:04:00.400 --> 00:04:03.560
76
00:04:03.639 --> 00:04:07.000
77
00:04:07.159 --> 00:04:09.919
78
00:04:09.960 --> 00:04:14.039
79
00:04:14.120 --> 00:04:17.839
80
00:04:17.959 --> 00:04:20.879
81
00:04:20.959 --> 00:04:24.279
82
00:04:24.519 --> 00:04:26.480
83
00:04:26.519 --> 00:04:29.000
84
00:04:29.279 --> 00:04:32.600
85
00:04:32.720 --> 00:04:35.839
86
00:04:35.879 --> 00:04:39.319
87
00:04:39.360 --> 00:04:42.160
88
00:04:42.160 --> 00:04:45.199
89
00:04:45.240 --> 00:04:48.680
90
00:04:48.720 --> 00:04:51.600
91
00:04:51.600 --> 00:04:54.879
92
00:04:54.879 --> 00:04:57.800
93
00:04:57.800 --> 00:05:00.560
94
00:05:00.600 --> 00:05:03.399
95
00:05:03.519 --> 00:05:06.079
96
00:05:06.160 --> 00:05:08.680
97
00:05:08.720 --> 00:05:11.959
98
00:05:12.079 --> 00:05:15.839
99
00:05:15.839 --> 00:05:18.600
100
00:05:18.680 --> 00:05:20.959
101
00:05:20.959 --> 00:05:23.199
102
00:05:23.279 --> 00:05:26.040
103
00:05:26.160 --> 00:05:30.399
104
00:05:31.759 --> 00:05:34.519
105
00:05:34.600 --> 00:05:38.040
106
00:05:38.079 --> 00:05:42.360
107
00:05:42.480 --> 00:05:44.639
108
00:05:44.839 --> 00:05:47.600
109
00:05:47.600 --> 00:05:50.240
110
00:05:50.279 --> 00:05:53.879
111
00:05:53.920 --> 00:05:57.040
112
00:05:57.160 --> 00:05:59.240
113
00:05:59.240 --> 00:06:02.920
114
00:06:02.920 --> 00:06:06.240
115
00:06:06.240 --> 00:06:10.160
116
00:06:10.199 --> 00:06:12.639
117
00:06:12.680 --> 00:06:15.680
118
00:06:15.720 --> 00:06:18.600
119
00:06:19.000 --> 00:06:21.959
120
00:06:22.000 --> 00:06:25.120
121
00:06:25.120 --> 00:06:28.040
122
00:06:28.079 --> 00:06:32.639
123
00:06:33.120 --> 00:06:36.439
124
00:06:36.480 --> 00:06:40.399
125
00:06:40.399 --> 00:06:43.399
126
00:06:43.439 --> 00:06:46.360
127
00:06:46.879 --> 00:06:50.160
128
00:06:50.160 --> 00:06:51.879
129
00:06:51.959 --> 00:06:55.560
130
00:06:55.839 --> 00:06:58.399
131
00:06:58.399 --> 00:07:01.240
132
00:07:01.279 --> 00:07:05.120
133
00:07:05.199 --> 00:07:09.560
134
00:07:09.680 --> 00:07:13.240
135
00:07:13.279 --> 00:07:16.720
136
00:07:16.879 --> 00:07:19.360
137
00:07:19.360 --> 00:07:22.519
138
00:07:22.600 --> 00:07:25.920
139
00:07:26.079 --> 00:07:28.800
140
00:07:28.879 --> 00:07:31.920
141
00:07:31.920 --> 00:07:34.560
142
00:07:34.560 --> 00:07:38.560
143
00:07:38.560 --> 00:07:40.879
144
00:07:40.959 --> 00:07:44.079
145
00:07:44.079 --> 00:07:46.759
146
00:07:46.800 --> 00:07:49.399
147
00:07:49.480 --> 00:07:53.040
148
00:07:53.199 --> 00:07:56.519
149
00:07:56.560 --> 00:07:59.680
150
00:08:00.040 --> 00:08:02.639
151
00:08:02.639 --> 00:08:06.240
152
00:08:06.319 --> 00:08:09.199
153
00:08:09.199 --> 00:08:12.680
154
00:08:12.680 --> 00:08:16.000
155
00:08:16.079 --> 00:08:18.959
156
00:08:19.240 --> 00:08:25.040
157
00:08:25.079 --> 00:08:29.000
158
00:08:29.040 --> 00:08:32.240
159
00:08:32.279 --> 00:08:34.679
160
00:08:34.759 --> 00:08:38.200
161
00:08:39.000 --> 00:08:42.600
162
00:08:42.679 --> 00:08:46.799
163
00:08:47.000 --> 00:08:51.639
164
00:08:51.840 --> 00:08:54.240
165
00:08:54.279 --> 00:08:57.559
166
00:08:57.600 --> 00:09:01.480
167
00:09:01.519 --> 00:09:04.279
168
00:09:04.480 --> 00:09:10.200
169
00:09:10.200 --> 00:09:14.440
170
00:09:14.480 --> 00:09:17.879
171
00:09:17.919 --> 00:09:19.919
172
00:09:19.960 --> 00:09:23.600
173
00:09:23.639 --> 00:09:26.639
174
00:09:26.679 --> 00:09:30.600
175
00:09:30.679 --> 00:09:33.960
176
00:09:34.000 --> 00:09:37.360
177
00:09:37.399 --> 00:09:40.120
178
00:09:40.159 --> 00:09:43.200
179
00:09:43.279 --> 00:09:46.840
180
00:09:46.919 --> 00:09:49.679
181
00:09:49.720 --> 00:09:52.919
182
00:09:52.960 --> 00:09:55.360
183
00:09:55.360 --> 00:09:58.799
184
00:09:58.799 --> 00:10:01.799
185
00:10:01.960 --> 00:10:04.279
186
00:10:04.279 --> 00:10:07.080
187
00:10:07.120 --> 00:10:10.240
188
00:10:10.279 --> 00:10:14.600
189
00:10:14.679 --> 00:10:17.639
190
00:10:17.759 --> 00:10:21.240
191
00:10:21.240 --> 00:10:24.519
192
00:10:24.639 --> 00:10:27.039
193
00:10:27.080 --> 00:10:31.639
194
00:10:31.720 --> 00:10:34.399
195
00:10:34.399 --> 00:10:37.519
196
00:10:37.559 --> 00:10:40.759
197
00:10:40.799 --> 00:10:43.240
198
00:10:43.320 --> 00:10:46.559
199
00:10:46.679 --> 00:10:50.480
200
00:10:51.039 --> 00:10:55.480
201
00:10:55.519 --> 00:10:58.279
202
00:10:58.759 --> 00:11:01.000
203
00:11:01.080 --> 00:11:03.960
204
00:11:04.000 --> 00:11:06.600
205
00:11:06.679 --> 00:11:09.960
206
00:11:09.960 --> 00:11:12.399
207
00:11:12.440 --> 00:11:15.639
208
00:11:15.639 --> 00:11:18.720
209
00:11:18.759 --> 00:11:21.720
210
00:11:21.759 --> 00:11:24.600
211
00:11:24.639 --> 00:11:27.600
212
00:11:27.600 --> 00:11:30.080
213
00:11:30.120 --> 00:11:33.240
214
00:11:33.279 --> 00:11:36.039
215
00:11:36.120 --> 00:11:39.440
216
00:11:39.480 --> 00:11:42.879
217
00:11:42.960 --> 00:11:46.000
218
00:11:46.039 --> 00:11:49.679
219
00:11:49.679 --> 00:11:53.440
220
00:11:53.440 --> 00:11:56.120
221
00:11:56.120 --> 00:11:58.240
222
00:11:58.240 --> 00:12:02.840
223
00:12:03.399 --> 00:12:07.159
224
00:12:07.240 --> 00:12:11.200
225
00:12:11.519 --> 00:12:14.600
226
00:12:14.639 --> 00:12:18.240
227
00:12:18.279 --> 00:12:20.440
228
00:12:20.480 --> 00:12:24.240
229
00:12:24.240 --> 00:12:27.759
230
00:12:27.799 --> 00:12:30.279
231
00:12:30.279 --> 00:12:32.919
232
00:12:32.919 --> 00:12:37.080
233
00:12:37.440 --> 00:12:40.840
234
00:12:40.879 --> 00:12:43.639
235
00:12:43.720 --> 00:12:48.679
236
00:12:48.679 --> 00:12:51.759
237
00:12:51.840 --> 00:12:55.279
238
00:12:55.639 --> 00:12:58.240