Power BI reports can now write back and trigger actions through Fabric User Data Functions. Here is where that earns its place, a worked example, and the governance questions to settle before you turn it on.
For years a Power BI report could show you the problem but not let you do anything about it. You saw the at-risk renewal, the data quality issue, the reforecast that needed a note against it, and then you left the report. An email here, a ticket there, a spreadsheet somewhere else. Seeing and doing lived in different places.
Translytical Task Flows close that gap. They reached general availability in the March 2026 Power BI update, and they let a Power BI report write back, update, delete and trigger actions in other systems without the user ever leaving it.
That is a genuine shift in what a report is for. It is also the kind of capability that is easy to turn on and easy to regret if you skip the governance. This guide covers what a task flow actually is, where it earns its place and where it does not, a worked example so you can see the moving parts, and the questions we would settle with a client before the first function is written.
What a Translytical Task Flow actually is
A Translytical Task Flow connects a button in a Power BI report to a Fabric User Data Function. The term translytical is a blend of transactional and analytical, which is a fair description of what it does: it brings a small transactional action into an analytical surface.
The engine underneath is the User Data Function, or UDF. This is reusable Python logic that lives in your Fabric workspace and runs on your Fabric capacity. When a user clicks the button, the report passes context to the function: selected rows, slicer values, free text typed into an input, or a measure value. The function then does the work. That might be an insert, update or delete against a Fabric data source, or a call to an external API to post an approval to Teams, raise a ticket, or ask an Azure OpenAI endpoint for a suggestion. The result comes back into the same report.
The important part is what does not change. The report stays a report. Because the action runs on a UDF inside Fabric, it inherits the same identity, permissions and observability you already have. It is not a bolt-on application sitting beside your report with its own login and its own lifecycle.
Where it earns its place, and where it does not
Translytical Task Flows are the right tool when the report context is the main input and the write stays inside Fabric. Good examples we see regularly include annotation and commentary, where a finance team reviews monthly actuals and wants to attach a comment to a specific number, stored with its period, entity and department, so it is there next month when they open the same view; data quality fixes at the point of discovery, where a field team spots a wrong address or a misspelled account while working in a report and corrects it there rather than routing the fix through a separate process; and lightweight approvals, where a sales manager selects opportunities, enters a discount and a justification, and submits, with the function writing the request and posting it to Teams with the full context attached, giving an audit trail from insight to action.
They are the wrong tool when you need a rich, multi-step interface, complex forms beyond a button and a few slicers, or a write that lands outside Fabric. That is still Power Apps territory. The honest rule of thumb: Translytical Task Flows for simple, Fabric-native write-back where the report is the context; Power Apps when you need a proper application. Task flows avoid the separate environment, the separate licence and the separate deployment lifecycle that come with an embedded app, but they are deliberately narrower.
The three things to agree before you switch it on
This is the part a tutorial will not tell you, and it is where most of the risk sits.
Permissions and identity. Only users authorised to run the function can trigger it. Anyone else gets an error. That is good, but it means you have to decide, on purpose, who is allowed to write, not just who is allowed to read. A report that used to be safely read-only for a wide audience now has an action behind it. Map the write permissions before you publish, not after someone changes a record they should not have.
Audit and observability. A write-back is a change to your data, so treat it like one. Decide what you record: who did what, when, and with which context. The cleanest designs store the action itself as data, with the user and a timestamp, so the audit trail is a table you can query rather than something you hope was logged. If a number can now be changed from a dashboard, you want to be able to answer who changed it and why without a forensic exercise.
Ownership and lifecycle. The UDF is code, and code needs an owner. Who writes it, who tests it, where does it sit in your deployment process, and who gets the call when it breaks. Application lifecycle improved at general availability, and the Power BI project formats PBIP and PBIR are now fully supported, which removes an earlier blocker to promoting these cleanly between environments. That does not remove the need for an owner. It just means there is no longer a good excuse for the function to be a mystery script nobody maintains.
A worked example
Here is the shape of a simple annotation flow, so the pieces are concrete. The goal: let a user add a comment against a record from within the report, stored in a Fabric SQL database.
Step 1: Store the data. Create a Fabric SQL database and a table to hold the comments, for example a Comments table with columns for the record id, the comment, the author and a created timestamp. For write-back we recommend a SQL database over a Lakehouse or Warehouse as the write store, because it handles the frequent small reads and writes that reporting scenarios generate far better.
Step 2: Write the function. Create a User Data Function item in the same workspace, add a connection to the database, and write a function that performs the insert. The logic is ordinary Python. The one rule to remember is that the function must return a string for its result to appear in the report.
import fabric.functions as fn
udf = fn.UserDataFunctions()
@udf.connection(argName="sql", alias="AnnotationsDB")
@udf.function()
def add_comment(
sql: fn.FabricSqlConnection,
record_id: str,
comment: str,
author: str,
):
connection = sql.connect()
cursor = connection.cursor()
cursor.execute(
"INSERT INTO dbo.Comments (RecordId, Comment, Author, CreatedUtc) "
"VALUES (?, ?, ?, SYSUTCDATETIME())",
(record_id, comment, author),
)
connection.commit()
cursor.close()
connection.close()
return "Comment saved"
The snippet is illustrative. Follow the current Fabric samples for exact syntax, and add input validation in the function itself, since that is where you want it, not in the report.
Step 3: Wire up the report. In Power BI Desktop, add a button and set its action type to Data Function, then point it at your workspace, the UDF and the specific function. Map the function’s parameters to the report: the record id from a measure using a conditional value, the comment from an input slicer, and the author from the current user. A common misconception is that inputs can only come from slicers. Button, list and input slicers are the built-in input controls, but you can also pass measure values through conditional value mappings, which opens up a lot more than the slicers alone.
Step 4: Publish and test. Test in Desktop, then publish and test again in the service as a real user would see it, because that is where permissions and credentials actually bite. On success the user gets a confirmation and the report refreshes to show the new comment.
Practical gotchas worth knowing
A few things that trip people up, so you can plan around them. The function must return a string, or its result will not surface in the report. Only authorised users can run functions, so factor the write permission into your rollout. A SQL database is the sensible write store for anything read and write heavy. Power BI Embedded is supported for secure embed scenarios only. And be ready for terse error messages during development, since the failure responses are not always descriptive and you will spend some time reading function logs. None of these are blockers. They are just the difference between a smooth build and a frustrating one.
How to decide if it is right for you
Translytical Task Flows are a real step forward, and for the right scenario they remove a genuine daily friction. The useful question is not whether you can turn it on. It is where it earns its place, and whether you have agreed the permissions, the audit and the ownership before you do.
That is the same principle we apply to everything: governed from day one, not bolted on at the end. If you are weighing up where write-back belongs in your reporting, or you want a second opinion before you switch it on, that is a conversation worth having early.
Matt Devine
Client Success Team
Part of the Hopton Analytics team, delivering governed analytics programmes for UK mid-market organisations.
