Rate limit + auth
Cookie or Bearer, then fixed-window D1 limits. Unchanged from the previous path.
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
debitWithCredit ran as multi-query. Credit, ledger, velocity, daily spend, rep, and receipt all blocked the JSON.
After · ctx.waitUntil()
One UPDATE … RETURNING. One DB.batch for credit + ledger. The client gets balances before the vault finishes.
POST /api/pay · advanced flow
Rate limit through settle stay on the hot path. Velocity, reputation, and HMAC receipts run after the JSON is already on the wire.
Cookie or Bearer, then fixed-window D1 limits. Unchanged from the previous path.
Wallet lock, policy, budget, velocity. Any fail stops the spend before a debit.
Same Idempotency-Key returns the original settle. Retries never double-charge.
Sender and recipient rows in one batch. No extra round trips before debit.
One UPDATE … WHERE balance ≥ amount RETURNING. If short, credit path.
Recipient balance ↑ and ledger row in one DB.batch.
Balances go back immediately. The agent is done waiting. Vault work is not on this clock.
08 · ctx.waitUntil()
Background jobs are batched. Failed ledger insert is deferred. The client already has the settle.
Fast path · single statement
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.
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.
If the batch settle fails after debit, a compensating credit restores the sender. The recipient credit is also undone when possible.
Recipient balance ↑ and the ledger row travel together. Partial success does not leave the books inconsistent.
When the ledger write can be retried safely, it moves to ctx.waitUntil. The agent already has the settle JSON.
ctx.waitUntil · post-commit
Velocity windows, daily spent, reputation, and HMAC receipts run after the JSON is on the wire. They never add to the client wait.
Sliding windows updated after settle. Hot path only checks the gate, never writes the counters.
Budget counters incremented in the same background batch. Client never waits on the write.
Credit / rep adjustment runs post-commit. A failed adjust does not roll back the settle the agent already saw.
HMAC-SHA256 receipt and idempotency finalize. Deferred when the ledger insert can safely retry.
Hot path · never deferred
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.
Cookie or Bearer. Fixed-window D1 limits. Unchanged from the previous path — still the first gate on every request.
Wallet lock, policy, daily budget, velocity. Any fail stops the spend before the single-statement debit runs.
Same Idempotency-Key returns the original settle. Retries never double-charge. Finalize happens later in the vault.
Client wait · before vs after
Old path kept the response open until velocity, daily spend, rep, and receipt finished. New path returns the moment balances are written.
Before · sequential
Blocking
Blocking
Blocking
Blocking
Blocking
Agent finally unblocked
After · ctx.waitUntil
Hot path
Hot path
Hot path
Agent unblocked here
Post-commit
Post-commit
What the agent can rely on
The settle JSON is the contract. Background work can fail or defer without changing what the agent already received.
The agent gets balances and status as soon as the debit and batch credit land. No waiting on velocity, rep, or receipt HMAC.
If the batch settle fails after debit, the sender is credited back and the recipient credit is undone when possible. Books stay consistent.
When a ledger write can safely retry, it moves into ctx.waitUntil. The client already has the settle and does not see the delay.
Same Idempotency-Key always returns the original settle. Retries never double-debit. Finalize runs in the vault.
Product impact
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.
Debit + batch settle return immediately. Velocity, daily spend, rep, and HMAC no longer sit on the critical path.
Single UPDATE … RETURNING. Zero extra balance reads. Reuse the returned row for the batch credit.
Compensating credit on settle failure. Deferred ledger when safe. Idempotency key makes retries safe forever.
Settlement architecture
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
Bind a repo. Send a POST. Agents settle — humans stay out of the way.
Join AgentPay│