Extract a capability with a clear boundary
A fictional position-publication batch combines validation, transformation, and delivery to several consumers. Modernization does not require replacing everything at once. A strangler fig can route an already validated capability to a new service while other functions remain in the legacy system. Define data ownership, contracts, routing, and exit criteria before extraction. Splitting only by technical layer can leave every service dependent on the same change and transaction. The transition proxy also needs capacity and availability; adding microservices does not remove that failure point. An anti-corruption layer translates semantics between models, including units, states, and identifiers. It should not indefinitely hide who owns an incompatible contract. Include its monitoring, release process, and eventual retirement in the plan.
Resolve dual writes without inventing a global transaction
If a service commits its database and fails before publishing an event, the consumer might never learn about the change. In a relational outbox pattern, the business change and event record belong to the same local transaction. A separate publisher reads committed changes and sends the event. This closes the gap between commit and publication intent but does not turn database and broker into a global ACID transaction. Delivery can repeat; preserve event identity, required ordering, and idempotent consumers. Measure publisher delay and failures and define replay. Committing an outbox row does not establish that the consumer applied the effect. Business-visible status should reflect the stage actually demonstrated, with reconciliation for deliveries whose outcome remains uncertain.
Compensate effects and make irreversibility explicit
A saga coordinates local transactions and compensating actions when the flow cannot finish as planned. Compensation is not equivalent to ROLLBACK in a single transaction and does not automatically isolate concurrent sagas. A reservation may be released, but an already delivered notification does not disappear. Define repeatable, compensable, and irreversible steps, with durable records and an exception owner. If compensation fails, the flow remains incomplete; do not report success merely because the original error was caught. Participants and compensations should tolerate repetition according to their contract. A circuit breaker can reduce pressure on a failing dependency but does not establish earlier call outcomes or replace business-effect reconciliation. Test partial progress and recovery, not only the successful path.
Choose the workflow and the meaning of completion
Step Functions Standard and Express have different models. Standard supports durable workflows and job or callback waiting patterns; Express has a five-minute maximum and does not support.sync or.waitForTaskToken. Distinguish asynchronous Express, with at-least-once execution, from synchronous Express, with at-most-once execution. These properties are not a global transaction over external effects, and explicit retries can repeat tasks. Request Response advances after the API response, which may only acknowledge submission. The.sync pattern waits for a supported job, but cancellation is best effort. Callback requires token correlation and appropriate authorization; an external system can communicate through an authorized bridge while respecting the same-account-principal requirement when returning the token. Confirm what the downstream consumer treats as completed work.
Bound retries and handle the correct error
An applicable Retry is evaluated before Catch. Define transient errors, retry count, backoff, jitter, and total deadline without automatically retrying business rejections. MaxAttempts counts retries and excludes the initial attempt. In the original model, three retries after waits of 2, 4, and 8 seconds produce at most four attempts and fourteen seconds of waiting, excluding task execution. States.ALL does not catch States.DataLimitExceeded or States.Runtime; current documentation allows explicit handling of DataLimitExceeded. Do not extend that possibility to Runtime. A workflow’s top-level timeout is not an error caught by an arbitrary Catch in the same machine. Heartbeats establish activity, not success, and do not remove the total execution limit. Observe the actual failing layer before changing retry behavior.
Prove resumption, observability, and transition to RUN
For Standard, repeating StartExecution with identical name and input while an execution is running has specific idempotent behavior; changing input or using a closed execution is a different situation. Express does not offer that start idempotency. Nor should complete Express history be assumed merely because CloudWatch Logs is enabled: delivery is best effort. If the business requires durable evidence, design appropriate records and state reconciliation. Handover should include correlation among request, workflow, outbox, and consumer, procedures for uncertain outcomes, and compensation limits. The PM requests recovery evidence after failures and criteria for retiring legacy functions. A green orchestration result is accepted only when that state’s meaning matches the business commitment, including required downstream acknowledgement rather than submission alone.
retry_count = 3
interval_seconds = 2
backoff_rate = 2
waits = [interval_seconds * backoff_rate ** i for i in range(retry_count)]
maximum_attempts = 1 + retry_count
total_wait_seconds = sum(waits)
# Original deterministic model: [2, 4, 8], four attempts, 14 seconds waiting.
# Excludes task duration, jitter, caps, redrive and other retriers. Not an AWS execution.In a fictional case, the new flow marks publication complete when the API accepts the job. The consumer has not received the positions yet. APS and business teams review completion state, correlation, and evidence before retiring the legacy batch.
Common pitfalls
Confusing outbox with single delivery, saga with ACID isolation, API response with completion, heartbeat with success, or best-effort logs with complete history.
Related topics: Performance, caching, and evidence
Modernization preserves meaning and recovery when each state, retry, and compensation has a demonstrable contract.
Reference: Strangler fig pattern · SAP-C02