Keeping RPC abusers from taking your whole cluster down
Introduction
If you expose blockchain nodes or indexers over HTTP, you are running an API that can be abused.
A few common scenarios:
- one customer opens 1,000 WebSocket subscriptions to the mempool
- a bot forgets to back off on errors and hammers
eth_call - a “free” tier user runs a full backfill through your public endpoint
Rate limiting and quotas are what stand between you and a very expensive outage.
Short‑term rate limits protect infrastructure in real time. Long‑term quotas enforce business constraints and pricing (free vs paid tiers, per‑customer budgets). Cloud API platforms make the same distinction: rate limits are about burst and per‑second/minute safety; quotas are about per‑day/month contracts and cost control. (Microsoft Learn)
I’ll walk through how I design both for blockchain APIs: token‑bucket rate limits, per‑user quotas, and tiered plans that look a lot like what Infura, Alchemy, QuickNode and others expose. (Medium)
1. What you are protecting
Conceptually, the pipeline looks like this:
[ Clients / Bots / dApps ]
|
(API key)
|
[ API Gateway ]
|
+---------+-----------+
| Rate limiter |
| Quota tracker |
+---------+-----------+
|
[ RPC nodes / indexers ]
You’re trying to:
- protect nodes and indexers from overload and “hot” methods
- prevent one tenant from starving others (noisy neighbour)
- align usage with what you actually sell (“N requests per month”, “X RPS”)
Modern rate‑limiting guides say the same thing: control bursts to protect infrastructure, and use quotas to govern longer‑term consumption and monetisation. (Zuplo)
2. Rate limits vs quotas
I keep a clear mental split:
Rate limit
- short window (seconds/minutes)
- protects capacity and avoids sudden overload
- implemented with token bucket / sliding window counters
Quota
- long window (hours/days/months)
- enforces plan limits and cost controls
- implemented as counters in a DB or usage store
Cloud API management docs make this explicit too: rate limits are about “requests per second/minute”; quota policies are renewable counters over longer periods, often keyed by subscription or API key. (Microsoft Learn)
For a blockchain API that usually means:
Rate limits
- e.g. 50 requests/second per key
- bursty but controlled
Quotas
- e.g. 10M requests/month on free,
80M on paid, 2B on enterprise
Those numbers look very similar to what commercial node providers publish for their free and paid tiers. (Medium)
3. Token bucket as the default algorithm
There are several rate‑limiting algorithms: fixed window, sliding window, leaky bucket, token bucket. Recent overviews all list the same four and generally recommend token or sliding window for most APIs. (API7)
For blockchain APIs I default to token bucket.
Intuition:
- Each key has a bucket.
- Tokens are added at a steady rate (say 50/sec).
- Each request consumes 1 token.
- If the bucket is empty, the request is rejected (or delayed).
- Bucket has a max size, so short bursts are allowed.
ASCII:
+-------------------+
| Token bucket |
|-------------------|
+--> | +1 token / 20 ms |
| | capacity: 100 |
| +-------------------+
| |
| token v
Request ---> [ allow ] or [ 429 Too Many Requests ]
Token bucket is:
- simple to reason about
- good at smoothing sustained traffic while allowing bursts
- widely implemented in gateways like Envoy and Istio’s local rate limit filter, and in NGINX modules (often paired with leaky‑bucket shaping). (Envoy Proxy)
For very spiky or very large systems you may climb to distributed sliding‑window implementations, but token bucket at the edge already solves most practical problems.
4. What you limit on: keys, users, methods
The hard part is not the algorithm; it’s choosing the identity you rate‑limit.
For blockchain APIs typical keys are:
- API key / project id
- user id (if you front with auth)
- IP address (last resort, for anonymous/public)
- wallet address (sometimes for public dApps)
Best‑practice material on rate limiting and quotas talks about “key‑level” limits: assign limits per API key, subscription or tenant, not just per IP. (Zuplo)
In blockchain I almost always limit per API key, with IP‑based limits as a coarse safety net for public endpoints.
Then I split by method type:
- cheap calls (latest block, simple balance lookup)
- expensive calls (deep history, archive state, traces)
- write‑like calls (sendRawTransaction, mempool subscriptions)
API rate‑limit best‑practice guides recommend this kind of resource‑based limit: heavier endpoints get tighter caps than light ones. (Zuplo)
For example:
- 100 r/s per key overall
- 20 r/s per key on trace/debug endpoints
- 5 concurrent WebSocket subscriptions per key
Envoy’s descriptors and similar mechanisms in gateways are made for this: you can define separate buckets by key + method or path. (Envoy Proxy)
5. Quotas: counting the bigger picture
Quotas track how much of your service a tenant uses over larger windows.
Think:
- free: 10M requests/month
- startup: 80M
- scale: 950M
- enterprise: 2B+
Those numbers are in the same ballpark as published plans from major node providers and gateway products, which all expose per‑month request quotas by tier. (Medium)
API governance and monetisation articles make the same point:
- rate limits protect infrastructure
- quotas are how you implement pricing, fair use and cost ceilings (Moesif)
Implementation sketch (conceptual, not code):
Per API key:
- rolling counters per period:
monthRequests, dayRequests, hourRequests
- tier config:
maxMonth, maxDay, maxHour
On each accepted request:
- increment counters in a shared store
- if any limit exceeded, mark as over-quota
Cloud platforms expose this as “quota” policies, often renewable over a period and keyed by subscription or custom keys. (Microsoft Learn)
You don’t have to count every single endpoint equally. For blockchain APIs it’s common to:
- count expensive methods as >1 “credit”
- count archive/tracing calls as much higher weight
- exclude cheap health checks from quotas
That maps the quota system closer to your actual cost.
6. Tiered access levels
Once rate limits and quotas are in place, tiers are just named bundles.
A simple tier table:
Tier RPS limit Monthly quota Features
-------------------------------------------------------------
Free 5 r/s 10M requests mainnet/testnet, no WS
Builder 25 r/s 80M requests WS, logs, some archive
Pro 100 r/s 450M+ archive, tracing, mempool
Enterprise custom 2B+ or custom dedicated infra, SLAs
This is very close to what public providers actually sell: free tier with small daily/monthly caps, several paid tiers with increasing request quotas and features, and an enterprise option with custom limits and SLAs. (Medium)
Rate‑limit best‑practice articles explicitly call out “tiered rate limits” as a way to segment users and monetise APIs. (API7)
From an implementation point of view:
Tier -> configuration:
- maxRps
- burstSize
- perMethod weights and caps
- quotas (per day / month / chain)
Your rate limiter and quota service just read the config; the business logic lives in the tier definitions.
7. Architecture: where the limiter lives
There are three broad places to enforce limits:
1. At the edge proxy / gateway (NGINX, Envoy, API gateway)
2. In a dedicated rate limit service (with Redis or similar)
3. In application code
Gateway docs and articles on NGINX and Envoy show both built‑in local rate limits (per instance) and integration with external, centralized limiters. (Solo)
For a blockchain API under load, I prefer a two‑layer approach.
ASCII:
[ Client ]
|
v
[ Edge proxy ]
| (cheap, local token bucket: immediate 429 on crazy spikes)
v
[ Rate limit/quota service ]
| (global, per-key decisions + counters)
v
[ Backend / nodes / indexers ]
The local limiter in the proxy stops obvious floods close to the network edge, with minimal latency and no cross‑node coordination. The central limiter tracks per‑key usage and quotas across the cluster.
A high‑volume design doc for rate limiting systems calls out exactly this pattern: local fast‑path limits near the gateway plus a scalable central store for per‑key counters and configuration. (Medium)
8. Blockchain‑specific wrinkles
A few things are nastier in blockchain than in generic APIs.
Method cost variance.
eth_blockNumber and eth_getLogs do not cost the same. You either:
- classify methods into cost classes and assign different token weights, or
- maintain a dynamic cost model based on historical CPU/time per method.
Multi‑chain tenants. One customer calling Ethereum mainnet archive state and another only hitting a small sidechain shouldn’t pay the same. Some providers expose separate quotas per chain or charge “credits” differently by network and method; you can copy that idea. (Alchemy)
WebSockets and subscriptions. Long‑lived connections watching the mempool or specific logs are not simple “requests”. I usually count:
- concurrent subscriptions per key
- messages per second per connection
- total bytes per period
and enforce separate limits, otherwise a few chatty sockets bypass your HTTP rate limits entirely.
Anonymous vs authenticated. Public, keyless RPC endpoints will be attacked. Anonymous limits should be very low and mostly there to let users bootstrap and obtain a key. Everything serious should go through a per‑key limiter.
9. Behaviour and headers
How you fail matters for integrators.
Basic behaviour most clients now expect:
- 429 Too Many Requests when hitting rate limits
- 403 or 402-style response when over quota (depending on billing model)
- Retry-After header to signal backoff window
- X-RateLimit-* headers to signal current window and remaining tokens
Gateways and API management products tend to follow this pattern: 429 for rate limits, quota exhaustion often as 403 with specific headers. (Microsoft Learn)
On blockchain APIs I also include:
- a clear error code in the body (e.g. RATE_LIMITED, QUOTA_EXCEEDED)
- current plan / tier info when over quota, if disclosure is OK
so bots and SDKs can distinguish “back off” from “upgrade your plan or stop”.
10. Experience callouts
Two things I’ve learned doing this around high‑throughput indexers and RPC gateways.
First, start by protecting expensive endpoints, not everything equally. On one BSC indexer, simply adding tight per‑key limits on getLogs and archive‑state calls removed 80% of the pathological traffic. Light calls like “latest block” were cheap to serve anyway.
Second, design the limiter and quotas with product in the loop. On a multi‑chain platform, the most useful quotas were not generic “N requests per month”. They were: “archive requests”, “trace requests”, “WebSocket subscriptions to mempool”. That mapping came from real usage and from how we were billed by our own upstream node providers.
Rate‑limiting and quota design papers make the same point: good limits come from real traffic analysis and clear goals, not just arbitrary numbers in config files. (Zuplo)
Conclusion
Fair usage for blockchain APIs is not magic; it’s a handful of deliberate choices:
- Separate fast, local rate limits from slower, long-window quotas.
- Use token buckets (or sliding windows) per key to smooth bursts.
- Tie quotas and limits to tiers, methods and chains, not just raw RPS.
- Implement a two-layer architecture: edge limiter + central usage service.
- Make behaviour predictable: clear status codes, headers, and error bodies.
Do that, and you get an API where a single misconfigured bot can’t saturate your cluster, serious customers get the throughput they paid for, and your infrastructure bill stays roughly where you expect it—even when mainnet gets busy.
Completion scope and production contract
This completion review turns the earlier conceptual treatment into a release-oriented engineering contract. It treats API Rate Limiting and Quota Management as a typed web, wallet, or blockchain API component, follows a user intent, API representation, wallet request, stream update, or transaction lifecycle event through validation and durable state, and separates normative requirements from implementation policy. The normative baseline is the published API or wallet specification, TypeScript model, and chain confirmation rules; deployment defaults, caching, retry limits, and operator thresholds are explicitly local policy. 11
The intended audience is experienced developers and architects. Readers should understand the surrounding chain or application model, typed data structures, persistence, and basic security engineering. The scope includes correctness, implementation boundaries, deterministic tests, failure recovery, security, performance, and observability. It does not claim that the educational companion is a drop-in replacement for a maintained protocol or cryptographic library. Production adoption requires an independent threat model, compatibility testing against the authoritative implementation, and operational ownership. 12
The mental model used throughout is deliberately strict: untrusted input crosses browser, wallet extension, transport, API, cache, and accessibility boundaries; a validator derives facts under the published API or wallet specification, TypeScript model, and chain confirmation rules; accepted transitions update server-derived data, wallet session, UI intent, and explicit transaction state; and observers consume committed facts, never optimistic intermediate mutations. A guarantee is stated only when it follows from those rules and assumptions. Heuristics such as fee selection, caching, peer scoring, timeouts, user messaging, or alert thresholds remain policy and may be tuned without redefining validity. 13
Reader contract and scope
For API Rate Limiting and Quota Management, this review makes the exact user decision and the prerequisites needed to make it safely explicit. Start from one user intent, API representation, wallet request, stream update, or transaction lifecycle event and write down its origin, canonical representation, validation context, authority, and durable outcome. The typed web, wallet, or blockchain API component must not infer a stronger fact from transport success, cache presence, or an upstream acknowledgement. Its authoritative state is server-derived data, wallet session, UI intent, and explicit transaction state, and every projection must remain rebuildable or reconcilable from committed facts. This framing distinguishes a protocol guarantee from an operational convenience and gives reviewers a concrete place to challenge an assumption. 11
The principal failure to design against is an attractive example being mistaken for a complete production design. Address it before optimizing by defining a narrow ownership boundary, stable identities, bounded resource use, and a machine-readable outcome for every rejected transition. Record a scope statement, excluded concerns, and a reviewable acceptance criterion. A reviewer should be able to trace each accepted result to input bytes, rule or policy version, prior state, and commit identity without relying on prose logs. When the authority cannot be reached or context is incomplete, return an explicit unavailable or pending state; do not convert uncertainty into acceptance.
Precise vocabulary and authority
Treat precise vocabulary and authority as part of the executable design of API Rate Limiting and Quota Management, not as documentation added after coding. The relevant operating envelope includes initial load, pagination, reconnect, chain switch, signing, pending confirmation, and partial API failure. For each mode, identify which state is authoritative, which work may be retried, what is bounded, and which observation proves progress. This is especially important across browser, wallet extension, transport, API, cache, and accessibility boundaries, where delivery and processing are different events and where local time or arrival order may not reflect authoritative order. 12
A useful review asks how the design behaves under stale closure, duplicate update, wallet rejection, chain mismatch, schema drift, reconnect storm, and misleading confirmation. The unsafe outcome is teams using the same word for incompatible states or guarantees. Prevent it with explicit preconditions and postconditions, and retain a glossary tied to the normative authority for every overloaded term as release evidence. Use stable codes rather than exception text, keep policy configuration versioned, and attach the accepted policy or rule version to durable results. An frontend or API-platform operator must be able to stop intake, drain or quarantine work, compare local state with authority, and resume without inventing a second side effect.
Trust assumptions
The implementation of API Rate Limiting and Quota Management should expose which actors, clocks, stores, libraries, and upstream systems may fail or act maliciously through types and module boundaries. Parse external representations once, preserve the original identity when audit or replay needs it, and pass validated domain values inward. Mutations of server-derived data, wallet session, UI intent, and explicit transaction state belong behind one authoritative transition function or transaction boundary. Network clients, storage adapters, user interfaces, and telemetry exporters must not duplicate consensus or business rules. That separation keeps deterministic logic testable and prevents a library upgrade from silently redefining validity. 13
Assume that an implicit trusted component invalidating the claimed guarantee will eventually occur in a staging fault test or production incident. The control is not a catch-all retry: classify the outcome, decide whether the identical operation is safe to repeat, bound attempts and elapsed time, and surface terminal work for reconciliation. The minimum evidence is a trust-boundary diagram and an assumption register with owners. Keep addresses, wallet permissions, access tokens, KYC data, transaction intent, and browser storage out of ordinary logs, and prefer hashes, version identifiers, counts, and sanitized reason codes. Any emergency bypass must be narrow, time-limited, approved, and observable.
Architecture and ownership
Verification for API Rate Limiting and Quota Management must demonstrate component responsibilities and the direction in which facts and commands move at several layers. Small tests cover deterministic transforms and boundary values; contract tests pin serialized forms; integration tests exercise real adapters; replay tests compare state roots or projections; and fault tests interrupt work at every commit boundary. The dataset must include normal history, malformed input, duplicates, reordering, maximum-size values, and changes of rule or schema version. A passing example is evidence about that environment and dataset, not a universal performance claim. 11
Make two components both believing they own the same transition a named negative test. The release packet should retain a context diagram, ownership table, and dependency rule, exact dependency and tool versions, the deterministic command, and its result. For performance work, report warm-up, repetitions, concurrency, percentiles, resource limits, and the point where backpressure begins. For security work, include abuse cases and independent review. A change is ready only when failures leave server-derived data, wallet session, UI intent, and explicit transaction state safe, recovery is rehearsed, and telemetry explains both user-visible outcome and operator action.
Canonical representation
For API Rate Limiting and Quota Management, this review makes the byte-level or schema-level representation used for hashing, comparison, storage, and transport explicit. Start from one user intent, API representation, wallet request, stream update, or transaction lifecycle event and write down its origin, canonical representation, validation context, authority, and durable outcome. The typed web, wallet, or blockchain API component must not infer a stronger fact from transport success, cache presence, or an upstream acknowledgement. Its authoritative state is server-derived data, wallet session, UI intent, and explicit transaction state, and every projection must remain rebuildable or reconcilable from committed facts. This framing distinguishes a protocol guarantee from an operational convenience and gives reviewers a concrete place to challenge an assumption. 12
The principal failure to design against is semantically equal values producing different identifiers or verification outcomes. Address it before optimizing by defining a narrow ownership boundary, stable identities, bounded resource use, and a machine-readable outcome for every rejected transition. Record golden encodings, round-trip tests, and rejection of non-canonical forms. A reviewer should be able to trace each accepted result to input bytes, rule or policy version, prior state, and commit identity without relying on prose logs. When the authority cannot be reached or context is incomplete, return an explicit unavailable or pending state; do not convert uncertainty into acceptance.
State-machine model
Treat state-machine model as part of the executable design of API Rate Limiting and Quota Management, not as documentation added after coding. The relevant operating envelope includes initial load, pagination, reconnect, chain switch, signing, pending confirmation, and partial API failure. For each mode, identify which state is authoritative, which work may be retried, what is bounded, and which observation proves progress. This is especially important across browser, wallet extension, transport, API, cache, and accessibility boundaries, where delivery and processing are different events and where local time or arrival order may not reflect authoritative order. 13
A useful review asks how the design behaves under stale closure, duplicate update, wallet rejection, chain mismatch, schema drift, reconnect storm, and misleading confirmation. The unsafe outcome is an impossible intermediate state becoming durable after interruption. Prevent it with explicit preconditions and postconditions, and retain a transition table exercised by positive, negative, and replay tests as release evidence. Use stable codes rather than exception text, keep policy configuration versioned, and attach the accepted policy or rule version to durable results. An frontend or API-platform operator must be able to stop intake, drain or quarantine work, compare local state with authority, and resume without inventing a second side effect.
Invariants
The implementation of API Rate Limiting and Quota Management should expose properties that must hold before and after every accepted operation through types and module boundaries. Parse external representations once, preserve the original identity when audit or replay needs it, and pass validated domain values inward. Mutations of server-derived data, wallet session, UI intent, and explicit transaction state belong behind one authoritative transition function or transaction boundary. Network clients, storage adapters, user interfaces, and telemetry exporters must not duplicate consensus or business rules. That separation keeps deterministic logic testable and prevents a library upgrade from silently redefining validity. 11
Assume that local success concealing corruption in a related aggregate or index will eventually occur in a staging fault test or production incident. The control is not a catch-all retry: classify the outcome, decide whether the identical operation is safe to repeat, bound attempts and elapsed time, and surface terminal work for reconciliation. The minimum evidence is executable assertions at the narrowest authoritative boundary. Keep addresses, wallet permissions, access tokens, KYC data, transaction intent, and browser storage out of ordinary logs, and prefer hashes, version identifiers, counts, and sanitized reason codes. Any emergency bypass must be narrow, time-limited, approved, and observable.
Validation pipeline
Verification for API Rate Limiting and Quota Management must demonstrate cheap structural checks, contextual checks, authoritative verification, and commit order at several layers. Small tests cover deterministic transforms and boundary values; contract tests pin serialized forms; integration tests exercise real adapters; replay tests compare state roots or projections; and fault tests interrupt work at every commit boundary. The dataset must include normal history, malformed input, duplicates, reordering, maximum-size values, and changes of rule or schema version. A passing example is evidence about that environment and dataset, not a universal performance claim. 12
Make expensive or stateful work running before malformed input is rejected a named negative test. The release packet should retain ordered validation stages with stable machine-readable rejection codes, exact dependency and tool versions, the deterministic command, and its result. For performance work, report warm-up, repetitions, concurrency, percentiles, resource limits, and the point where backpressure begins. For security work, include abuse cases and independent review. A change is ready only when failures leave server-derived data, wallet session, UI intent, and explicit transaction state safe, recovery is rehearsed, and telemetry explains both user-visible outcome and operator action.
Error semantics
For API Rate Limiting and Quota Management, this review makes the distinction between invalid input, conflict, unavailable dependency, retryable interruption, and internal defect explicit. Start from one user intent, API representation, wallet request, stream update, or transaction lifecycle event and write down its origin, canonical representation, validation context, authority, and durable outcome. The typed web, wallet, or blockchain API component must not infer a stronger fact from transport success, cache presence, or an upstream acknowledgement. Its authoritative state is server-derived data, wallet session, UI intent, and explicit transaction state, and every projection must remain rebuildable or reconcilable from committed facts. This framing distinguishes a protocol guarantee from an operational convenience and gives reviewers a concrete place to challenge an assumption. 13
The principal failure to design against is blind retries amplifying a permanent failure or changing user intent. Address it before optimizing by defining a narrow ownership boundary, stable identities, bounded resource use, and a machine-readable outcome for every rejected transition. Record typed errors mapped consistently across logs, metrics, APIs, and queues. A reviewer should be able to trace each accepted result to input bytes, rule or policy version, prior state, and commit identity without relying on prose logs. When the authority cannot be reached or context is incomplete, return an explicit unavailable or pending state; do not convert uncertainty into acceptance.
Concurrency control
Treat concurrency control as part of the executable design of API Rate Limiting and Quota Management, not as documentation added after coding. The relevant operating envelope includes initial load, pagination, reconnect, chain switch, signing, pending confirmation, and partial API failure. For each mode, identify which state is authoritative, which work may be retried, what is bounded, and which observation proves progress. This is especially important across browser, wallet extension, transport, API, cache, and accessibility boundaries, where delivery and processing are different events and where local time or arrival order may not reflect authoritative order. 11
A useful review asks how the design behaves under stale closure, duplicate update, wallet rejection, chain mismatch, schema drift, reconnect storm, and misleading confirmation. The unsafe outcome is a check-then-act race accepting two individually plausible operations. Prevent it with explicit preconditions and postconditions, and retain a linearization argument plus stress tests at the chosen contention boundary as release evidence. Use stable codes rather than exception text, keep policy configuration versioned, and attach the accepted policy or rule version to durable results. An frontend or API-platform operator must be able to stop intake, drain or quarantine work, compare local state with authority, and resume without inventing a second side effect.
Idempotency and replay
The implementation of API Rate Limiting and Quota Management should expose how duplicate delivery, process restart, and historical backfill preserve the same result through types and module boundaries. Parse external representations once, preserve the original identity when audit or replay needs it, and pass validated domain values inward. Mutations of server-derived data, wallet session, UI intent, and explicit transaction state belong behind one authoritative transition function or transaction boundary. Network clients, storage adapters, user interfaces, and telemetry exporters must not duplicate consensus or business rules. That separation keeps deterministic logic testable and prevents a library upgrade from silently redefining validity. 12
Assume that at-least-once delivery creating a second side effect will eventually occur in a staging fault test or production incident. The control is not a catch-all retry: classify the outcome, decide whether the identical operation is safe to repeat, bound attempts and elapsed time, and surface terminal work for reconciliation. The minimum evidence is stable operation identities, deduplication state, and deterministic replay fixtures. Keep addresses, wallet permissions, access tokens, KYC data, transaction intent, and browser storage out of ordinary logs, and prefer hashes, version identifiers, counts, and sanitized reason codes. Any emergency bypass must be narrow, time-limited, approved, and observable.
Persistence and atomicity
Verification for API Rate Limiting and Quota Management must demonstrate which facts commit together and how derived views catch up at several layers. Small tests cover deterministic transforms and boundary values; contract tests pin serialized forms; integration tests exercise real adapters; replay tests compare state roots or projections; and fault tests interrupt work at every commit boundary. The dataset must include normal history, malformed input, duplicates, reordering, maximum-size values, and changes of rule or schema version. A passing example is evidence about that environment and dataset, not a universal performance claim. 13
Make a crash exposing a cursor that claims work whose state was not committed a named negative test. The release packet should retain transaction boundaries, durable checkpoints, and reconciliation queries, exact dependency and tool versions, the deterministic command, and its result. For performance work, report warm-up, repetitions, concurrency, percentiles, resource limits, and the point where backpressure begins. For security work, include abuse cases and independent review. A change is ready only when failures leave server-derived data, wallet session, UI intent, and explicit transaction state safe, recovery is rehearsed, and telemetry explains both user-visible outcome and operator action.
API and schema contracts
For API Rate Limiting and Quota Management, this review makes input limits, optionality, pagination, versioning, and compatibility behavior explicit. Start from one user intent, API representation, wallet request, stream update, or transaction lifecycle event and write down its origin, canonical representation, validation context, authority, and durable outcome. The typed web, wallet, or blockchain API component must not infer a stronger fact from transport success, cache presence, or an upstream acknowledgement. Its authoritative state is server-derived data, wallet session, UI intent, and explicit transaction state, and every projection must remain rebuildable or reconcilable from committed facts. This framing distinguishes a protocol guarantee from an operational convenience and gives reviewers a concrete place to challenge an assumption. 11
The principal failure to design against is a technically valid deployment silently changing a consumer-visible meaning. Address it before optimizing by defining a narrow ownership boundary, stable identities, bounded resource use, and a machine-readable outcome for every rejected transition. Record consumer fixtures, schema-diff checks, and explicit deprecation windows. A reviewer should be able to trace each accepted result to input bytes, rule or policy version, prior state, and commit identity without relying on prose logs. When the authority cannot be reached or context is incomplete, return an explicit unavailable or pending state; do not convert uncertainty into acceptance.