Skip to content
/practice·retry-safe-workflow

Retry-Safe Workflow

advancedretriestransactionsfailure-handlingdatabase
/concept
Retry-Safe Workflows
Building multi-step operations that survive failures
Read full guide

Problem

Build a multi-step order processing workflow that handles partial failures and can be safely retried without duplicating side effects.

Background

In production systems, multi-step operations (charge payment, reserve inventory, send confirmation) can fail partway through. If the caller retries, a naive implementation might charge the customer twice or send duplicate confirmations.

A retry-safe workflow ensures that:

  • Each step is idempotent or guarded by state tracking
  • Partial completions are detected and resumed (not restarted)
  • The final state is consistent regardless of how many retries occur

Requirements

  • Implement POST /api/orders/process — a multi-step order processing endpoint
  • The workflow has 3 steps: chargereserveconfirm
  • Track each step's completion in the database
  • If the endpoint is called again with the same orderId, resume from where it left off
  • Never execute a completed step again (no double charges, no duplicate reservations)
  • Return the current state of the workflow on each call

Your Server

  • Start an HTTP server on the port specified by the PORT environment variable (default: 3000)
  • A PostgreSQL database is available at the DATABASE_URL environment variable
  • You are responsible for creating any tables you need

API Contract

`GET /health`

Health check. Return 200 when ready.

`POST /api/orders/process`

Process an order through the multi-step workflow.

Request:

json
{
  class="text-pass">"orderId": class="text-pass">"order-123",
  class="text-pass">"amount": 99.99,
  class="text-pass">"item": class="text-pass">"widget"
}

Response:

  • Status: 200
  • Body:
json
{
  class="text-pass">"orderId": class="text-pass">"order-123",
  class="text-pass">"status": class="text-pass">"completed",
  class="text-pass">"steps": {
    class="text-pass">"charge": { class="text-pass">"completed": true },
    class="text-pass">"reserve": { class="text-pass">"completed": true },
    class="text-pass">"confirm": { class="text-pass">"completed": true }
  }
}

Step Details

  • charge: Records a payment charge for the given amount. Sets charge.completed = true.
  • reserve: Reserves the item in inventory. Sets reserve.completed = true.
  • confirm: Finalizes the order. Sets confirm.completed = true and overall status = "completed".

Each step should only execute if it hasn't been completed yet for this orderId.

Status Values

  • "pending" — workflow has not started
  • "charging" — charge step in progress
  • "reserving" — reserve step in progress
  • "confirming" — confirm step in progress
  • "completed" — all steps done
  • "failed" — a step failed (for future use)
Scenarios·4 visible + hidden

Your solution will be tested against these scenarios plus a hidden set.

  1. 01POST /api/orders/process completes all 3 steps and returns completed status
  2. 02Calling process again with the same orderId returns completed without re-executing steps
  3. 03Response includes step-by-step completion status
  4. 04Different orderIds are processed independently

Hints

Click each hint to reveal it. Take your time — try before you peek.