Failure is part
of engineering.
Losing work
is a choice.

Rockets blow up on the pad. Workers die mid-payment. Write your steps as ordinary code and Hopskip journals every one, so when the process craters, the work walks away and finishes somewhere else. Nothing charged twice. Nothing left half-done.

THREAT MODEL - WILL YOUR RUN SURVIVE?
kill -9, OOM, panic✓ survives
deploy mid-payment✓ survives
region catches fire✓ survives
meteor hits the datacenter✓ survives*
nuclear apocalypse✓ survives†
heat death of the universe✗ roadmap
*untested, but the journal is in a different blast radius and we like its odds. †your customers may have churned.
LIVE · checkout.order_8842worker_03 · READY
reserve_inventory sku:ABCqueued
charge_card amount:20.00queued
ship_order carrier:defaultqueued
notify_customer emailqueued
JOURNAL · SURVIVES THE WORKER
frame 0frame 1frame 2frame 3
worker_03 is waiting for a run

go on. it's insured.

Resumeafter crashes, deploys, and other acts of engineering
Waitseconds, days, or months
Inspectstate, attempts, failures
Replaythe recorded path, not logs

THE PROBLEM

Starting a job is easy.
Finishing the whole process is not.

A queue can deliver a message. It cannot tell you which business steps already succeeded, whether a retry is safe, or how to continue after a deploy. Soon the process is scattered across workers, retry loops, status tables, cron jobs, and recovery scripts, with the important state living in the gaps between them.

Hopskip keeps the process and its progress together. That is durable execution: application code that can stop, wait, fail, and continue without forgetting where it was.

Three moves.
No choreography.

The full mechanics →
01

Write steps as code

No DSL, no YAML, no state machine diagrams. A workflow is a function; a step is a call.

await hop.step("charge_card",
() => stripe.charge(order));
await hop.sleep("cooloff", "30d");
02

Every step is journaled

Each completed step commits a frame to the journal. The worker holds nothing that matters.

0 ✓1 ✓2 …3
state_bytes 4096 · fsync ok
03

Crash. Replay. Continue.

When a worker dies, another one replays the journal, skips committed steps, and picks up mid-process.

worker_03 ✗ SIGKILL @ frame 1
journal → replay 1 frame
worker_07 ✓ resumed, attempt 2

WHERE IT EARNS ITS KEEP

The work that must finish

Payments & billing

Charge once, exactly once, even when the process dies mid-capture.

authorize → capture → invoice → dunning(30d)

Order fulfillment

Inventory, carrier, tracking, refund windows, a week-long process in one function.

reserve → charge → ship → sleep(7d) → close

User onboarding

Drip sequences and trials that survive every deploy between day 0 and day 30.

welcome → sleep(3d) → nudge → convert

Data pipelines

Extract, transform, load, and re-run from the failed step, not from zero.

extract → transform → validate → load → verify

Ship code that
outlives its process.

no per-step billing · no imaginary recovery promises