Tulip does not natively prevent two operators from claiming the same batch simultaneously. When multiple operators work from a shared batch queue on separate devices, a race condition can occur: both devices read the batch status as "Pending", both write "In Progress", and both navigate into the execution app. The result is parallel execution of a single batch record, which corrupts process compliance and invalidates the batch.
A status update alone is not sufficient. The fix is a record lock - a dedicated field that ties the batch to a single owner before execution begins, verified before navigation is allowed.
This pattern applies to any shared-queue scenario in Tulip: batch launchers, work order picking, task assignment - anywhere multiple operators select from a shared list of records on separate devices.
Locking Patterns
Tulip supports two locking patterns. Pattern 1 stores the lock on the batch record itself, with two options depending on whether you lock by station or by user. Pattern 2 uses the existing Stations Table structure.
| Pattern | Option | Lock lives on | Schema change? | Best for |
|---|---|---|---|---|
| 1 - Batch Table lock | A: Lock by Station | Batch Table | Yes - one column | Fixed stations, lock visible on batch record |
| 1 - Batch Table lock | B: Lock by User | Batch Table | Yes - one column | Shared devices, named audit trail |
| 2 - Station ownership | - | Stations Table | No | Fixed workstations |
When to Use Record Locking
Apply this pattern when:
- Multiple operators share a queue of actionable records on separate devices
- Two operators could select the same record simultaneously
- Parallel execution would violate process compliance or data integrity
This pattern is not required when each operator works from a pre-assigned batch, when only one device accesses the table at a time, or when Tulip Automations handle batch assignment before operators interact with the queue.
Pattern 1: Batch Table Lock
Tulip writes an owner value to a dedicated column on the Batch Table, then re-reads the field to verify the lock was acquired before allowing navigation. Two field types cover the two main use cases.
Option A: Lock by Station
Add one column to your Batch Table:
| Column | Type | Purpose |
|---|---|---|
locked_by_station |
Station | Stores the claiming station. Empty = unlocked. |
A native Station-type field ensures only a valid Tulip station can be written to this column.
Claim and verify sequence:
- Read
locked_by_stationon the selected batch. - If populated - block navigation. Display: "This batch is locked by another station."
- If empty - write the current station to
locked_by_station. - Re-read
locked_by_station. - If the value matches the current station - proceed to the execution app.
- If the value shows a different station - block navigation. Display the error message.
- On batch completion - clear
locked_by_station.
The re-read in steps 4-6 is critical. If two stations write simultaneously, only one write persists. The re-read determines which station won.
Best for: Environments where operators work from fixed, named stations.
Option B: Lock by User
Identical to Option A, but uses a User-type field. The lock is tied to the logged-in operator rather than the device, which supports named audit trails in regulated environments and handles shared-device workflows where multiple operators share the same device.
Add one column to your Batch Table:
| Column | Type | Purpose |
|---|---|---|
locked_by_user |
User | Stores the claiming operator. Empty = unlocked. |
Claim and verify sequence:
- Read
locked_by_useron the selected batch. - If populated - block navigation. Display: "This batch is locked by [User Name]."
- If empty - write the current user to
locked_by_user. - Re-read
locked_by_user. - If the value matches the current user - proceed to the execution app.
- If the value shows a different user - block navigation. Display the error message.
- On batch completion - clear
locked_by_user.
Best for: Shared-device environments in pharma, medical devices, or regulated industries where compliance requires a named-user record of each batch execution.
Pattern 2: Station Ownership
Tulip's built-in Stations Table includes an order_id column. Writing an order ID to a station's order_id field designates that station as the owner of the order. Any other station attempting to start the same order will find the field populated and be blocked.
No schema changes are required.
Claim and verify sequence:
- Query the Stations Table for any station where
order_idmatches the selected order. - If a match is found - block navigation. Display: "This batch is already in progress at another station."
- If no match - write the order ID to the current station's
order_id. - Re-query the Stations Table to confirm no other station wrote to the same order in the interval between steps 1 and 3.
- If no other station holds this order ID - proceed to the execution app.
- If another station now holds it - block navigation. Display the error message.
- On batch completion - clear the station's
order_id.
If a device crashes mid-batch, the station's
order_idremains set. Provide a supervisor Force Release function that clears the field manually.
Best for: Fixed, named workstations. The Stations Table can also serve as a live floor view - querying it shows which station is running which order at any given time.
Operator-Facing Behavior
When a batch is locked, the operator should receive a clear message, not a system error.
- On the Batch Dashboard, use Tulip's conditional formatting or a filtered Interactive Table to visually mark locked batches (e.g. a "Locked" indicator or grayed-out row).
- On tap, display: "This batch is currently being executed by another operator. Please select a different batch."
- Add a timer trigger (e.g. every 30 seconds) to refresh the batch list automatically, so cleared locks are reflected promptly.
Releasing the Lock
Build a trigger on app exit that clears the lock field. Handle the following exit scenarios:
| Exit scenario | Trigger to use |
|---|---|
| Batch completes normally | App Completed trigger |
| Batch is canceled | App Cancelled trigger - also revert batch status |
| Operator exits mid-run | App Closed trigger |
| Device crash or unresponsive session | Supervisor Force Release - manually clear the lock field |
Edge Cases
| Scenario | Handling |
|---|---|
| Device crashes mid-batch | Supervisor clears the lock field via Force Release |
| Operator walks away without completing | Supervisor clears the lock field via Force Release |
| Network disconnect during write | The re-read verify step detects mismatches caused by partial writes |
| Testing | Run two devices against the same batch within 1-2 seconds. Only one should proceed to the execution app |
Related Resources
- Triggers - Best Practices - includes guidance on avoiding race conditions with variables
- Data review for GxP compliance - review workflows relevant to batch compliance
- Record History Widget - track changes to locked records
- GxP data collection - regulated data capture patterns
- eBR Review App Group - batch record review workflows
- Batch Production Dashboard - the launcher app where this pattern applies
- Electronic Batch Record Suite - the broader eBR workflow