Logo AgentPay

Settle first. The vault waits.

POST /api/pay returns the settle JSON immediately. Velocity, daily spend, reputation, and HMAC receipts run after commit via ctx.waitUntil — the agent sees ~1 ms, not the full ledger write.


Before

Every pay waited on the full ledger write.

debitWithCredit ran as multi-query. Credit, ledger, velocity, daily spend, rep, and receipt all blocked the JSON.

Always went through debitWithCredit (multi-query) Credit + ledger as separate steps Extra readBalances after debit Sequential: velocity → daily → rep → receipt → idem Failed ledger insert blocked the error response Settlement error after debit had no compensate

After · ctx.waitUntil()

Settle first. Everything else is post-commit.

One UPDATE … RETURNING. One DB.batch for credit + ledger. The client gets balances before the vault finishes.

Fast path: UPDATE … WHERE balance ≥ amount RETURNING One DB.batch: credit recipient + insert tx Reuse debit RETURNING — zero extra balance reads Velocity, daily, rep, receipt, idem via ctx.waitUntil Failed ledger insert deferred when possible Compensating credit back to sender (+ credit undo)

POST /api/pay · advanced flow

Eight steps. The agent only waits for seven.

Rate limit through settle stay on the hot path. Velocity, reputation, and HMAC receipts run after the JSON is already on the wire.

01 Hot

Rate limit + auth

Cookie or Bearer, then fixed-window D1 limits. Unchanged from the previous path.

02 Hot

Safety gate

Wallet lock, policy, budget, velocity. Any fail stops the spend before a debit.

03 Hot

Idempotency lock

Same Idempotency-Key returns the original settle. Retries never double-charge.

04 Hot

Ensure both accounts

Sender and recipient rows in one batch. No extra round trips before debit.

05 Hot

Cash debit

One UPDATE … WHERE balance ≥ amount RETURNING. If short, credit path.

06 Hot

Batch settle

Recipient balance ↑ and ledger row in one DB.batch.

07 ~1 ms

Return JSON

Balances go back immediately. The agent is done waiting. Vault work is not on this clock.

08 · ctx.waitUntil()

The vault runs after commit.

Background jobs are batched. Failed ledger insert is deferred. The client already has the settle.

Velocity windows Daily spent Reputation / credit Receipt HMAC-SHA256 Idempotency finalize Batched, not sequential

Fast path · single statement

One UPDATE … RETURNING. Zero extra reads.

Cash leaves the sender in a single atomic statement. The returned row is reused for the batch credit — no second balance lookup on the hot path.

Hot-path debit Atomic
UPDATE wallets
SET balance = balance - ?
WHERE id = ?
  AND balance >= ?
RETURNING balance, id;

-- if rows === 0 → short, fall to credit path
-- if rows === 1 → reuse returned balance
--   for the batch credit + ledger insert

No multi-query debitWithCredit. No readBalances after the write. The RETURNING clause is the balance the client sees.

Compensating credit

If the batch settle fails after debit, a compensating credit restores the sender. The recipient credit is also undone when possible.

One DB.batch

Recipient balance ↑ and the ledger row travel together. Partial success does not leave the books inconsistent.

Failed insert deferred

When the ledger write can be retried safely, it moves to ctx.waitUntil. The agent already has the settle JSON.


ctx.waitUntil · post-commit

The agent already has the settle.
The vault keeps working.

Velocity windows, daily spent, reputation, and HMAC receipts run after the JSON is on the wire. They never add to the client wait.

0
extra milliseconds on the
client response path
4
background jobs batched
after commit
1
Cloudflare Worker promise
via ctx.waitUntil()

Velocity

Sliding windows updated after settle. Hot path only checks the gate, never writes the counters.

Daily spent

Budget counters incremented in the same background batch. Client never waits on the write.

Reputation

Credit / rep adjustment runs post-commit. A failed adjust does not roll back the settle the agent already saw.

Receipt HMAC

HMAC-SHA256 receipt and idempotency finalize. Deferred when the ledger insert can safely retry.


Hot path · never deferred

Safety and idempotency stay
in front of the debit.

Rate limit, wallet lock, policy, budget, velocity, and the idempotency key all run before a single cent moves. They are not moved into ctx.waitUntil.

01

Rate limit + auth

Cookie or Bearer. Fixed-window D1 limits. Unchanged from the previous path — still the first gate on every request.

Hot path
02

Safety gate

Wallet lock, policy, daily budget, velocity. Any fail stops the spend before the single-statement debit runs.

Hot path
03

Idempotency lock

Same Idempotency-Key returns the original settle. Retries never double-charge. Finalize happens later in the vault.

Hot path

Client wait · before vs after

The agent stops waiting
at settle.

Old path kept the response open until velocity, daily spend, rep, and receipt finished. New path returns the moment balances are written.

Before · sequential

Auth + rate limit

Blocking

Safety gate

Blocking

debitWithCredit (multi-query)

Blocking

Credit + ledger (separate)

Blocking

Velocity → daily → rep → receipt

Blocking

JSON returned

Agent finally unblocked

After · ctx.waitUntil

Auth + rate limit

Hot path

Safety + idempotency

Hot path

UPDATE … RETURNING + batch settle

Hot path

JSON returned · ~1 ms

Agent unblocked here

Velocity + daily (batched)

Post-commit

Rep + receipt HMAC + idem finalize

Post-commit


What the agent can rely on

Balances first.
Everything else is recovery.

The settle JSON is the contract. Background work can fail or defer without changing what the agent already received.

Settle is the response

The agent gets balances and status as soon as the debit and batch credit land. No waiting on velocity, rep, or receipt HMAC.

Compensating credit

If the batch settle fails after debit, the sender is credited back and the recipient credit is undone when possible. Books stay consistent.

Deferred ledger insert

When a ledger write can safely retry, it moves into ctx.waitUntil. The client already has the settle and does not see the delay.

Idempotent by key

Same Idempotency-Key always returns the original settle. Retries never double-debit. Finalize runs in the vault.


Product impact

Agents feel the settle,
not the ledger write.

Every millisecond the response stays open is a millisecond the agent cannot act. Moving post-commit work into ctx.waitUntil cuts that wait without giving up consistency or recovery.

~1 ms

Client wait

Debit + batch settle return immediately. Velocity, daily spend, rep, and HMAC no longer sit on the critical path.

1

Statement debit

Single UPDATE … RETURNING. Zero extra balance reads. Reuse the returned row for the batch credit.

0

Lost settles

Compensating credit on settle failure. Deferred ledger when safe. Idempotency key makes retries safe forever.


Settlement architecture

How the hot path compares
to other agent pay stacks.

Most agent payment systems either wait on a full ledger write, wait on chain confirmation, or sit on card-network latency. AgentPay’s optimized POST /api/pay returns the settle first and moves the rest into ctx.waitUntil.

Approach What the agent waits on Typical settle path Post-settle work
AgentPay · ctx.waitUntil This ~1 ms — debit + batch only Single UPDATE … RETURNING + one DB.batch Velocity, daily, rep, HMAC, idem finalize in background
Synchronous agent ledgers Full multi-query write debitWithCredit + separate credit + ledger + counters None — everything blocks the JSON
x402 (on-chain / facilitator) Verify + settle (L2 or batch) HTTP 402 → signed payload → facilitator → chain On-chain finality; batch schemes amortize later
Skyfire / identity wallets Policy + rail latency KYA identity + spend rules, then underlying rail Depends on chosen rail (stablecoin / card / ACH)
Stripe MPP / card sessions Network + issuer path Session pre-auth or shared payment token Reconciliation in Stripe dashboard; higher micropay floors

AgentPay is not a replacement for x402 or card rails — it is the internal settle engine when the agent already holds a balance on the edge ledger. Other platforms optimize for open HTTP micropayments, identity, or merchant checkout. The differentiator here is client wait: balances return before the vault finishes.


Now

The ledger is open.

Bind a repo. Send a POST. Agents settle — humans stay out of the way.

Join AgentPay

│

Join now
AI Assistant