AL+

Language: RO (română) EN (English)

Email us: paul@alplustech.com

Rails job cursors leave external commits outside the checkpoint

Use Rails 8.1 job continuations to resume work while designing idempotency, uncertain outcomes and reconciliation at the external side-effect boundary.

Citiți articolul în română

A resumable job can remember where it stopped without knowing whether an external service completed its request. Rails job continuations reduce repeated work after an interruption. They do not turn cursor advancement and an arbitrary remote operation into one atomic commit. Put the duplicate-prevention decision at the boundary where the external effect happens.

This distinction matters whenever the business consequence survives the worker process. A payment, a message or another remote action can succeed even if the worker never receives its response. Progress recorded by the application and completion recorded by the remote service can disagree. A continuation offers a place to resume; the application still needs a policy for that disagreement.

Read the cursor as progress state

The Rails 8.1 release announcement of 22 October 2025 introduces discrete job steps and a cursor for progress inside a step. Its example processes a record before advancing the cursor. This ordering makes the job easier to resume, but the example does not claim a transaction spanning an external service.

The tagged Rails 8.1.0 step implementation is precise about advancement: advance! computes the successor of the supplied or current value, then calls set!, which updates the cursor and checks for interruption. This is not a synchronous promise to commit arbitrary external work together with durable progress. Correct use of the cursor remains the step’s responsibility.

That reading also avoids overstating persistence. Updating a cursor in the running job and having usable continuation state after a particular failure are different questions. Check the interruption and requeue behaviour of the actual job setup before promising recovery from every process termination. The argument here concerns the external commit boundary even when continuation persistence works as intended.

Examine the uncertain interval

Consider the ordering as a design analysis, not a reported experiment. The job sends a remote request, the service commits its effect, and the worker stops before it records enough progress to skip that operation on resumption. The next execution can repeat the request. Nothing in a local cursor tells the remote service that the business operation was already completed.

Moving advancement earlier changes the failure risk. If the worker records progress before the remote service commits, an interruption can leave the operation skipped when the job resumes. That trades potential duplication for potential omission. Choosing an order alone cannot make two independent systems participate in one atomic decision. The application needs a way to recognise the same intended operation across attempts.

A timeout is another uncertain outcome. It does not establish that the remote service rejected the request. Treating every timeout as safe to repeat can create duplicates, while treating it as success can lose work. Decide what evidence resolves the uncertainty: a lookup by stable operation identity, a provider response retained locally or a human reconciliation path when neither is available.

Give the business operation a stable identity

Where a remote interface supports idempotency, its contract deserves review before adopting it as the answer. Determine how requests with the same identity are handled, how long the service remembers them and whether changed parameters are rejected or treated as another operation. This article makes no provider-specific guarantee. The useful requirement is that a retry of the same business operation can be recognised at the effect boundary.

Choose identity from the intended business action rather than from the current worker attempt. If each retry creates a new identity, the remote service may see independent requests even when the application thinks it is resuming the same work. Conversely, reusing an identity for genuinely different operations can suppress work that should happen. Identity scope is a product rule as well as an implementation detail.

Keep enough local state to explain that rule. The record should distinguish an operation awaiting a response from one confirmed complete, and preserve the external reference when one exists. A continuation cursor can then guide traversal through records without pretending to be the sole ledger of remote outcomes. The details depend on the service contract and the consequence of uncertainty.

Reconciliation belongs in the feature

A recovery procedure should say who handles operations whose state remains unknown. Reconciliation can compare the application’s record with an authoritative remote result when the interface allows that. If automatic resolution is impossible, give the responsible person the operation identity and the evidence already gathered. A generic “job failed” notification leaves them without the context needed to avoid another unsafe attempt.

Verification should follow those failure points. Exercise interruption before the external request, after remote completion but before local confirmation, and during an uncertain response. Check both duplication and omission. These are recommended checks, not tests run for this article, and their exact mechanism depends on the application. A successful uninterrupted job says little about the interval that motivates the design.

The strongest counterargument is that much background work has no troublesome external effect. Pure calculations or operations that naturally converge to the same result may tolerate repetition. Adding an operation ledger and manual reconciliation to every loop would create unnecessary machinery. Use the stronger design where a repeat or omission changes something the business must account for.

A local database-only operation may also admit a simpler transactional design when the relevant writes genuinely share one transaction. That possibility should be assessed directly. It cannot be extended by analogy to a remote API merely because both calls appear inside the same job step. Match the guarantee to the systems that actually participate in it.

For custom software development, define the acceptable recovery outcome before estimating a resumable integration. Rails continuations can organise progress through the work. The external service contract and the application’s reconciliation policy determine whether resuming that work preserves the intended business action.