Data Bear

Lessons from a Fabric App demo build

Filters

We built a Fabric App demo. Here’s what it would take to make it production-grade, and why a demo isn’t there yet

A Fabric App demo can be built fast, especially with AI assistance. A working page that reads a semantic model, renders like a polished web app and does something a report cannot, that can exist in days. The speed is real and it is genuinely useful for discovery.

It is also the trap. Because the thing that makes a demo fast to build is precisely the set of questions it lets you skip: who owns this, who reviews changes to it, what happens when the model underneath it shifts, who gets the call when a user says a number looks wrong. A Power BI report answers most of those questions by convention, because the platform and your organisation already have a shape for it. A Fabric App is a custom web application on top of your data, and it answers none of them by default. You do.

We built a finance Fabric App demo (a dashboard plus forecast writeback) and, because we build these for clients, we were deliberate about the line between “demo-grade” and “production-grade” from the start. This post is about that line: the governance and maintainability work a Fabric App needs before it is more than a demo, drawn from the actual guardrails we put around ours and the specific reasons a demo is not production even when it looks finished.

The short version: the demo is the easy 90% of the effort and the last 10% is most of the risk. Everything below is that last 10%.

The visible part is not the quality signal

The first thing anyone notices about a Fabric App is the interface: custom visuals, app-style navigation, a guided experience instead of a report canvas full of slicers. That is the part that gets attention in a demo, and it is the part that matters least to whether the app can be trusted.

The quality signal sits underneath, and it is mostly invisible in a demo: can the semantic model reliably answer the questions the app asks, are the queries against it validated, is there a clear owner for the app code and a separate clear owner for the model, and is there a defined path for a change to reach users without breaking them. A demo can score perfectly on look and zero on every one of those, and from the outside the two are indistinguishable. That gap between what a demo shows and what production needs is the whole subject here.

fabric app

At the time of writing this, July 2026, Fabric Apps are still in preview.

Fabric Apps Dashboard

The Fabric App landing page. The interface is the visible layer. Whether the app is production-grade is decided by things this screenshot cannot show.

Ownership is two questions, not one

The instinct is to ask “who owns the app?” In a Fabric App there are two owners and they are usually not the same person, which is exactly the complication a report does not have.

There is the app code: the React, the TypeScript, the queries, the layout, the deployment. And there is the semantic model: the tables, the relationships, the DAX measures, the security rules. In our build these are cleanly separate concerns, and the separation is not incidental, it is structural. The model’s fact and dimension tables are read-only to the app. The app reads them through the data service and cannot write to them. Anything the app needs to persist (in our case a forecast adjustment) goes to a separate writeable store, never into the model’s tables.

That read-only boundary is the single most clarifying fact for ownership. It means the model team can own the model and the app team can own the app without stepping on each other, because the app physically cannot alter the model’s data. But it also means a change on either side of the boundary can break the other, and nobody owns the boundary itself unless you deliberately assign it. The question production forces that a demo lets you dodge is: when a measure definition changes in the model, who is responsible for checking that the app still reads it correctly? In a demo, the answer is “the same person built both, so nobody had to ask.” In production, that person has moved on and the question is live.

Deployment is where a demo quietly becomes production

The most dangerous moment in a Fabric App’s life is the one nobody notices: the deploy where a prototype starts being used for real. Nothing technical marks it. The app that was a demo yesterday is load-bearing today, and if you have not built the discipline in advance, you build it after something has already gone wrong.

We put the controls in before the app was worth protecting, which is the only time it is cheap to do. Concretely, deployment runs through a single choke point: exactly one script is permitted to deploy, and it refuses to run unless several preconditions hold. It checks it is on the working branch and not the protected one. It checks the git tree is clean. It checks the deploy target is the one specific workspace and item it is allowed to touch, and refuses any other target outright. It logs every deploy. No deploy can happen any other way, and that is enforced, not merely requested.

The reason for a single guarded path is that ad hoc deploys are how demos rot into production without anyone deciding they should. If any developer can push the live app from their machine on a whim, there is no moment where a change is reviewed, and “it worked on my screen” becomes the release process. Funnelling every deploy through one gate creates the checkpoint that a report gets for free from its publishing model.

Alongside that, the main branch is protected: changes reach it only through review, never by a direct push, and several categories of action are blocked outright by automated guards rather than left to good intentions. Destructive operations against the data, edits to secret and credential files, and any write while on the protected branch are all refused at the tooling level. The principle we followed throughout: a rule that depends on everyone remembering it is not a control, it is a hope. If it matters, it should be impossible to violate by accident, not merely discouraged.

fabric workspace

fabric workspace

One guarded deployment path, a protected main branch, review before release. The controls a report inherits by convention, an app has to be given.

Secrets and auth: the boundary a script cannot cross

Here is a concrete production consideration that a demo surfaces in an awkward way, and it is worth stating plainly because it caught us out before we understood it.

The credentials the app needs to reach its data live in environment and configuration files that must never enter version control and must never be edited by an automated process. We enforced that with a hard guard: the build tooling is blocked from touching those files at all, with no exception path. Any change to them is a deliberate human edit in a separate session, and the files themselves are kept out of the repository and backed up separately. That is ordinary secure practice, but a Fabric App makes it your responsibility explicitly, where a report keeps it inside the platform.

The sharper, less obvious one: the app’s writes to its data store run under Fabric’s embedded authentication, which is tied to the signed-in user session inside the running app. A command-line or automated process cannot complete that authentication. It is not awkward, it is structurally impossible. For us that meant certain operations, seeding data, verifying what was written, can only happen as actions a signed-in human takes inside the deployed app, never as a script.

This matters for production planning far beyond the demo, because it dictates what can and cannot be automated in the app’s operations. If your maintenance plan assumes you can script the app’s data setup or run automated checks that write to its store, embedded auth says otherwise, and you need to know that at design time, not when you are trying to build a nightly job that cannot authenticate. Classify the operations that are structurally human-in-the-app from the start.

The demo will lie to you about maintainability in one specific way

A demo runs on a machine where the person who built it is present, the model has not changed since, and every dependency is exactly as it was. Production is defined by the absence of all three. The maintainability questions are the ones the demo conditions hide:

What happens when the model schema changes? A renamed column or a redefined measure that the app reads will not announce itself, the app will keep rendering, possibly with wrong numbers, exactly the way our own headline figure once read plausibly while being wrong. In production you need a way to catch that a model change has desynchronised the app, which means tests over the app’s important data journeys that run against the real deployed app, not just the developer’s confidence.

What happens when a user reports a number that looks wrong? In a demo, the builder investigates. In production, someone has to be able to trace a displayed number back through the query, to the measure, to the model, and that someone needs to exist and know the path. If ownership is unclear (the two-owner problem above), this is where it bites.

What is the rollback plan? A demo has none because it does not need one. A production app needs a defined way back to the last good state when a deploy goes wrong, and for an app that writes data, that plan has to account for the data written since, not just the code.

None of these are exotic. They are the standard concerns of running software, and that is the point: a Fabric App is software, and the demo is the one phase where you are allowed to pretend it is not.

Match the governance to the risk, and sometimes that means not building an app

The weight of everything above should scale with what the app is for. A throwaway internal demo needs almost none of it. An app that finance or operations leaders rely on needs most of it, and that starts to look like software delivery: version control, clear ownership on both sides of the model boundary, validated queries, tested user journeys, reviewed permissions, a rollback plan.

Which leads to the honest conclusion, the same one we reach on every one of these builds. Not every report should become a Fabric App. If the deliverable is something people read and explore, a Power BI report is faster to build, cheaper to maintain, and comes with an ownership and governance model your organisation already understands. The app earns its governance cost only when it does something a report fundamentally cannot, and even then the cost is real and should be counted before you start, not discovered after the demo has quietly become the thing everyone depends on.

We built the controls into our demo not because a demo needs them, but because the distance between a demo that has them and one that does not is exactly the distance between something you can put in front of a client and something you can hand to a client. That distance is the work. It is mostly invisible, it is almost all in the last stretch, and it is the part worth asking about before anyone is impressed by the interface.

To learn more about Microsoft Fabric and how we can help with Fabric Apps, see our Microsoft Fabric page.