When people ask what makes Power Platform powerful, they point to the tools. Power Apps for the interface. Power Automate for the workflow. Copilot Studio for the agent. After a couple of years of building with it, I think the answer sits somewhere else.
The power is in what the platform rides on.
Power Platform sits on Azure, Microsoft 365, Entra ID, and Dataverse. Identity is solved. Security is inherited. Your users already live in these tools. So the useful question stops being “what can this tool do?” and becomes “what does the Microsoft cloud already do that I can pull in?”
Here is what that looked like in practice.
A word about connectors
In Power Automate, almost everything is a connector. SharePoint is one. Outlook is one. The HTTP action is one too, so calling an Azure Function is still using a connector.
The difference is what each one gives you. A prebuilt connector wraps a service and hands you actions someone else already built: get a file, send a message, create a row. The HTTP action gives you only a pipe. It carries a request out and a response back, and it does no thinking in between.
That distinction shapes everything below. Connectors move data between systems. They don’t interpret it. When a solution needs something understood, calculated, or reshaped beyond what the actions allow, the logic has to live somewhere else, and the flow reaches it through that pipe. Each section that follows is a different answer to the same question: where should this work live?
Power Platform is the front door. Everything beneath the pipe is the Microsoft cloud doing the work.
When no connector understands the work
I needed to run construction takeoffs from CAD drawings. A drawing arrives as a DXF file, and the questions are practical ones. How much floor? How much wall? How many doors? No connector I know of opens a drawing and reports its geometry.
An Azure Function does. It uses a Python library called ezdxf. The flow sends the file over HTTP, the function reads the drawing and walks every entity, the lines, arcs, polylines, hatches, and text labels, and it returns structured JSON: counts by type, total length, enclosed area, and the room annotations. One hospital floor plan came back with more than fifty thousand entities, summarized in a payload a flow can handle.
Then the flow goes back to what it does well. It stores the result, routes it for review, and notifies the right person.
Two lessons came out of it. Files travel in more shapes than you expect. The content can arrive wrapped in JSON, as raw base64, or as a stringified byte object, and my function had to learn to accept all three. And know what your library can read. ezdxf handles DXF and DWG, not DWF, so a different file format meant a different step before the function ever ran.
When the loop is the problem
Some flows turn into nested loops with actions stacked inside each one. They work, but they run slowly and they are painful to maintain.
I moved that logic into functions. One example compared two lists of tasks, treating one as the source of truth, and returned three things: items to update, items to add, items to remove. The flow’s only job was to apply those results through an HTTP call. The function did the thinking and the flow did the delivering.
It also costs less than people expect, and the setup is modest. Secrets go in Key Vault, and the function reads them through a managed identity. The API key never appears in the flow.
When the work outgrows a flow
Contract analysis is one of my favorite examples. A user uploads a PDF to a record in Dynamics 365. A Logic App watches that table, notices the file, downloads it in chunks, and sends it to an Azure Function for analysis. The function is given thirty minutes, because contracts are not quick reading. The result is cleaned, written back to the record, and the user gets an in app notification.
The Power Platform front end stayed simple. The user uploads a file and receives an answer. Behind it, a Logic App, a Function, and a vector store did the heavy work. Nobody on the business side needed to know.
When the answer lives in Excel
This is the one people overlook, and it fits the definition in an interesting way. Running an Office Script from a flow is itself a connector action, the Run script action in the Excel Online connector. The connector is only the pipe. The script is where the work happens.
In one solution, scripts read the column headers from an uploaded file and from the target import template. An AI prompt mapped one to the other, and a final script wrote the clean CSV. A practical note from that build: return arrays from a script as JSON strings. Power Automate will not surface a native array as usable dynamic content, and you will lose an afternoon finding that out.
In another, a script wrote summary values to fixed cells and built a named table, while the bulk rows went in through the Microsoft Graph API using the HTTP with Entra ID connector. Excel stayed the output, and the platform did the rest.
One caution. Office Scripts can be switched off in a tenant, and mine was at first. Know what your environment allows before you design around it.
What reaching costs
Every piece of this has a price, and I do not mean only the invoice.
Logic Apps Standard needs a storage account. Managed identities need role assignments on every resource they touch. Choose a model in Foundry without understanding its pricing, and you can pay for reasoning tokens to summarize an email. I have seen that mistake multiply a cost by seven. I have also cost an organization 23,000 dollars in a single day through one careless configuration. The lesson was simple. Ask questions before you configure, of your stakeholders and of yourself.
Reaching into the platform is worth it. It just is not free, and it rewards builders who know what they are reaching for.
The shift
A solution built on one tool inherits that tool’s limits. A solution built on a platform inherits the platform’s reach.
Power Platform is the front door. The Microsoft cloud is the building behind it. Good architects learn to use the whole building.
Most security gaps in Dataverse don’t look like gaps. A reviewer opens a list, sees only their rows, and everyone assumes the boundary is real. A view decides what people see. Filtered record ownership decides what they can reach. I built a small compliance lab in a Dataverse sandbox to test that line, and most of it held. One result did not.
Filtered record ownership is in preview. Microsoft can change how it behaves before general availability, and preview features aren’t meant for production. Everything below comes from a sandbox.[1]
The question every maker asks
Dataverse makers already understand views.
We create views to focus people on the records that matter to their work. We filter them by status, region, legal entity, assigned team, or any number of other attributes. We can even control which security roles see particular public views.
So when Microsoft introduces filtered record ownership, still in preview, a reasonable question follows:
Isn’t this just another way to create a filtered view?
No.
A filtered view decides what appears in a saved list. Filtered record ownership decides which records a user is allowed to access in the first place.[1][2]
The familiar approach
Imagine a custom table called Compliance Evidence.
Each record has a Legal Entity field. You create a public view named US Corp Evidence Awaiting Review with these criteria:
Legal Entity equals US Corp
Evidence Status equals Submitted
You then make that view visible only to the US Compliance Reviewer security role.
That is useful. It gives US reviewers a relevant list and keeps the application easier to navigate. Microsoft supports managing access to public system views through security roles.[2] Two details trip people up: role-based view access only works after an administrator turns on the environment setting EnableRoleBasedSystemViews, and it only applies to public views that aren’t the table’s default view.[2]
A view limited to one security role. It decides who sees the list, not who can reach the data.
But that configuration answers only this question:
Which saved view should this user see in the application?
It does not answer this question:
Which evidence records is this user allowed to access?
Microsoft explicitly distinguishes view access from data access: being able to use a view does not grant access to the records in it, and the user’s underlying Dataverse privileges still control which rows are returned.[2]
The difference
Capability
View limited by role
Filtered record ownership
Primary purpose
Give a role a relevant saved list
Enforce access row by row, based on record values
Filter means
“Show matching rows in this view”
“Authorize access only to matching rows”
Controls
User experience
Data access
Another view can show other rows
Possibly, if normal privileges allow it
No, not for the same restricted identity
API, SDK, or flow access
Normal table permissions determine results
Filter privileges limit results for the identity making the request
System Administrator
Sees whatever the role’s privileges allow
Sees every row, through a built-in “All records” filter
Record owner
Existing ownership model remains
No user or team owner (on tables with Filtered ownership)
Assignment and record sharing
Available when supported by ownership model
Not available because rows under filtered ownership have no owner
Status
Generally available
Preview
Filtered record ownership uses filters assigned through roles as security predicates. Dataverse evaluates the record’s column values against those privileges when deciding whether to allow actions such as Create, Read, Write, Delete, Append, and Append To.[1]
Record filters aren’t limited to the new ownership type. You can also add them to existing tables owned by a user or team, where they grant access on top of ownership rather than replace it.[4]
One filter, two meanings
The same-looking criteria can do two very different jobs.
In a view:
Legal Entity = US Corp
Means:
“When someone opens this saved list, display US Corp evidence.”
In filtered record ownership:
Legal Entity = US Corp
Means:
“A user with this filter privilege is authorized to access only US Corp evidence.”
The criterion is identical. Its role in the platform is not.
A view filter shapes a query. A filtered ownership rule shapes authorization.[1][2]
The view’s filter: Legal Entity equals US Corp and Evidence Status equals Submitted. It decides what appears in this list, not what the user can reach.
Record filters live in their own table. The condition matches the view’s, but here it decides access.
A compliance example
Consider this simple model:
Parent table:Silver Compliance Tracker
Child table:Compliance Evidence
Evidence classification fields: Legal Entity, Region, Sensitivity, and Evidence Status
The parent tracker represents the overall audit, certification, or compliance cycle. It can remain a normal table owned by a user or team, because there may be an accountable compliance manager or team.
The child Compliance Evidence table represents individual evidence items. This is where filtered ownership earns its place, because access may need to depend on the evidence item’s classification rather than who owns it.[1]
For example, the US Compliance Reviewer role might receive a record filter:
Legal Entity = US Corp
An EU Compliance Reviewer role might receive a different record filter:
Legal Entity = EU GmbH
Now the US reviewer may see the overall tracker but only the evidence items that match the US filter. The EU reviewer sees only EU evidence. That is need to know, enforced by the platform.[1]
The lab: Silver Compliance Tracker is the parent, and Compliance Evidence is the child that carries the record filters.Record ownership: Filtered (preview). The field is greyed out because the choice is permanent once the table exists.
What I tested
Documentation tells you what a feature should do. A lab tells you what it does. So I built this model in a Dataverse sandbox and tried every route I could find. The setup:
The two tables above, with Compliance Evidence created as Filtered ownership
Two record filters (US Corp and EU GmbH) and two reviewer roles, each granted its own filter
Six evidence rows: three US Corp, two EU GmbH, and one Canada Ltd row that no reviewer filter covers
The same data surfaced through a model-driven app, the Web API, a Power Automate flow, a code app, and a Copilot Studio agent
One test user without admin rights, switched between the two roles
The clearest result is the second row of the table below. The Evidence Submitted view has no Legal Entity filter at all, yet each reviewer still saw only their own entity’s rows. The record filter did that, not the view.
Route
US reviewer
EU reviewer
System Administrator
View: All Compliance Evidence
3 rows
2 rows
6 rows
View: Evidence Submitted (no Legal Entity filter)
2 rows
1 row
4 rows
View: US Corp Evidence Awaiting Review
In the list, 2 rows
Not in the list; 0 rows when opened through Manage and share views
2 rows
Other entity’s record by direct link or Web API
Not returned
Not returned
Returned
Web API list
3 rows, all US Corp
2 rows, all EU GmbH
6 rows
Power Automate flow (run as the user)
3 rows
2 rows
6 rows
Code app
Own rows only
Own rows only
Not tested
Copilot Studio agent (Authenticate with Microsoft)
Own rows only
Own rows only
Not tested
Create a record for the other entity
Blocked
Blocked
n/a
Change own record’s Legal Entity to the other entity
Allowed
Allowed
n/a
The last row is the one that matters most. I come back to it below.
The administrator column is a warning, not a feature. Dataverse automatically gives the System Administrator role a built-in “All records” filter on every filtered table, so an admin always sees everything. If you test with an admin account, you prove nothing.[1]
The agent result is what I observed in one test, not documented behaviour. Treat it as something to verify in your own environment.
US Compliance Reviewer Role
EU Compliance Reviewer RoleThe view opened. The records didn’t. The EU reviewer’s filter blocks US Corp evidence, whichever view they use.The view isn’t the boundary.Signed in as the EU reviewer, I asked the Web API for a US Corp record by its ID. Dataverse refused. RecordFilterAccessRights: None. No filter granted access, so no record.Signed in as the EU reviewer, the code app shows three rows, all EU GmbH. The app doesn’t filter anything; the record filter does. The third row started life as US Corp evidence. A US reviewer moved it here, which is the edit problem covered below.Signed in as the EU reviewer, I asked the agent for everything. It returned three EU GmbH records and found nothing for US Corp or Canada Ltd. The agent never saw those rows, so it couldn’t leak them.
The security layer
So what is it, then? A security control at the data layer, for reading and creating records.
A user cannot get around the filter simply by selecting a different view. Whether the user reaches Dataverse through a model-driven app, a code app, the Web API, or a flow that runs as that user, Dataverse evaluates the same filter privilege.[1] In my tests, every one of those routes returned the same rows for the same role.
When a client asks, I put it this way:
A view controls the screen. Filtered ownership controls the record.
Or:
Views organize data; filtered ownership authorizes data.
An important qualification
Dataverse always evaluates the permissions of the identity making the request. That sounds obvious until you meet a cloud flow.
A flow does not run as the person who presses the button by default. It runs with the connections saved in the flow, which are usually the maker’s. In my lab, the Evidence Read Test flow returned all six rows to every user until I opened the flow’s Run only users panel and set the Dataverse connection to Provided by run-only user. Only then did it return three rows for the US reviewer and two for the EU reviewer.[3]
Two details matter:
The connection’s account needs a privilege. For Dataverse in the same environment, “provided by run-only user” makes Dataverse act on behalf of whoever runs the flow. The account behind the flow’s Dataverse connection must hold Act on behalf of another user (or the Delegate role). When I pointed the flow at a connection for a regular user, saving failed with a missing prvActOnBehalfOfAnotherUser error.[3]
Data that leaves Dataverse leaves the filter behind. A flow co-owner can open the run history of someone else’s run and read everything that run returned. In my lab, that meant all six evidence names, including rows the co-owner’s own role could never read. The filter protects rows in Dataverse. It does not protect copies of them in run history, exports, emails, or logs.
A flow or integration running under a service account, application user, or service principal is the same case: a separate security principal with its own permissions. That does not bypass security, but it can return more than an individual reviewer could see.[5][1]
So the honest version is:
Filtered ownership applies consistently everywhere Dataverse evaluates the same identity’s permissions. Check which identity each route actually uses.
Run as the administrator: count 8. The flow returns every evidence record, US and EU alike.The same flow, run as the EU reviewer: count 3. Same steps, same query. The only thing that changed is whose identity Dataverse checked.
One flow, two answers. As the administrator, it returns 8 records. As the EU reviewer, it returns 3. The flow didn’t change. The identity did.
A gatekeeper on create, not on edits
The filter is not auto-fill
Filtered ownership does not automatically populate fields.
Suppose a US reviewer can create only records where:
Legal Entity = US Corp
The application still needs to set the Legal Entity field, through a form default, Power Fx, automation, a plug-in, or another controlled process. The filter acts as a gatekeeper: it allows the new record only if its value satisfies the user’s Create filter.[1] In my tests that held. Each reviewer could create a record for their own entity, and an attempt to create one for the other entity was refused.
The filter is a gatekeeper, not an auto-fill rule.
When it fits
Filtered ownership is useful when access should follow a trustworthy record attribute:
Legal entity
Geographic region
Data classification
Customer segment
Business division
Control area
Regulatory scope
This makes it useful for need-to-know scenarios, provided those classification fields are required, accurately maintained, and governed. The security rule is only as reliable as the data used to evaluate it, and, as the edit test shows, only as reliable as the controls on who can change that data.[1]
When teams still fit better
Filtered ownership is not a replacement for tables owned by a user or team.
Use a traditional design built on ownership when you need:
A clear individual or team accountable for each record
Assignment and reassignment
Record sharing
Ownership-based processes and reporting
A regional or functional team that truly manages the work
Use filtered ownership when the central access question is:
“Does this record’s classification authorize this person to access it?”
Use team ownership when the central question is:
“Which person or team is responsible for this work?”
The two aren’t mutually exclusive. A table owned by a team can also carry record filters that grant extra access, based on record values, on top of ownership.[4]
Choose the pattern that matches how the work runs, not the one that shipped most recently.[1]
Where the boundary lives
Filtered record ownership is not a new way to make filtered views.
It is a different security model for custom tables, one where a record’s values, rather than a user or team owner, determine who can access it.
A view limited by role may still be valuable. It gives each user an appropriate experience and reduces navigation clutter. But it does not establish the data boundary.
Filtered record ownership is still in preview, and that matters more than it sounds. A table’s ownership type can’t be changed once it’s created, so a table you build on it today is a commitment to a feature that isn’t finished. The edit behaviour above is exactly the kind of detail that may change before general availability. Approach it as a sandbox exercise and a pattern to evaluate, not yet a production security foundation.[1]
The view says, “Start here.”The filtered ownership rule says, “Only these records.”Your own controls on the classifying field say, “And they stay that way.”