Tag: Power Apps

  • How to Run a Power Platform Licensing Audit Before You Ship

    How to Run a Power Platform Licensing Audit Before You Ship

    Checklist and connector diagram representing a power platform licensing audit before solution rollout

    A working app in your dev environment tells you nothing about what it costs to run for 300 people. I have watched a solution sail through UAT and then stall at rollout because one flow used an HTTP action, which flipped the whole thing premium, and suddenly every user needed a license nobody had budgeted. A structured power platform licensing audit takes an afternoon and catches this before procurement finds out the hard way. By the end of this walkthrough you will have a one-page map of every connector, every flow context, and every license gap in your solution.

    Step 1: Inventory Every Connector in the Solution

    Open the solution in make.powerapps.com, then go through each app under Details and check the connections list. Premium connectors carry the diamond Premium tag. SharePoint, Outlook, and Teams are standard. SQL Server, Dataverse, HTTP, and every custom connector are premium. I wrote a full walkthrough on building custom connectors, and the licensing footnote there matters: they are always premium, even when they wrap a free public API.

    Do not stop at the app level. Open every flow in the solution and read the actions, because the HTTP action never appears in the app’s connection list. Search the flow definitions for shared_http if you want to be thorough. This is where most surprises hide.

    Step 2: Trace the Context of Every Flow

    Licensing for flows depends on how they run, not what they do. A flow with a Power Apps (V2) trigger, packaged in the same solution as the app that calls it, runs in the context of that app and is covered by the app user’s Power Apps license. A scheduled or automated flow that runs standalone is not covered by anything. It needs Power Automate Premium on the owner, or a Process license attached to the flow itself.

    While you are here, check who owns each standalone flow. A flow running on the personal license of someone who leaves the organisation gets suspended when that license is removed. Move business-critical standalone flows to a service account or a Process license now, not after the first silent outage. If your flows rely on desktop automation, the selector strategy you choose also affects maintenance overhead — Selectors vs Image Recognition for Power Automate Desktop Flows covers the tradeoffs in detail.

    Step 3: Map Real Users to Real Licenses

    Pull the actual license assignments from the Microsoft 365 admin center, or with Get-MgUserLicenseDetail in PowerShell. Do not assume everyone has the same SKU. Mixed tenants are the norm, and the F3 users in the warehouse do not have what the E5 users in finance have.

    Then do the arithmetic. Per-app runs 5 dollars per user per app per month, Power Apps Premium runs 20 per user per month. The break-even sits at four apps per user. If your solution is app number one for a group of frontline workers, per-app wins. If the same 50 people will end up using five internal apps within a year, per-user is cheaper and you should say so before someone locks in the wrong plan. The Microsoft licensing overview has the current SKU details.

    Step 4: Check API Request Limits and Dataverse Capacity

    Licenses carry daily Power Platform request entitlements, and they are not generous at the low end. A Power Apps Premium user gets 40,000 requests per 24 hours. A user running on a seeded Microsoft 365 license gets 6,000. A flow that loops over 2,000 SharePoint items with three actions per item burns 6,000 requests in one run. The request limits documentation lists the allocations per SKU. Check your heaviest flow against the lowest entitlement in your user base.

    Dataverse capacity is the other quiet cost. If your solution logs every run or every submission into a Dataverse table, estimate table growth per month against your tenant’s storage allocation. Capacity overages show up on someone else’s budget line, which means they show up as an angry email. If you are also planning to add AI features to those Dataverse tables, the new Prompt Columns in Dataverse column type adds storage considerations of its own that are worth factoring in early.

    Step 5: Test With a Standard-Licensed Account

    Your dev account masks everything. It almost certainly has per-user premium plus an E5, so every connector works and every flow runs. Create a test user with exactly the license mix your real end users have, share the app with it, and run every screen and every flow path. If there is a gap, this account hits the premium license prompt immediately, and you fix it before rollout instead of during it. In my experience, this single step catches more licensing problems than the previous four combined, because it tests the actual runtime entitlement chain instead of your reading of the documentation.

    The Final State

    You now have a connector inventory with premium flags, a flow list with run contexts and owners, a user-to-license map with the per-app versus per-user math done, and a request limit sanity check. That one page is the difference between a rollout and a procurement escalation.

    The pitfall to watch: child flows. A standard-looking parent flow that calls a child flow containing one HTTP action inherits the premium requirement, and nothing in the app’s connection list will tell you. Open every child flow. Read every action. It takes ten minutes and it is the ten minutes people skip.

    Frequently Asked Questions

    How do I run a Power Platform licensing audit before deploying a solution?

    Start by inventorying every connector in your solution and flagging anything premium, such as SQL Server, Dataverse, HTTP, or custom connectors. Then trace how each flow runs, since standalone flows need separate licensing while flows triggered by a Power Apps canvas app can be covered by the user’s Power Apps license. Finally, pull real license assignments from the Microsoft 365 admin center to confirm every user has the right SKU before rollout.

    What is the difference between a standard and a premium connector in Power Platform?

    Standard connectors like SharePoint, Outlook, and Teams are included with most Power Platform licenses at no extra cost. Premium connectors, which include SQL Server, Dataverse, HTTP, and all custom connectors, require users to hold a Power Apps or Power Automate Premium license to use them.

    Why does a single HTTP action in a flow affect licensing for all my users?

    The HTTP action is a premium connector, so any flow that includes it requires the users who interact with it to hold a premium license. Because this action does not show up in an app’s connection list, it is easy to miss during a review and can trigger unexpected licensing costs at the point of deployment.

    When should I check who owns standalone flows in my Power Automate solution?

    You should verify flow ownership before any production rollout, not after an incident occurs. If a standalone flow runs on a personal license and that person leaves the organisation, the flow will be suspended when their license is removed, causing silent failures in business processes.

    About the author: Halilcan Soran is a Senior Business Analyst at Visa working on process optimization with Power Platform, RPA, and agentic AI. He previously led a 15-person team at Thomson Reuters, where the Power Automate solutions he built started his automation career. More about Halilcan · LinkedIn

  • Power Apps MCP Server Now Has Closed-Loop Learning Capabilities

    Power Apps MCP Server Now Has Closed-Loop Learning Capabilities

    Power Apps MCP server closed-loop learning diagram for enterprise agents

    Microsoft dropped the June 2026 Power Platform feature update on June 11, and the headline for me is Power Apps MCP server closed-loop learning for enterprise agents. Not a UX refresh. Not another connector. A real change in how agents get better after you ship them.

    The rest of the update is worth reading too, but this is the one I want to test against a real internal agent this week.

    What shipped on June 11

    The Power Apps MCP server now supports closed-loop learning. In practice that means the agent can adjust its grounding and skill selection based on how it is actually being used, without a developer manually rewriting prompts or retraining anything.

    Before this, teaching an agent your org meant one of two paths. Either you fed it documents and custom instructions and hoped the retrieval was good enough, or you stood up a data science workflow to run evaluation and optimization cycles yourself. Both paths break down at maintenance time. Docs go stale. Nobody wants to rerun eval jobs every quarter.

    Closed-loop learning changes the shape of that problem. Outcome signals from real usage flow back into the agent’s behavior at runtime.

    What Power Apps MCP server closed-loop learning actually does

    To be precise about what is and is not happening here: the underlying model is not being fine-tuned. What is being updated is the agent’s grounding layer and its skill selection policy, based on outcome data that lands in Dataverse.

    I wrote about this separation before in my post on the MCP server as the feedback layer. Skills are the policy layer. The MCP server signals are the feedback layer. Keep those two straight and the mental model holds up.

    The technical surface, as far as I can read from the docs and the Power Platform learn pages, looks like this. When a user interacts with the agent, outcomes get captured. Not just accept or reject clicks, but structured signals about what worked and what did not. Those signals feed a learning loop that updates how the agent grounds itself and which skills it reaches for in a given context. The Dataverse MCP server tool shape update that split metadata inspection, querying, and search into cleaner boundaries is part of what makes this grounding layer more precise.

    That is closer to how a good colleague gets better at their job than how a model gets fine-tuned. Which is the point.

    Why this changes the agent maintenance story

    Most internal agents I see, and most I hear about from people at other organisations, are frozen at deploy time. They make the same mistake in month four that they made in week one, until someone finally opens a ticket and a developer patches the prompt. That is not maintenance. That is triage. It is also exactly the kind of failure pattern I covered in why AI agents fail in production when they worked fine in testing.

    Closed-loop learning breaks that pattern if you set it up carefully. The agent adapts to how the process actually runs, not how the process was documented eighteen months ago when the SOP was last updated. Process drift stops being invisible.

    The trade-off is real though. Runtime learning means the audit story gets harder. Version history now has to cover learned behavior, not just authored skills. If a policy owner asks why the agent behaved differently in July than it did in May, someone has to be able to answer that from data, not from memory. Microsoft has not fully answered that governance question yet, and I want to see how the audit surface actually looks in a live environment.

    The other risk is signal quality. If your team treats every user click as positive feedback, you are teaching the agent that fatigue clicks and correct clicks mean the same thing. They do not. The learning loop is only as good as the signals you decide to trust.

    What I would do with it this week

    I have an internal agent in mind that has been quietly degrading for a few months. Not broken, just noticeably less useful than at launch. Perfect candidate.

    The plan looks like this. First, turn on closed-loop learning in a non-production copy and run it against a shadow traffic sample for a few days. Second, define the outcome signals I actually trust ahead of time, before I look at any data. Accept-without-edit is one signal. Accept-with-edit is another and it means something different. Explicit thumbs down is the cleanest. Fatigue clicks I want to filter out entirely.

    Third, set a review cadence. Not because I do not trust the loop, but because I want to see what it learns and whether the changes match the policy the skill owner would have made themselves. Having a clear way to measure whether the agent is actually improving is where a framework like measuring useful work per dollar for Power Platform AI agents becomes useful alongside the learning loop.

    If the learned behavior lines up with what a human policy owner would do, the loop is doing its job. If it drifts somewhere I did not expect, that is the interesting part.

    This is the first update in a while where I closed the browser tab and immediately opened a new one to start planning a test. I cannot wait to see how it holds up on a real workload.

    Source: What’s new in Power Platform: June 2026 feature update (Microsoft Power Platform Blog).

    About the author: Halilcan Soran is a Senior Business Analyst at Visa working on process optimization with Power Platform, RPA, and agentic AI. He previously led a 15-person team at Thomson Reuters, where the Power Automate solutions he built started his automation career. More about Halilcan · LinkedIn

  • Power Platform May 2026 Update Landed and Here Are the Three Things I Am Actually Turning On

    Power Platform May 2026 Update Landed and Here Are the Three Things I Am Actually Turning On

    Power Platform May 2026 feature update highlights for builders

    The Power Platform May 2026 feature update dropped on the 14th and the release notes are dense. I read through the whole thing twice. Most of it is noise for day-to-day builders. A few things are not. This is the short list of what I am actually turning on this week and why.

    What shipped in the May 2026 update

    The headline item is Power Fx user defined types going generally available as of version 3.26044. UDTs are enabled by default on new apps and require a manual toggle in settings > updates > new > user-defined types on existing ones. Defined with the Type function in App.OnStart or app-scoped formulas.

    Beyond that, the release covers Copilot Studio shipping bits around agent authoring, more Dataverse plumbing for skills and knowledge sources, governance tweaks for managed environments, and a long tail of small Power Apps and Power Automate quality-of-life updates. Some of it is useful. A lot of it is preview-flag churn that will not affect what I build this month.

    Why this release is heavier than it looks

    On the surface, the May 2026 update reads like another monthly drop. It is not. UDTs going GA changes how I write Power Fx, full stop. Component libraries stop being copy-paste exercises and start behaving like an SDK. The agent and skill updates keep moving business logic out of system prompts and into managed Dataverse artifacts, which I have written about before.

    The governance pieces are quieter but they hit the parts of the platform that decide whether your environment stays usable at 200 makers or collapses into sprawl. None of these are flashy. All of them shift how you architect.

    The three things I am turning on this week

    1. Power Fx user defined types on existing apps. This is the one. Before UDTs, type information was inferred from whatever record you passed first. One missing field and the schema silently widened. Runtime surprise. With UDTs you declare the shape once with Type and the formula bar catches mismatches at authoring time. I am going through my medium-sized apps and flipping the toggle, then retyping the component props that have caused the most regression bugs. The trade-off is real. Existing formulas can break when types get strict. You will spend an afternoon fixing things. You get type safety for the next two years. Worth it. More on what UDTs unlock in my earlier post.

    2. The Copilot Studio agent authoring improvements tied to Dataverse skills. If you have not moved your business logic out of system prompts yet, this release is the nudge. A focused 400-token skill outperforms a 4000-token prompt every time. I am rebuilding two internal agents this week, lifting policy logic into skills with named owners and version history. The governance gain matters more than the latency gain. If you want a practical look at surfacing those skills inside an app, How to Build Custom Copilot UI Widgets in Power Apps covers how to wire the Copilot payload to a real component rather than a text box.

    3. The managed environment governance updates. Specifically the changes around DLP scope and the maker access controls. I am not going to pretend this is exciting. It is the unglamorous flipping of switches that keeps the platform from rotting. If you run a CoE, read that section twice and update your baseline. Skipping this is how you end up with the month-three stall I described in Inside a Power Platform Center of Excellence: Why Most Setups Stall in Month Three.

    What I am ignoring this month: most of the preview flags, the cosmetic Power Apps studio tweaks, and anything in the Copilot canvas experience that is not GA. Preview features burn debugging time and break when the next release lands. I will come back to them when they ship for real.

    For the official documentation on UDTs and the Type function, the Microsoft Learn reference is the place to start. For my running notes on what I turn on and what I skip, I keep a list on LinkedIn.

    Monday morning: toggle UDTs on one app, port one skill out of a system prompt, update the managed environment baseline. Three concrete moves. Everything else can wait.

    Source: What’s new in Power Platform: May 2026 feature update (Microsoft Power Platform Blog).

    About the author: Halilcan Soran is a Senior Business Analyst at Visa working on process optimization with Power Platform, RPA, and agentic AI. He previously led a 15-person team at Thomson Reuters, where the Power Automate solutions he built started his automation career. More about Halilcan · LinkedIn

  • How to Build Custom Copilot UI Widgets in Power Apps Step by Step

    How to Build Custom Copilot UI Widgets in Power Apps Step by Step

    Copilot custom UI widgets in Power Apps rendering a card instead of text

    Default Copilot responses in Power Apps are text. Useful for quick answers, useless when the user actually needs a card, a form, or a chart. This walkthrough shows how to build copilot custom UI widgets power apps style, so the chat renders a real component when a specific question is asked, and falls back to text otherwise. Credit to Matthew Devaney’s writeup which is the spine I am building on here.

    End state: a canvas app with a Copilot chat. Ask it about an order, and a card component appears in the conversation with the order details. Ask anything else and you get normal text.

    Step 1: Add the Copilot control and a component to your canvas app

    In your canvas app, insert the Copilot control from the Insert panel. Place it on the right side of the screen. Keep the default width, you will want the space.

    Now create the component that will act as your widget. Go to the Components tab in the tree view, create a new component called OrderCardWidget. Add an input property called OrderPayload of type Record. Inside the component, drop a container with a few labels for order ID, customer name, status, and total. Bind each label to OrderCardWidget.OrderPayload.OrderId and so on.

    Add the component to the screen. Set its Visible property to false for now. You will flip this on from the Copilot response in Step 3.

    Step 2: Configure the Copilot topic to return a structured response

    Open the Copilot studio agent connected to this app. Create a new topic called Show Order Details. Add trigger phrases like show me order, display order, open order card.

    Add a question node asking for the order ID. Then add a tool call to a Power Automate flow that returns the order as structured JSON. The flow does a Dataverse or SharePoint lookup and returns a response with this shape:

    { "widget": "OrderCard", "payload": { "orderId": "...", "customer": "...", "status": "...", "total": 0 } }

    The widget field is the trigger phrase for the UI layer. The payload field is what binds into the component. Do not skip the typed schema on the flow response. If you return a generic object, the Copilot control hands you a string and you spend the next hour wondering why parsing fails. I wrote about that exact failure mode in my custom connector walkthrough.

    Finish the topic with a Message node that returns the JSON as the final response. Microsoft’s docs on Copilot in canvas apps have the current control reference if your version differs.

    Step 3: Bind the component to the Copilot response payload

    Back in the canvas app, select the Copilot control. The control exposes a property called OnResponse that fires every time the agent sends a message. This is where you parse the JSON and route it.

    Set OnResponse to:

    Set(varLastResponse, ParseJSON(Self.LastMessage)); Set(varWidgetType, Text(varLastResponse.widget)); Set(varOrderPayload, varLastResponse.payload)

    Now set the component’s Visible property to:

    varWidgetType = "OrderCard"

    And set its OrderPayload input to:

    { OrderId: Text(varOrderPayload.orderId), Customer: Text(varOrderPayload.customer), Status: Text(varOrderPayload.status), Total: Value(varOrderPayload.total) }

    The widget now renders only when the agent says it should, and only with the data the agent returned. If you want to support multiple widgets later, swap the boolean for a switch on varWidgetType and toggle different components. If you are thinking about when that kind of routing logic warrants a dedicated agent per task, single agent vs multi-agent is worth reading before you scale this pattern.

    Step 4: Test the widget end to end and handle the fallback

    Run the app. Open the Copilot chat. Type show me order 1042. The topic should trigger, the flow should fire, and the card should appear with the right data.

    Now test the fallback. Ask something unrelated like what is the weather. The card must disappear. If varWidgetType is not reset between turns, the old widget hangs around showing stale data. Add a default branch to OnResponse:

    If(IsBlank(varLastResponse.widget), Set(varWidgetType, ""))

    Also test a malformed response. Force the flow to return invalid JSON once and confirm the app does not crash. ParseJSON returns blank on failure, your visibility check handles it, the chat continues as text. That is the behavior you want.

    Final state and one pitfall to watch for

    You now have a Copilot chat that renders a real Power Apps component when the topic returns the right payload, and text the rest of the time. Same pattern works for forms, charts, anything you can build as a component. If you want the agent behind this to pull from richer knowledge sources or close feedback loops on responses, the Dataverse agent data platform new features are worth wiring up alongside this.

    The pitfall: the Copilot control reads the raw message text. If your topic adds any conversational wrapper around the JSON, like Sure, here is your order: {...}, ParseJSON fails silently and the widget never appears. Return pure JSON from the final Message node, nothing else. That one rule will save you an afternoon of debugging. More notes on this kind of integration thinking on my LinkedIn.

    Frequently Asked Questions

    How do I build copilot custom UI widgets in Power Apps?

    You add a Copilot control to your canvas app, create a component to act as the widget, and configure a Copilot Studio topic to return a structured JSON response that includes a widget identifier and a data payload. The canvas app then reads the response, checks the widget field, and toggles the component visible while binding the payload to its input properties.

    Why does my Copilot control return a string instead of a parsed object in Power Apps?

    This usually happens when the Power Automate flow response does not have a typed schema defined. Without a typed schema, the Copilot control treats the response as plain text, which causes JSON parsing to fail. Always define the response schema explicitly in your flow to ensure a structured object is passed back.

    When should I use a custom widget instead of a default text response in Copilot?

    Use a custom widget when the user needs to view or interact with structured data, such as order details, forms, or charts, rather than a plain text answer. Text responses work for simple questions, but components give users a far more usable experience when the data has multiple fields or requires visual formatting.

    How do I connect a Power Automate flow to a Copilot Studio topic?

    Inside your Copilot Studio topic, add a tool call node and select your Power Automate flow as the action. The flow handles the data lookup and returns a structured JSON response back to the topic. Make sure the flow output schema is typed so the Copilot control can pass the data correctly to your canvas app.

    Source: How To Create Copilot Custom UI Widgets In Power Apps (Matthew Devaney (Power Apps)).

    About the author: Halilcan Soran is a Senior Business Analyst at Visa working on process optimization with Power Platform, RPA, and agentic AI. He previously led a 15-person team at Thomson Reuters, where the Power Automate solutions he built started his automation career. More about Halilcan · LinkedIn

  • Power Platform May 2026 Update Shipped and UDTs Going GA Is the Headline for Me

    Power Platform May 2026 Update Shipped and UDTs Going GA Is the Headline for Me

    Power Fx user defined types GA in the May 2026 Power Platform update

    The May 2026 Power Platform feature update dropped on May 14 and the list is long. Copilot updates, Dataverse changes, governance bits. But the one item I keep coming back to is Power Fx user defined types going generally available. If you write any non-trivial Power Apps, this is the change that matters. UDTs are GA as of version 3.26044, enabled for new apps by default, and switchable on existing apps through settings.

    What Power Fx user defined types GA actually does

    UDTs let you define a named, structured type once and use it everywhere in your app. You declare them with the Type function in the App’s OnStart or named formulas. Something like Type({ Id: Text, Name: Text, Status: Text, DueDate: DateTime }) bound to a name, and now every function signature, every variable, every collection can reference that type by name.

    Before UDTs, type information in Power Fx was inferred from whatever record you happened to pass first. Pass a record with one less field and Power Fx would silently widen or narrow the schema. Build a component that took a record parameter and good luck enforcing what was inside it. The result was a lot of defensive coding, a lot of IfError, and a lot of runtime surprises.

    With UDTs you get a contract. A function expects a specific shape. A component prop declares what it accepts. Collections carry a known schema instead of guessing from the first row. The Type function reference covers the syntax if you want the official version.

    Why it matters for app maintainability

    Power Apps has had a maintainability problem for years. Not because the platform is bad. Because untyped records meant every medium-sized app slowly turned into a pile of implicit assumptions. You open someone else’s screen six months later and you cannot tell what shape locSelectedItem is supposed to be without running the app and inspecting it live.

    UDTs make those assumptions explicit. The variable has a type. The component prop has a type. The function returns a type. When the schema changes, you change it in one place and Power Fx tells you everywhere it breaks. That is the difference between a 2000-line app you are afraid to touch and one you can actually refactor.

    There is a real trade-off though. You give up some of the speed of just throwing a record into a variable and moving on. For tiny apps that is overkill. For anything that more than one person touches, or anything that lives longer than a quarter, the upfront type definition pays for itself the first time you onboard a new developer.

    The other thing UDTs do, and this is the part I find more interesting, is that they make Power Fx feel like a language you can actually build component libraries in. Reusable components have been technically possible for a while. They have not been pleasant because the prop interface was loose. With named types, a component library starts looking like an SDK instead of a copy-paste exercise. If you are thinking about how governance fits around that kind of library work, Power Platform governance that does not kill adoption is worth a read before you start standardising component patterns across teams.

    What I would do with Power Fx user defined types this week

    Pick one existing canvas app. Not a critical one. Something internal that you wrote and you are tired of debugging. Enable UDTs through settings, updates, new, user-defined types.

    Then find the single record shape that gets passed around the most. The selected item from your main gallery, the form values for your main edit screen, the API response from your most-used connector. Define it as a UDT in App.OnStart with the Type function. Give it a clear name. Refactor the three or four places that record gets read or written to use the named type.

    You will hit one or two spots where Power Fx now flags a mismatch that was silently working before. That is the point. Those mismatches were latent bugs. Fix them. Then look at any component you wrote that takes a record input and convert the prop to your new named type.

    That is enough for week one. Do not try to type the whole app at once. The way I have seen this go sideways elsewhere is people treating UDTs like a migration project instead of a habit. Start with one type, one screen, one component. Build the muscle.

    I have written before about moving business logic out of system prompts and into managed artifacts, and UDTs are the same idea at the Power Fx layer. Put the contract in one place, let everything else reference it, and stop hiding the schema in tribal knowledge. If you are wiring typed records into flows alongside your canvas apps, the Power Automate error handling patterns post covers how to keep that layer equally explicit about what it expects and what it does when things break. More notes on what I am building with this are on my LinkedIn.

    This is the kind of change that does not look exciting in a release post and ends up changing how I write Power Fx every day.

    Source: What’s new in Power Platform: May 2026 feature update (Microsoft Power Platform Blog).

    About the author: Halilcan Soran is a Senior Business Analyst at Visa working on process optimization with Power Platform, RPA, and agentic AI. He previously led a 15-person team at Thomson Reuters, where the Power Automate solutions he built started his automation career. More about Halilcan · LinkedIn

  • SharePoint Lists Are Still the Best Backend for 80 Percent of Power Platform Apps

    SharePoint Lists Are Still the Best Backend for 80 Percent of Power Platform Apps

    SharePoint lists for power platform apps backend architecture decision

    There is a pattern I keep seeing on LinkedIn and in conversations with people at other organisations. A team starts a new Power Platform project, someone labels it ‘enterprise’, and suddenly the backend discussion jumps straight to Dataverse. No one questions it. Licensing gets justified in a spreadsheet, premium seats get budgeted, and six weeks later the solution is a list of 4000 records with a status column and three lookup fields. That is the moment I want to push back. For a big chunk of internal work, SharePoint lists for power platform apps are still the right call, and treating that choice as amateur hour is costing teams real time and money.

    Why SharePoint Lists Keep Getting Dismissed Unfairly

    The dismissal usually comes from two places. First, the word SharePoint carries baggage from the 2013 era that has nothing to do with what Lists actually is in 2026. Second, Dataverse gets sold as ‘the proper enterprise choice’ in every Microsoft deck, so picking anything else feels like admitting you cut corners.

    Neither of those is an engineering argument. They are vibes.

    In practice, a modern SharePoint list gives you a REST and Graph API, column-level validation, versioning, item-level permissions if you really need them, native integration with every Power Platform connector, and a UI that business users can actually open and fix when something looks off. You get Entra ID authentication for free. DLP policies cover it. The audit log flows into the same Purview tenant everything else does. For an internal request tracker, an onboarding checklist, a small approval queue, or a reference table that three flows read from, that is the whole job.

    The Workloads Where SharePoint Is Genuinely the Right Answer

    I am not arguing SharePoint wins everywhere. I am arguing it wins for a specific and very common shape of work.

    If the app is an internal tool, used by under a few hundred people, with a data volume that will never credibly pass 20 or 30 thousand items in any single list, and a schema that fits cleanly into flat records with a handful of choice and lookup fields, you are in SharePoint territory. Registrations, comms sign-offs, small approval workflows, asset inventories, internal request forms, training trackers, audit checklists. This is the bread and butter of Power Platform inside any large organisation.

    Building on a list for that kind of workload is faster in almost every dimension. You spin up the schema in minutes. Makers on your team can read and edit the data directly in the browser without a model-driven app wrapper. Your Power Automate flows use the standard SharePoint connector, which means no premium licence for the thousand people who happen to trigger a flow indirectly. That last point alone saves real budget. I have written before about how licensing shapes architecture choices in enterprise environments, and this is one of the clearest examples.

    The Real Limits You Need to Design Around

    SharePoint lists are not magic. They have hard edges, and you need to know them before you commit.

    The 5000 item view threshold is the one everyone quotes, and it is real, but it is a view and query limit, not a storage limit. A list can hold millions of items. You work around the threshold with indexed columns, filtered views, and delegable queries in Power Apps. If you are careful with your delegation, a list with 50,000 items performs fine for the usage patterns most internal apps actually have.

    Throttling is the other one. The SharePoint connector has its own limits, and if you are running a flow that hammers a list in an Apply to Each loop at full concurrency, you will get throttled. Same story I covered in the throttling post. Drop concurrency, batch your reads, and stop treating the list like a transactional database.

    Where SharePoint genuinely falls over is relational complexity. More than two or three lookups deep and you are building joins in Power Automate, which is painful to maintain. Row-level security beyond basic item permissions gets ugly fast. Calculated columns are limited. And if two users edit the same item in the same second, you can get conflicts the platform does not resolve gracefully. This is also where why Power Automate is still worth learning in 2026 becomes relevant — knowing how to structure flows around list limitations is a skill that pays off repeatedly.

    When to Actually Move to Dataverse

    Dataverse earns its licence cost when the workload has specific characteristics. Genuine relational depth with many-to-many relationships you actually traverse. Role-based security that needs to be enforced at the data layer, not the app layer. Business rules and calculated fields that are part of the data contract. Plugins, server-side logic, or integration with Dynamics. Auditing at the field level for compliance. Transactional guarantees where a failed write must roll back cleanly.

    If your project has three or more of those, Dataverse is the right choice and the licensing conversation is easy to win because the alternative is building those features yourself and maintaining them forever.

    If your project has none of them, and you are about to spend eight weeks justifying premium seats for 400 people so you can store a status column on 4000 records, stop. Build it on a list. Ship it next week. Spend the saved budget on something that actually needs it. And before you wire any intelligence layer into whatever you build, it is worth reading Adding Copilot to Your Power App Is Not the Same as Making It Smarter — the backend choice and the AI layer choice follow the same logic.

    The backend choice is an engineering decision, not a status symbol. I write more about these kinds of trade-offs on my LinkedIn if this is the kind of call you are wrestling with right now.

    Frequently Asked Questions

    When should I use SharePoint lists for Power Platform apps instead of Dataverse?

    SharePoint lists are a strong fit when your app is internal, used by fewer than a few hundred people, and will never exceed tens of thousands of items in a single list. Common examples include approval queues, request forms, training trackers, and asset inventories where a flat schema with a few lookup fields covers everything you need.

    Why does using SharePoint as a Power Platform backend save money on licensing?

    Power Automate flows that connect to SharePoint use the standard connector, which does not require a premium licence. In large organisations where thousands of users might trigger a flow indirectly, avoiding premium connector requirements can add up to significant budget savings compared to a Dataverse-backed solution.

    What are the security and governance features available with SharePoint lists?

    Modern SharePoint lists authenticate through Entra ID and are covered by your organisation’s DLP policies. Audit logs feed into the same Purview tenant as your other Microsoft 365 services, so governance and compliance requirements are met without additional configuration.

    How do I know if Dataverse is actually necessary for my Power Platform project?

    If a solution is genuinely enterprise in scale, involving complex relational data, high record volumes, or advanced role-based security requirements, Dataverse earns its place. However, if the data model is a few flat lists with simple lookups and the user base is a small internal team, reaching for Dataverse by default adds cost and complexity without a clear engineering benefit.

    About the author: Halilcan Soran is a Senior Business Analyst at Visa working on process optimization with Power Platform, RPA, and agentic AI. He previously led a 15-person team at Thomson Reuters, where the Power Automate solutions he built started his automation career. More about Halilcan · LinkedIn

  • Adding Copilot to Your Power App Is Not the Same as Making It Smarter

    Adding Copilot to Your Power App Is Not the Same as Making It Smarter

    Microsoft published a post this week about making business apps smarter by embedding Copilot, app skills, and agents directly into Power Apps. The features are real and some of them are genuinely useful. But I keep seeing teams read announcements like that and immediately open their existing apps to start wiring things in. That is where it goes wrong. Adding Copilot to Power Apps does not make the app smarter. It makes the AI visible. Those are different things.

    What App Skills and Agent Integration Actually Do Under the Hood

    When you expose a Power App as an app skill or embed a Copilot Studio agent into a canvas app, you are giving the AI a surface to operate on. The agent can read context from the app, trigger actions, and return responses into the UI. In theory, the AI bridges what the user needs and what the app can do.

    In practice, the agent is only as capable as what you hand it. It reads data from your app’s data sources. It calls the actions you have defined. It interprets user intent against the topics and instructions you have written. If your data model is inconsistent, your actions are incomplete, or your process logic has gaps, the agent does not compensate for any of that. It just operates on top of it and returns confident-sounding responses anyway.

    I wrote about this problem in a different context when covering why Copilot Studio agents fail in production. Silent action failures are one of the nastiest issues: the agent completes its response, the user thinks something happened, nothing actually did. That risk does not disappear when you move the agent inside a Power App. If anything, it gets harder to spot because users expect the app to be reliable.

    Why the Data Model and UX Structure Matter More Than the AI Feature

    Most Power Apps I have seen built inside large organisations were designed around a specific, narrow workflow. The data model reflects decisions made at the time of build, often under time pressure, often by someone who is no longer on the team. Fields are repurposed. Status columns hold values that mean three different things depending on which team is using them. Lookup tables have orphaned records nobody cleaned up.

    When you put an agent on top of that, the agent queries this data and tries to give useful answers. The answers will be coherent. They will not be correct. Not reliably.

    The UX structure compounds this. Canvas apps built for point-and-click navigation do not automatically become good AI surfaces. If a user can ask the agent to update a record, but the app’s own form has fifteen required fields and three conditional rules that only run client-side, you now have a conflict between what the agent can do via a Power Automate action and what the app enforces through its UI. One of them will win. It will not always be the right one.

    This is the same argument I made about automating a bad process. The automation does not fix the process, it executes it faster and more consistently, including the broken parts. Embedding AI into a poorly structured app works the same way.

    What I Check Before Wiring Any Agent Into an Existing App

    Before I connect anything to a Copilot Studio agent or enable app skills on an existing Power App, I go through a short audit. Not a formal document. Just four questions that save a lot of cleanup later.

    • Is the data model clean enough to query? If the same concept is stored in three different columns across two tables with inconsistent naming, the agent will surface that inconsistency directly to the user. Fix the model first.
    • Are the actions the agent can trigger complete and safe? Every Power Automate flow an agent can call needs proper error handling and a defined failure response. Silent failures inside agent topics are a known problem. If the flow does not return a clear success or failure, the agent cannot respond accurately.
    • Does the app enforce rules that the agent needs to know about? If business logic lives only in Power Fx expressions inside the app’s forms, the agent does not see it. Validation that matters needs to exist at the data layer or inside the flows the agent calls.
    • Is the process the app supports well-defined enough to describe to an AI? If I cannot write a clear system prompt describing what the agent should and should not do in this app, the process is not ready. Ambiguity in the process becomes ambiguity in agent behaviour.

    When Embedding AI in a Power App Is Worth It and When It Is Not

    There are genuinely good cases for this. An app where users regularly need to find records across complex filters is a reasonable candidate. Surfacing a conversational shortcut to navigate a large dataset, trigger a common action, or get a summary of a record without clicking through multiple screens can reduce real friction. I have seen it work well when the underlying data is clean and the scope of what the agent can do is narrow and explicit.

    The cases where it is not worth it yet are more common. An app with inconsistent data. A process with unresolved exceptions. A UX that was never designed with AI interaction in mind. In those situations, embedding an agent creates a new layer of support burden without a proportional benefit.

    I also want to be direct about something I mentioned in my post on when Copilot Studio is the wrong choice: not every interaction benefits from being conversational. Some things in a Power App are faster as a button. The AI control is not always an upgrade on a well-placed filter or a clear form layout.

    Connect with Halilcan Soran on LinkedIn for more insights on Power Apps and AI integration.

    About the author: Halilcan Soran is a Senior Business Analyst at Visa working on process optimization with Power Platform, RPA, and agentic AI. He previously led a 15-person team at Thomson Reuters, where the Power Automate solutions he built started his automation career. More about Halilcan · LinkedIn