// field notes / automation reliability
Before you automate
the handoff.
A workflow can run successfully and still leave the business in the wrong state. Review the structure underneath it: who owns the data, what gets validated, and what happens when only half the work succeeds.
By Logan Pinney · Practical design checklist · Fictional example
Ten checks before the first live run
01Name the owner and the source of truth.
Which system owns each field, and who resolves conflicting values?
Try this: Change the same record in two systems. Confirm that one documented rule decides the winner, rather than whichever sync ran last.
02Validate before creating downstream work.
Are required fields, allowed values, and stable identifiers checked at the boundary?
Try this: Submit an empty owner, an unknown status, and a malformed date. Each should produce a clear rejection or review item without creating partial work.
03Make duplicate delivery harmless.
Can the same event arrive twice without creating two tasks or sending two messages?
Try this: Replay one event twice, including overlapping requests. Use an atomic uniqueness rule for the event key; a separate lookup followed by insert can race.
04Handle events that arrive out of order.
Can an old update overwrite a newer decision?
Try this: Deliver version 4 before version 3. Reject or reconcile the stale update using a source version or another documented ordering rule.
05Separate retryable errors from rejected inputs.
Which failures recover with time, and which need correction?
Try this: Simulate a timeout, rate limit, invalid payload, and revoked credential. Bound retries, respect retry guidance, and route permanent failures to an owner.
06Plan for partial success.
What happens when a record is saved but the next API call fails?
Try this: Stop the workflow between writes. Resume from a durable checkpoint or reconcile the external state before repeating a side effect.
07Keep permissions narrow.
Does the automation have only the access it needs, with a named owner for its credentials?
Try this: Check that it cannot read unrelated records or perform unneeded writes. Revoke its credential and verify that the failure is visible.
08Make the handoff explicit.
Who approves consequential changes, and what does the next person need to see?
Try this: Route one ambiguous record to review. Show the proposed change, supporting context, responsible person, and an explicit approve or reject action.
09Leave a useful audit trail.
Can someone explain what happened without exposing the full payload?
Try this: Trace one event through intake, validation, approval, and delivery using a correlation ID. Log outcomes and safe identifiers, not secrets or unnecessary personal data.
10Prove recovery before launch.
Can an operator pause the workflow, locate failed items, and replay them safely?
Try this: Run a small failure drill. Check alert ownership, the recovery instructions, duplicate protection, and the final state in every affected system.
A small handoff record
This fictional intake record separates approval from delivery. It is a design sketch, not a client schema or a complete implementation. Keeping those states separate prevents “approved” from being mistaken for “successfully delivered”.
{
"event_id": "evt_demo_001",
"record_id": "request_demo_042",
"source_system": "intake",
"source_version": 4,
"correlation_id": "trace_demo_042",
"status": "awaiting_review",
"owner_role": "operations_reviewer",
"approval": { "required": true, "state": "pending" },
"delivery": { "state": "not_started", "attempts": 0 },
"last_error_code": null
}Open the example JSON →Use the event ID to recognize repeated deliveries and the record ID to identify the business request. A version belongs to that source record. An event ID alone does not guarantee that an external email or API write happens once: delivery still needs a durable checkpoint, a downstream idempotency key where supported, or reconciliation.
Walk one failure all the way through
Imagine intake creates an operations request. A reviewer approves it, then a downstream task service times out. The outcome is unknown: the task may already exist. Keep approval as approved, mark delivery for reconciliation, and look up the task using the stable request key before creating another. If the destination cannot support that lookup, route the uncertainty to an operator instead of retrying blindly.
The useful question is not just “did the automation run?” It is “can someone prove the request reached the intended state, and recover it when it did not?”