This document is the dense reference companion to the public guide Middleware performance and latency. It maps the HTTP hops Kit middleware triggers per guarded tool call, documents Gateway rate limits and timeouts, and states what observability exists today.
Paybond does not publish Kit p50/p99 benchmarks. Treat all duration guidance as qualitative unless you measure in your own environment.
Design principles
- Serial hops per guarded call. The interceptor authorizes, executes the handler, completes the spend decision, then submits evidence — in order. There is no batch verify API for multiple tools in one HTTP request.
- Gateway composes policy; Harbor authorizes capability.
POST /verifyalways reaches Harbor for capability validation when Harbor is configured. Gateway may add Postgres idempotency and spend-policy evaluation around that forward. - Evidence path differs by bind mode. Sandbox binds use Gateway guardrails evidence composition. Production attach binds sign payee evidence locally and call
/harbor/intents/{id}/evidencethrough recognition and fraud gates. - Kit runs off-platform. Production latency observation defaults to Gateway/Harbor SLIs and partner APM — not Paybond-hosted Kit telemetry.
Hop model (production attach)
sequenceDiagram
autonumber
actor Kit as Kit interceptor
participant GW as Gateway
participant PG as Postgres
participant HB as Harbor
Kit->>GW: POST /verify (Bearer API key)
GW->>PG: Idempotency and spend policy
GW->>HB: POST /verify (mTLS, 30s timeout)
HB-->>GW: allow / deny and audit
GW-->>Kit: decision_id, audit_id
Note over Kit: Local tool handler (durationMs in trace only)
Kit->>GW: POST /v1/spend/decisions/{id}/complete
opt stripe_mpp session metering
GW->>HB: Voucher finalize (internal forward)
end
GW-->>Kit: consumed / released
Kit->>Kit: Sign payee evidence and recognition proof
Kit->>GW: POST /harbor/intents/{id}/evidence
GW->>GW: Recognition verify and fraud hardening
GW->>HB: POST /intents/{id}/evidence (mTLS)
HB-->>GW: predicate_passed, evaluation
GW-->>Kit: 200 JSONHop summary table
| Step | Kit API / trigger | Gateway route | Harbor route | Notes |
|---|---|---|---|---|
| 1 Authorize | guard.assertSpendAuthorized | POST /verify | POST /verify | Spend policy and idempotency in Gateway |
| 2 Execute | User handler | — | — | Not a Paybond HTTP hop |
| 3 Complete | guard.completeSpendAuthorization | POST /v1/spend/decisions/{decision_id}/complete | Optional voucher finalize via internal forward | MPP session mode only |
| 4 Evidence (sandbox) | guardrails.submitSandboxEvidence | Composed guardrails evidence | Harbor evidence via internal forward | Simulator lifecycle |
| 4 Evidence (production) | harbor.submitEvidence | POST /harbor/intents/{id}/evidence | POST /intents/{id}/evidence | Recognition and fraud gate before proxy |
Settlement confirm (POST /harbor/intents/{id}/settlement/confirm) is outside the default auto-evidence interceptor path unless your app calls it explicitly after evidence.
Sandbox and offline paths
| Mode | Network hops | Representative use |
|---|---|---|
paybond dev loop --offline | 0 Paybond HTTP calls | Policy rehearsal, trace UX |
Sandbox bind (instrument({ sandbox: true })) | Verify and complete and guardrails evidence against sandbox tenant | Integration tests, paybond dev loop |
| Production attach | Full hop table above | Live funded intents |
Offline mode does not predict production latency.
Authorization cache
Split authorize / execute frameworks can avoid a second /verify when:
| Constant | Value | Source |
|---|---|---|
| TTL | 120 seconds | AUTHORIZATION_CACHE_TTL_SEC |
| Cache key | {toolCallId}:{operation} | authorization-cache.ts |
| Match fields | operation, requestedSpendCents, toolName | Must match at wrapExecute time |
Implementation: kit/ts/src/agent/authorization-cache.ts (Python parity in paybond_kit.agent).
Gateway timeouts and retries
Harbor client timeout
Gateway Harbor HTTP clients use a 30 second request timeout, including:
CallHarborVerify(go/gateway/internal/spend/spendauth/harbor.go)- intent mutation proxies (
go/gateway/internal/httpserver/harbor.go) - Sandbox guardrail Harbor forwards (
sandbox_guardrails.go)
Kit SDK retry loop
Default maxRetries: 3 on Paybond / HarborClient gateway HTTP (kit/ts/src/index.ts).
| Behavior | Detail |
|---|---|
| Retriable status | 429, 500, 502, 503, 504 |
| Backoff | 200 * 2^attempt ms and jitter, cap 5000 ms (backoffMs) |
Retry-After header | Honored, cap 30 seconds |
| Cloudflare edge body | cloudflare_error: true — max 8000 ms delay, max 1 extra retry |
| Non-retriable | Cloudflare edge errors after one retry; other 4xx |
Tail latency on upstream blips can reach several seconds across retries — not represented in dev trace events.
Rate limits (default Gateway windows)
Per-tenant unless noted. Source: go/gateway/internal/httpserver/router.go.
| Limiter key | Default quota | Window | Applies to |
|---|---|---|---|
verify_capability | 240 | 1 minute | POST /verify |
mpp_voucher_verify | 120 (env override) | 1 minute | /verify with x-paybond-payment-authorization |
harbor_proxy_read | 120 | 1 minute | Harbor operator GET proxies |
Exceeding limits returns 429 with Retry-After — interacts with SDK retry backoff.
Spend-policy evaluation may contend on Postgres rows during high /verify concurrency; scope policies narrowly for hot operations.
Trace event limits
PaybondTraceEvent (kit/ts/src/agent/types.ts) exposes phase timestamps and handler timing only.
| Event | Latency field | Includes Paybond HTTP RTT? |
|---|---|---|
tool_executed | durationMs | No — local handler only |
spend_authorized | — | No |
evidence_submitted | — | No |
spend_finalized | — | No |
Dev trace (paybond dev trace, .paybond/dev-trace.jsonl) and hosted /demo/agent-trace replay use the same vocabulary. They are phase debuggers, not network profilers.
There are no authorize_duration_ms or evidence_duration_ms fields in the shipped trace schema today.
Production observability map
| Layer | What to monitor | Document |
|---|---|---|
| Gateway → Harbor | Error rate, harbor_unreachable, p99 upstream duration | Monitor in your APM / Gateway metrics |
| Gateway OTEL | otelhttp spans when OTLP configured | Gateway OpenTelemetry when enabled |
| Harbor | /health, recovery errors, stuck intents | Console intent dossier and Gateway errors |
| Partner APM | Span around wrapExecute / authorizeToolCall with intent_id, operation | This doc — bring your own |
| Signal indexer | Ledger lag, receipt 404 spikes | Signal console and Gateway provenance |
| Console | Intent dossier, agent-run timeline | Middleware trace |
Kit does not phone home per-tool latency unless you wire traceSink or Gateway agent-run reporting.
Qualitative sizing guidance
| Workload | Expectation |
|---|---|
| Fast tool (<50ms handler) | Paybond serial hops often dominate wall time |
| Slow tool (seconds+) | Handler dominates; middleware overhead is a smaller fraction |
| High fan-out (many tools per turn) | Multiply hops per side-effecting tool; watch verify_capability quota |
| MPP session mode | Extra verify header processing and optional voucher finalize on complete |
| Predicate failure | HTTP 200 with predicate_passed: false — not a transport retry (Disputes and evidence evaluation) |
Order-of-magnitude on healthy same-region hosted infra: ~20–150ms per Paybond HTTP hop, plus handler time and retry tails on errors.
Related documentation
- Public guide: Middleware performance and latency
- Integration: Agent middleware
- Trace phases: Middleware trace
- Evidence signing cost path: Evidence & artifacts
- Support matrix (what Kit does not ship): Support matrix