Concord blog · Part 3 of 3

A day in the life

Two parts of theory. One part of seeing it work. The contract isn't real until you watch it execute — so I'll trace a hotel booking through Concord end-to-end and let you toggle the contract on, off, and somewhere in between.

Read ~8 min Series 3 / 3 Previous ← Contract, not runtime

The scenario

A user opens the app and types: "Find me a hotel in Lisbon for July 14-17, around $200 a night, somewhere walkable to Belém."

What follows is the kind of work that didn't really exist three years ago. An agent reads the request, plans, searches a hotel API, ranks the results, recommends one, asks for approval over $500, books the room, charges the card, writes a confirmation, and offers a 24-hour cancellation grace period. Nine steps, give or take, depending on how you count.

Behind those nine steps, a lot of records are being written — or, depending on how the system is built, a lot of records that should be written aren't. The simulation below plays out the same booking three ways: with the full Concord contract, with the minimal useful subset, and with no Concord at all.

Interactive Hotel booking, traced through the contract
0 / 9 steps

Bad, better, best

The simulation makes the spectrum visible. In prose form, here's the same thing said three times.

Bad

The agent calls book_hotel() directly. The charge succeeds. A retry double-charges. The duplicate is found three days later in a postmortem.

Better

The agent proposes a command. Policy fires. The connector has an idempotency key. A duplicate would be deduped at the connector layer, but the policy decision and approval trail aren't durable.

Best

Full chain. Command, policy, approval packet, artifact snapshot, idempotency, compensation graph. The 24-hour cancellation is one row away because the compensation was declared at registration time.

What the developer actually does

The simulation makes Concord look like a lot. From the runtime's perspective, it is. From the developer's perspective, it's declarations, not workflow code.

For the hotel booking, the developer writes something like:

@command_type(
  name="book_hotel",
  policy=hotel_booking_policy,
  approval=hotel_booking_approval,
  produces=[reservation_confirmation],
  invokes=[hotel_booking.book_hotel],
  cancellation_mode="compensate_then_stop",
)
class BookHotel(CommandPayload):
  hotel_id: str
  checkin: date
  checkout: date
  total_cost: Decimal

def hotel_booking_policy(cmd, ctx) -> Decision:
  if cmd.payload.total_cost > 500:
    return require_approval("cost_threshold_500")
  return allow()

That's most of it. The workflow body — the branching on the policy decision, the request to the approval queue, the wait for the human, the invocation of DBOS, the writing of the artifact — Concord generates from the declaration. The developer wrote the what; Concord handled the how.

The win isn't the workflow body. The win is that there is no workflow body — just declarations the runtime knows how to interpret.

This is the day-in-the-life shape. You spend most of your time editing declarations: command types, policies, artifact schemas, connector contracts. You spend almost no time writing workflow plumbing. When something breaks, you read the domain_events table and you can see the contract's trace through your code, in your terms.

The minimal useful Concord

One worry I hear: "this is too much for my small app." Sometimes true. The smallest useful Concord is four primitives:

  • Command — the named action and its payload
  • Policy — the function that returns allow/deny
  • DBOS step — the side effect, executed durably
  • Artifact — the durable output

Approvals, memory, compensation, swarms — all opt-in per command type. The "minimal Concord" mode in the simulation above shows what that looks like for a booking with policy="allow" instead of "require_approval." Three steps are skipped. The remaining six still produce the audit trail and the artifact.

The point isn't that everything has to be Tier 4. The point is that when something earns Tier 4 treatment, the framework already knows what that means.

Three counterarguments I take seriously

"This is a lot of ceremony for booking a hotel"

For a single hotel booking, yes. For an app that books hotels and also runs vendor syncs and also handles support escalations and also approves expense reports, the ceremony amortizes. Concord's bet is that most apps reach the second shape within a year of starting at the first. If your app is going to stay at one workflow, vanilla DBOS is plenty.

"What if I just want a workflow engine?"

Then use DBOS or Temporal directly. Concord is opt-in above them — it doesn't intercept anything. You can run a Concord-free workflow next to a Concord-governed one in the same app. There's no exclusivity.

"What about lock-in?"

The DurableRuntime protocol is the answer I've designed for. Domain code imports the protocol, not the runtime. DBOS is the default adapter; Temporal is the named alternate. If the protocol turns out to be wrong — too narrow, missing methods — that's a Concord problem to fix. The locked-in surface is small by design.

The honest version: I've shipped one adapter so far. The protocol is a promise. Until the Temporal adapter ships, the lock-in concern is reasonable to hold.

Where I might be wrong

The contract may not survive a really weird use case

I built Concord against a few archetypes — hotel booking, vendor sync, revenue investigation swarm. I think the primitive set generalizes, but I'd expect the first novel use case to find an edge I didn't think about. The mitigation isn't to ship more primitives; it's to keep the primitive set small enough that adding one isn't catastrophic.

The Domain Registry may be too rigid for fast-changing apps

Registration-time validation is great for catching mismatches early. It's bad for teams that want to ship five new command types a week and don't want to wait for a build to validate them. Hot-reloadable registry entries are doable but I haven't built them.

I might be over-fitting to enterprise audit requirements

The "audit tier 4" treatment is shaped by what regulated industries need. If you're building a consumer app where nothing is regulated and everything is fast, the tier might feel performative. I think this is the wrong objection — even consumer apps need to know which charge was authorized — but I'd want to test the framing against a few consumer use cases before being confident.

End of series

Three parts. The argument was: agents are starting to initiate real work, durability isn't enough, and a contract layer is what makes the work governable. Concord is one shape of that contract. There are others.

If you want to go deeper, here's where each piece lives.