Build1 publisher2 min readPublished
This revocation intake writes the audit row before it touches the gateway's key cache
A dev.to design walkthrough pairs signed webhook intake with an hourly polling sweep over per-tenant API keys. It argues the architecture should be settled by what an access review can reconstruct afterwards.
The Engineer · Build desk

What happened
- The design pairs a registered webhook that carries a revocation to the gateway in a couple of seconds with a scheduled poll that reports, an hour later, whether the revocation actually landed.
- The worked example is a customer support platform issuing one scoped key per tenant, good for reading tickets and writing replies, revoked when an agent offboards or a contract ends.
- Enforcement sits at an edge gateway holding a local key table, so it avoids a network hop per request. That table is a cache of the issuer's truth.
- The post ranks what access reviewers need: the revocation applies, the moment it applied can be named, the discovery path can be named, and latency comes fourth.
- Intake verification follows the Standard Webhooks shape, with webhook-id, webhook-timestamp and webhook-signature headers and HMAC-SHA256 taken over the id, the timestamp and the raw body.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- decision A team tuning median delivery latency is answering a question the access reviewer never asks; the post would settle the choice on whether one key's afternoon can be reconstructed.
- constraint Reliability cannot be escalated to the issuer. The delivery semantics put it on the receiver, so a missed revocation is a bug in your intake by definition.
- cost The polling backstop bills by tenant count times poll frequency, so a month with zero revocations costs the same as a month with hundreds, and the payer is whoever runs the gateway.
- exposure An unsigned feed hands an attacker a switch for deactivating a tenant's access, and a forged issuance event on the same channel puts a key back.
Verification runs first, and the audit append runs before the cache update. The intake records the event in an append-only log, and only then does it teach the local key table the word "revoked" [9]. That row is indexed on the webhook event id, so a redelivery lands as a no-op instead of a second revocation record [19]. Invert those two writes and the access-review trail is whatever the cache happens to hold when somebody asks [9].
The sample verifier rejects on clock skew before it computes anything. MAX_SKEW_SECONDS is 300, so a signature whose timestamp is more than five minutes old fails without an HMAC ever being taken [17][2]. Standard Webhooks signs the id, the timestamp and the raw body [15]. The route is therefore mounted with express.raw, so the bytes that were signed are the bytes that get hashed; the comparison strips the "v1," prefix, base64-decodes, checks the length and then calls timingSafeEqual [18]. RFC 9421 is the standards-track alternative when you control both ends and want the headers signed instead of the payload [16].
Push and poll go quiet in different ways. Webhook delivery is at-least-once on a retry budget the sender chose; when the budget is spent the event is dropped, and the receiver is the only party that could have noticed [4]. Past the last retry, according to the post, nothing distinguishes "nothing happened" from "four revocations were dropped while my intake returned 503" [10]. At an hourly interval, each tenant key gets compared 24 times a day whether or not anything was revoked [1], and each mismatch the sweep finds is one event the push path lost [13]. "Polling is boring and hard to lose track of, which is exactly why it makes a good witness," the post says [12].
So the couple of seconds is a claim about the issuer's first delivery attempt [1]. It transfers to your system only while your intake is reachable and answers quickly. Return 503 for long enough and the latency you observe is the retry schedule the sender set [4].
The post does not report measured delivery rates or latency percentiles for either path [20]. It argues from what a reviewer has to be handed instead: an auditor who wants to know whether a key was still usable after the offboarding ticket closed is asking for a row, the post says, not a percentile [8].
What to watch
- Measured divergence counts from a real sweep over a real tenant population.
- Issuers publishing their retry budgets and final-attempt timing; that bounds how long a dropped revocation can hide.
- Key issuers shipping RFC 9421 signed headers next to a Standard Webhooks payload signature.