A connectivity dialog in Fabric's API for GraphQL looks like a setup step. It quietly decides who needs permissions where, whether row-level security means anything, and whether your production API serves development data after every deployment.
Episode 34 • 2026-08-21 Duration: 8:36
A connectivity dialog in Fabric's API for GraphQL looks like a setup step. It quietly decides who needs permissions where, whether row-level security means anything, and whether your production API serves development data after every deployment.
The Fabric Friday video on this topic: https://youtu.be/IuGCxyLWzo0
AI-generated voices. Matthias — cloned voice. Fabia — designed AI co-host. See Matthias live on YouTube (Fabric Friday), at his meetups, and at conferences like FabCon.
Hosted by Matthias Falland — Microsoft Data Platform MVP and community architect behind the Fabric Periodic Table. New episodes every Friday.
Have an architecture decision you are wrestling with? DM Matthias on LinkedIn — find him as Matthias Falland. Three to five sentences about the decision, your team size, and your current stack. We anonymize before airing.
This podcast was generated by AI. Both voices are synthetic: Matthias is a cloned voice, Fabia is a designed AI co-host.
Brand design based on fabricperiodictable.com.
Architecture decisions for Microsoft Fabric. Anonymized real customer scenarios, cost realism, counter-arguments included. Weekly episodes aligned with Fabric Friday recordings.
The Radio Button That Decides Your Security Architecture
Episode 34 | 2026-08-21
Fabric Architecture Podcast | Hosted by Matthias Falland with AI co-host Fabia
---
[00:08] Fabia: A query runs. Rows come back. Under two hundred milliseconds. Everything looks healthy.
[00:13] Matthias: Except the rows are from dev.
[00:15] Fabia: And nobody finds out for weeks, because the credential's valid and the query never fails.
[00:21] Matthias: A connectivity setting did that?
[00:23] Fabia: A radio button, actually. Two options in a dialog that shows up once and looks like a setup step. Today we're unpacking what that choice quietly decides — about security, about deployment, and about whose data your production API serves.
[00:39] Matthias: API for GraphQL on Fabric.
[00:41] Fabia: When you create an API for GraphQL, Fabric reads your data source's schema, generates the GraphQL types, writes the resolvers, builds the CRUDL operations, and hands you a live endpoint. No code, no deployment.
[00:55] Matthias: How fast?
[00:55] Fabia: In the video, the first query came back in about a hundred and fifty milliseconds. From clicking new item to a working endpoint — under two minutes.
[01:05] Matthias: That's genuinely useful. The pattern I keep running into... an app team needs warehouse data, and the options are all terrible. Hand them a connection string — now your database's security surface includes their laptop. Build a backend — now you own a service. This skips both.
[01:24] Fabia: That's the pitch. Generated, Entra-authenticated, strongly typed. The caller decides what the response contains, which is why generation works at all.
[01:34] Matthias: Because a generated REST API would have to guess at useful endpoints.
[01:38] Fabia: GraphQL just describes the data and lets the caller ask. The type system IS the API design.
[01:44] Fabia: When you attach the first data source, you see two radio buttons. SSO or saved credentials. Microsoft's own line: once selected, these options are enforced for all data sources later added to the API. You can't mix them.
[01:59] Matthias: API-wide, permanent, applies to sources you haven't added yet.
[02:03] Fabia: SSO passes the caller's identity through to the data source. The data source sees who's actually asking, so row-level security still applies. The price — every caller needs permissions on the data source too.
[02:17] Matthias: And saved credentials?
[02:19] Fabia: One shared connection. The caller only needs Execute on the API. Nobody touches the data source directly.
[02:26] Matthias: Which is often exactly the requirement. You don't want an external app team holding warehouse credentials.
[02:33] Fabia: Right. But one connection means one set of permissions. Every caller sees the same rows. If your security model lives in RLS—
[02:41] Matthias: —this path erases it. Quietly. Because the query works.
[02:45] Fabia: Works perfectly. Returns rows. Just... the same rows for everyone.
[02:49] Fabia: I added columns to the table, updated the schema, and they are not there.
[02:55] Matthias: That's a pattern I keep hearing.
[02:57] Fabia: It's documented behavior. Microsoft states it plainly — GraphQL APIs in Fabric do not automatically detect schema changes in their underlying data sources. The API keeps the schema it captured when it was created or last refreshed.
[03:12] Matthias: Wait — the ninety-second generation... that was a one-time snapshot?
[03:17] Fabia: One-time. New tables get picked up when you update the schema. New columns on a table that's already attached? Community reports say that's unreliable.
[03:27] Matthias: So what's the fix?
[03:28] Fabia: Escalation ladder. Update the schema on the item. If the columns are still missing, remove the table and add it again. Worst case, delete and reattach the entire data source.
[03:40] Matthias: That's a lot of manual steps for something that felt automatic.
[03:44] Fabia: The schema's a contract with every client that's ever written a query against it. Auto-adopting a renamed column would break those clients without warning. Defensible — but it has to be known.
[03:57] Matthias: In the video, a column rename broke the query, and the error didn't even name the column.
[04:02] Fabia: Now here's where the radio button collects its debt. The video walks through four deployment paths. Only ONE autobinds — SSO with the source in the same workspace.
[04:13] Matthias: And the rest?
[04:14] Fabia: Saved credentials: the API deploys, the credential still points at dev, it's perfectly valid. Cross-workspace source, any auth: stays where it was. A SQL analytics endpoint that's a child of a parent item like a lakehouse: also stays.
[04:30] Matthias: So production returns dev data.
[04:32] Fabia: And nothing fails. The credential works. The query succeeds. Rows come back.
[04:37] Matthias: For how long?
[04:38] Fabia: Until somebody opens the API in the target environment and checks which data source it's actually attached to. Could be weeks.
[04:46] Matthias: That's the defect I'd lose sleep over. Every other failure mode in this feature announces itself — a missing column errors out, a depth violation gets rejected. This one returns rows. It succeeds. And nobody looks twice until the data doesn't match reality.
[05:04] Fabia: One more. Azure SQL Database requires saved credentials. So one external source forces that mode for every other source on the API.
[05:12] Matthias: One Azure SQL connection decides the deployment behavior of the whole endpoint.
[05:18] Matthias: Okay so... what's this thing actually sized for?
[05:21] Fabia: The page size defaults to a hundred items, and pagination stops at a hundred thousand total. A request gets a hundred seconds before it's cut. Read those together — this is sized for an application screen. A product catalog, a customer record.
[05:37] Matthias: And Microsoft says so?
[05:38] Fabia: Their note calls paginating past a hundred thousand an uncommon pattern in GraphQL. That's a polite way of saying use a pipeline.
[05:47] Matthias: What about the data source underneath? Does the API add overhead?
[05:51] Fabia: It inherits the data source's performance completely. A missing index in the warehouse becomes a slow API, and once it hits the hundred-second timeout it doesn't slow down — it fails. You're tuning the warehouse underneath.
[06:06] Matthias: So capacity cost is really the data source's bill wearing a GraphQL URL.
[06:11] Matthias: I want to defend saved credentials for a second. If the design intent is that callers should never hold data-source credentials — a partner integration, an external app team — then saved credentials is the architecture. You accept the manual binding check after every deploy, and you DOCUMENT why, because that's the trade.
[06:33] Fabia: Agreed. Saved credentials is a legitimate design. What makes it dangerous is choosing it without knowing what it costs you on deploy.
[06:42] Matthias: Write it down. In the architecture doc. With the reason.
[06:45] Fabia: Because the person debugging it in six months won't know a radio button caused it.
[06:51] Matthias: What about multi-source? In the video, one query hit two sources and came back as one response.
[06:57] Fabia: Fabric fans the requests out in parallel. One round trip, merged response. But no relationships across sources, no transactions, no guaranteed order between them.
[07:08] Matthias: If you need the join, do it upstream.
[07:10] Fabia: It's a federation of reads. Useful for assembling an app screen from two sources in one call. Just don't confuse it with a query engine.
[07:19] Fabia: So the risk inventory. Schema drift is a maintenance cost — predictable, schedulable. The autobinding gap is a correctness risk, and it's silent. One you calendar. The other you verify every single deploy.
[07:33] Matthias: And the decision that matters most isn't which source to connect. It's which radio button to click, before anyone opens the portal.
[07:42] Fabia: Pattern dictates platform. If the pattern is an app team needing typed, authenticated access to warehouse data, this is the right tool.
[07:51] Matthias: The thing that stays with me... a generated API feels managed. Like it's watching your source and keeping up.
[07:59] Fabia: The generation happened once. The tracking never started.
[08:03] Matthias: If you're staring at that dialog, or you've already deployed and you're not sure what your API's pointing at — DM me on LinkedIn, find me as Matthias Falland.
[08:13] Fabia: Show me the query pattern.
---
End of episode. ~08:15 estimated.