---
title: "Where a screen flow commits"
url: "https://trailassembly.com/screen-flow-transaction-boundary/"
topic: "Flow and Automation"
published: "2026-09-21T11:45:33+00:00"
updated: "2026-09-23T11:02:59+00:00"
---

# Where a screen flow commits

**The two facts people get wrong:** a screen flow commits its pending DML every time it shows a screen, and each segment between screens is its own transaction with its own governor limits. So a record created before a screen is already saved when the user reaches that screen, and clicking Previous does not unsave it. Design around that rather than discovering it during user testing.

## Where the boundaries are

A screen flow’s transaction ends at a Screen element, a Pause element, and at a local action. Everything between two of those is one transaction. When the boundary is reached, pending DML is committed and limits reset for the next segment.

| Element | Ends the transaction? |
| --- | --- |
| Screen | Yes |
| Pause | Yes |
| Local action | Yes |
| Decision, Assignment, Loop | No |
| Get / Create / Update / Delete Records | No |
| Subflow (screen flow with screens) | Yes, at each of its screens |

## What this gives you

The reset is genuinely useful. A flow that processes a large collection can put a screen between batches and get a fresh 100 SOQL queries and 150 DML statements on the other side. For an admin-built bulk tool, “show a progress screen every 200 records” is a legitimate way to stay inside limits without writing Apex.

It also means a long, multi-step wizard is not accumulating limit usage across the whole session — each step starts clean.

## What it costs you

### There is no rollback across a screen

A wizard that creates an Account on screen two and fails on screen four leaves the Account behind. The user clicks the browser back button, restarts, and creates a second one. This is the single most common screen flow defect in production and it does not appear in any test that follows the happy path.

Two workable answers:

- **Do all the DML after the last screen.** Collect input into variables, create everything in one final segment. Clean, and only possible when nothing mid-flow needs a real record Id.

- **Create records in a draft state** and flip a status field at the end, with a scheduled job cleaning up drafts older than a day. More moving parts, and the only option when you genuinely need saved records mid-flow.

I would take the first wherever it fits. The second is a real pattern but it introduces an object lifecycle nobody asked for.

### Automation fires before the user has finished

A record created on screen two runs its triggers, flows and validation rules immediately. The customer-facing email that Account creation sends has gone out while the user is still filling in screen three, and if they abandon the flow, it has still gone out.

If downstream automation should only run on completion, gate it on the status field the final segment sets rather than on record creation.

### Variables persist, database state may not match

Flow variables carry across screens. So a record variable populated before a screen still holds the values it had — even if a trigger modified the record during the save at the boundary. Read the record again after the screen if the values matter. The variable is a snapshot, not a live reference.

This is a quiet source of wrong data: the flow writes back stale field values over what the trigger calculated.

## Where the Previous button makes it worse

Previous returns the user to an earlier screen with their input intact. It does not undo anything that was committed. A flow that creates a record before a screen and lets the user go back and change their answer will, on Next, either create a second record or update the first — depending entirely on how you wrote it, and most people did not consider it.

Either disable Previous on screens that follow a commit, or make the following segment idempotent by checking for an existing record before creating one. Disabling the button is usually the honest choice, because an idempotent wizard is more code than the requirement is worth.

## Pause is a bigger boundary than it looks

A Pause element ends the transaction and schedules resumption. The flow resumes as an asynchronous interview, which means it resumes in a different context. With async limits rather than synchronous ones. Work that depended on the running user’s synchronous context should not straddle a Pause.

## Designing with the boundary rather than against it

- **Put the DML in the last segment** unless there is a concrete reason not to.

- **If you must commit early, set a status** that downstream automation and reports can filter on.

- **Use the boundary deliberately for limits** — a progress screen between chunks is a feature, not a workaround.

- **Re-Get records after a screen** when a trigger might have changed them.

- **Test the abandonment path.** Start the flow, get halfway, close the tab, then look at what exists in the database. That is the test nobody runs and the one that finds this.

## Frequently asked

### Does a record-triggered flow have the same boundaries?

No. A record-triggered flow with no screens runs in the triggering transaction, and an unhandled fault rolls back the user’s save. Only screens and pauses create boundaries, and record-triggered flows do not have screens.

### Can I roll back a screen flow segment?

Not across a screen. Once committed, it is committed. Within a single segment a fault rolls back that segment’s DML, which is why grouping DML into the final segment gives you the strongest guarantee available.

### Do limits really reset at every screen?

Yes, each segment gets a fresh allocation. That is what makes the progress-screen pattern work for bulk operations in Flow.

### What happens if the user closes the browser mid-flow?

Everything committed so far stays. The interview is abandoned. There is no cleanup, which is why the draft-status pattern needs a scheduled sweeper if you use it.

### Does a subflow create a boundary?

A subflow containing screens creates boundaries at those screens, because they are still screens. An autolaunched subflow with no screens runs inside the caller’s current transaction.

---

*Reference: Flow Transaction Boundaries*, *Flow Limits and Considerations* and *Screen Flows*, Salesforce Help; [Execution Governors and Limits](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_gov_limits.htm).

---

Source: https://trailassembly.com/screen-flow-transaction-boundary/
Trail Assembly — independent Salesforce write-ups.
