Markdown Editor

Webhook Delivery System Design Template

Outbound webhook platform design: at-least-once delivery, HMAC signing, per-endpoint queues, backoff and circuit breaking, ordering, replay, SSRF protection

SystemdesignVollständigStandard Webhooks v1.0.0; OWASP SSRF Prevention Cheat Sheetdesignwebhookdelivery

Anleitung: Use it when you build or harden the system that sends event notifications to customer URLs. Fill the delivery contract (at least once, ordering, retry period) and the failure-backlog estimate (3.4) first. The main pitfall is one slow or hostile endpoint hurting everyone else or your internal network; keep per-endpoint isolation and the egress proxy.

Vorschau

System Design: [Webhook delivery platform name]

Reference design for an outbound webhook platform that delivers event notifications from your product to endpoints that customers register: at-least-once delivery, payload signing, per-endpoint isolation and queues, retries with backoff and circuit breaking, ordering options, replay, endpoint verification, protection against server-side request forgery (SSRF) and delivery observability for customers. The signing and header format follows the Standard Webhooks specification v1.0.0; error bodies follow RFC 9457. It follows the structure of the System Design Document template and is pre-filled with a worked design to adapt. Replace every [bracketed] value and every row marked Example; all numbers are illustrative assumptions, not benchmarks.

Document control

FieldValue
Document ID[SDD-WH-001]
System / feature[Outbound webhooks]
Version[0.1]
Status[Draft / In review / Approved / Implemented / Superseded]
Owner[@owner]
Author(s)[@author]
Reviewers[@reviewer-1], [@reviewer-2]
Last updatedYYYY-MM-DD
Classification[Internal]
Signature format[Standard Webhooks v1.0.0, symmetric (v1) / asymmetric (v1a)]
RelatedNotification Service System Design Template (system-design/design-notification-service), Message Queue System Design Template (system-design/design-message-queue), API Design Guidelines Template (architecture/api-design-guidelines)

Approvals

RoleNameDecisionDate
Tech lead, developer platform[@name][Approved / Changes requested]YYYY-MM-DD
Staff / principal engineer[@name][Decision]YYYY-MM-DD
SRE / operations[@name][Decision]YYYY-MM-DD
Security (egress and SSRF)[@name][Decision]YYYY-MM-DD
Developer experience / docs[@name][Decision]YYYY-MM-DD

Revision history

VersionDateAuthorChange summary
0.1YYYY-MM-DD[@name]First draft for design review
0.2YYYY-MM-DD[@name]Example: Replaced one shared delivery queue with per-endpoint scheduling
0.3YYYY-MM-DD[@name]Example: Moved all egress through a filtering proxy after SSRF review
1.0YYYY-MM-DD[@name]Example: Approved

Contents

1. Overview

1.1 Problem statement

[Example: Webhooks are sent from the API servers in the request thread pool through one shared queue. When a large customer's endpoint started timing out after 30 s last month, worker threads filled up and deliveries to every other customer were delayed by up to 3 hours. Retries are a fixed 3 attempts over 10 minutes, so short customer outages lose events. Payloads are unsigned, and a penetration test showed that a registered URL pointing at the cloud metadata address returned internal credentials.]

1.2 Proposed solution

[Example: Product services publish domain events to an event log. A fan-out stage matches each event to subscribed endpoints and creates one delivery per endpoint. Deliveries are scheduled per endpoint, with a concurrency cap and a circuit breaker for each endpoint, so one slow endpoint only delays its own deliveries. Workers send signed HTTPS POST requests in the Standard Webhooks format through an egress proxy that blocks private and internal addresses. Failed deliveries are retried with exponential backoff and jitter for about 3 days, then marked failed and available for manual or API replay for 30 days. Customers see every attempt in a delivery log and are notified when an endpoint keeps failing.]

1.3 Decisions requested from reviewers

IDQuestionRecommended optionSection
Q-01Example: One shared queue or per-endpoint scheduling?Per-endpoint virtual queues with a fair scheduler7.1
Q-02Example: Do we guarantee ordering?No by default; optional ordered mode per endpoint with per-resource FIFO7.3
Q-03Example: Symmetric or asymmetric signatures?Symmetric HMAC (v1) by default; asymmetric (v1a) as an option7.4
Q-04Example: How long do we retry?About 3 days, then failed and replayable for 30 days7.2
[Q-nn][Question][Option][Section]

1.4 45-minute interview path

MinutesCoverKey point to land
0 to 5Scope: outbound only, customer-registered URLs, event typesThe other end is untrusted and unreliable
5 to 10Contract: at least once, unordered by default, signed, retried for N daysReceivers must deduplicate by event ID
10 to 15Estimates: events per second, fan-out, in-flight requests, failure backlogSlow endpoints, not volume, size the worker pool
15 to 20Data model and access patterns: event, endpoint, delivery, attemptDue-time index per endpoint
20 to 25High-level diagram: event log, fan-out, scheduler, workers, egress proxyIsolation between endpoints
25 to 38One deep dive: per-endpoint isolation with retries and circuit breaking (7.1, 7.2) is the strongest; ordering (7.3) or signing and SSRF (7.4) are good alternativesOne bad endpoint cannot delay others
38 to 42Failure modes and customer-facing observabilityReplay closes the loop
42 to 45Trade-offs and what changes at 10xWhere the design breaks first

2. Requirements

2.1 Core functional requirements

IDRequirementPriority
FR-01Example: Customers register HTTPS endpoints and choose event types per endpointMust
FR-02Example: Deliver each matching event to each subscribed endpoint at least onceMust
FR-03Example: Sign every request; support secret rotation with overlapMust
FR-04Example: Retry failed deliveries with exponential backoff and jitter for about 3 daysMust
FR-05Example: Show every delivery attempt (status, latency, response excerpt) to the customerMust
FR-06Example: Replay a single event or a time range to an endpointMust
FR-07Example: Verify endpoint ownership before activationShould
FR-08Example: Optional ordered delivery per resource for endpoints that opt inShould
FR-09Example: Send test events from the dashboard and APIShould
[FR-nn][Requirement][Must / Should / Could]

2.2 Non-functional requirements

IDQualityTargetMeasured as
NFR-01Delivery latencyExample: p99 below 5 s from event commit to first attempt for healthy endpointsPipeline timestamps
NFR-02DurabilityExample: No accepted event is lost before it is delivered or expiresReconciliation job
NFR-03IsolationExample: One endpoint timing out does not raise p99 first-attempt latency for others by more than 10%Fault injection
NFR-04ThroughputExample: 105,000 deliveries/s at peakLoad test
NFR-05SecurityExample: No request reaches a private, loopback, link-local or internal addressEgress proxy tests
NFR-06Customer visibilityExample: Attempt visible in the dashboard within 10 sDashboard probe
[NFR-nn][Quality][Target][Measurement]

2.3 Below the line (out of scope)

  • [Example: inbound webhooks from third parties into our product]
  • [Example: exactly-once delivery (impossible over HTTP without receiver cooperation; receivers deduplicate by event ID)]
  • [Example: push notifications to devices, email and SMS (Notification Service System Design Template, system-design/design-notification-service)]
  • [Example: event streaming to customer cloud accounts (separate connectors)]
  • [Example: transforming payloads per customer]

3. Capacity estimation

3.1 Assumptions

InputValueSource
Events per dayExample: 2 billionEvent log metrics
Peak to average ratioExample: 3Hourly profile
Endpoints subscribed per event, averageExample: 1.5Subscription table
Registered endpointsExample: 500,000Endpoint table
Share of endpoints failing at any timeExample: 2%Delivery history
Payload size, averageExample: 4 KBEvent schemas
Healthy endpoint response timeExample: 300 msAttempt records
Request timeoutExample: 10 sPolicy (Standard Webhooks suggests 15 to 30 s; shorter here to bound worker time)
Replay retentionExample: 30 daysProduct decision

3.2 Delivery rate

2 billion / 86,400 s = about 23,150 events/s on average, about 69,400/s at peak (round to 70,000). With 1.5 endpoints per event: about 105,000 deliveries/s at peak.

Consequence: a single queue partition or a single scheduler cannot keep up; partition the scheduler by endpoint ID (Example: 256 partitions, about 410 deliveries/s each at peak).

3.3 Concurrent requests

By Little's law, healthy traffic needs 105,000/s x 0.3 s = 31,500 requests in flight. If 1% of deliveries hit slow endpoints that run to the 10 s timeout, that adds 1,050/s x 10 s = 10,500. Total about 42,000.

Consequence: slow endpoints add a third of the in-flight load from 1% of traffic. Use non-blocking HTTP clients (Example: 2,000 in-flight requests per worker, so 21 workers at peak, plan 32 for headroom and zone loss) and cap in-flight requests per endpoint so a slow endpoint cannot take more than its share.

3.4 Failure backlog

Deliveries per day = 2 billion x 1.5 = 3 billion. If 2% go to failing endpoints, 60 million deliveries per day enter retry; held for up to 3 days that is up to 180 million pending deliveries.

Consequence: the pending set does not fit in a broker's memory and must not block healthy traffic. Store pending deliveries durably with an index on (endpoint_id, next_attempt_at) and let a circuit breaker stop attempts to dead endpoints (7.2) instead of retrying each delivery independently.

3.5 Storage

Payloads are stored once per event: 2 billion x 4 KB = 8 TB per day, 240 TB for 30 days before compression. Attempt records at Example: 200 bytes and 1.2 attempts per delivery: 3 billion x 1.2 x 200 B = 720 GB per day, about 21.6 TB for 30 days.

Consequence: keep payloads in compressed object storage keyed by event ID, and only metadata and attempt records in the database; replay reads the payload from object storage.

3.6 Summary

QuantityEstimateDesign consequence
Deliveries at peak105,000/sScheduler partitioned by endpoint
In-flight requestsabout 42,000Non-blocking workers; per-endpoint caps
Pending retriesup to 180 millionDurable due-time index; circuit breakers
Payload storage240 TB raw for 30 daysObject storage, compressed
Attempt recordsabout 21.6 TB for 30 daysPartitioned table with TTL

4. API design

4.1 Management API

OperationPurpose
POST /v1/webhook_endpointsRegister an endpoint URL with event types; returns the signing secret once
PATCH /v1/webhook_endpoints/{id}Change URL, event types, ordered mode, or disable
POST /v1/webhook_endpoints/{id}/rotate_secretNew secret; old one stays valid for an overlap period (Example: 24 h)
GET /v1/webhook_endpoints/{id}/deliveries?status=failedList deliveries and attempts
POST /v1/webhook_endpoints/{id}/replayReplay by event IDs or a time range
POST /v1/webhook_endpoints/{id}/testSend a test event

Management API errors use Problem Details (RFC 9457); for example a rejected URL returns 422 with the reason (private address, not HTTPS).

4.2 Webhook request format

The request follows Standard Webhooks v1.0.0: three headers and a JSON body with type, timestamp and data.

POST /hooks/acme HTTP/1.1
Host: hooks.customer.example
Content-Type: application/json
webhook-id: evt_2Lq8x7Kp
webhook-timestamp: 1792656000
webhook-signature: v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4=

{"type": "invoice.paid", "timestamp": "2026-10-22T08:00:00Z", "data": {"id": "inv_93Fa", "amount": 12000, "currency": "EUR", "status": "paid"}}
  • webhook-id is the event ID and stays the same on every retry, so the receiver can use it as an idempotency key.
  • webhook-timestamp is set per attempt, in Unix seconds.
  • webhook-signature is v1, plus the base64 HMAC-SHA256 of webhook-id.webhook-timestamp.body using the endpoint secret. During rotation it carries two signatures separated by a space.
  • The signature value above is illustrative, not a real computation.

Keep payloads small (the specification suggests staying well under about 20 KB); for large objects send an ID and let the receiver fetch the resource through the API.

4.3 Response handling

ResponseTreatment
2xxSuccess; delivery complete
3xxFailure; redirects are not followed (prevents SSRF through redirects); customer is told to update the URL
410 GoneDisable the endpoint and notify the customer
429, 502, 504Failure; slow down this endpoint; honour Retry-After if present (the throttling codes named by Standard Webhooks)
503Failure; this design also slows down and honours Retry-After (a local choice: the specification treats 503 as an ordinary failure)
Other 4xx and 5xxFailure; retry per schedule
Timeout, TLS or connection errorFailure; retry per schedule

5. Data model

5.1 Entities

One event fans out to many deliveries; each delivery has one or more attempts.

5.2 Storage choices

DataStoreWhy
Events (metadata)Event log plus partitioned tableFan-out source and replay index
PayloadsObject storage, compressed240 TB per 30 days at low cost
Deliveries and due timesExample: Partitioned database by endpoint_idDurable pending set with due-time index
AttemptsPartitioned table with 30-day TTLCustomer delivery log
Endpoint config and secretsRelational database; secrets in a key management service, referencedStrong consistency, audit, encryption
Endpoint healthIn memory on scheduler partition, checkpointedBreaker decisions per attempt

5.3 Access patterns

QueryServed byKey or indexPartition rationale
Which endpoints subscribe to event type T for account ASubscription cache(account_id, type)Small, cached in fan-out workers
Next due deliveries for endpoint EDeliveries table(endpoint_id, next_attempt_at)Partition by endpoint_id so one scheduler partition owns an endpoint
Endpoints with due work on partition PReady index(partition, earliest_due_at)Lets the scheduler skip idle endpoints
Delivery log for endpoint E, newest firstAttempts table(endpoint_id, started_at desc)Same partition as deliveries
All deliveries of event X (support)Secondary indexevent_idLow volume
Replay range for endpoint EEvents table(account_id, created_at) filtered by typeRange scan, rate-limited
Next item for ordering key KDeliveries table(endpoint_id, ordering_key, sequence)Same partition as the endpoint

6. High-level design

ComponentResponsibilityScales by
Transactional outboxPublish events only when the business transaction commitsPer service
Fan-out workersMatch events to endpoints, store payload, create deliveriesEvent log partitions
Scheduler partitionsOwn endpoints; pick due deliveries fairly; apply caps and breakers256 partitions
Delivery workersSign, send, record attemptsIn-flight requests
Egress proxyResolve, validate and connect only to public addressesProxy instances
Dashboard and APIDelivery log, replay, test eventsRead replicas

7. Detailed design

7.1 Deep dive 1: per-endpoint isolation

OptionIsolationCostVerdict
A. One shared FIFO queueNone: a slow endpoint holds workers and blocks the queueLowestThe current outage
B. Physical queue per endpoint in the brokerStrong500,000 queues; broker limitsToo many queues to operate
C. Virtual per-endpoint queues in a partitioned store with a fair schedulerStrongIndex per endpointChosen

Choice: C. Reason: it gives each endpoint its own backlog and limits without creating broker objects per customer. Each scheduler partition:

  • Keeps a ready set of endpoints with due deliveries, ordered by earliest due time.
  • Takes deliveries in rounds across endpoints (deficit round robin), so a customer with a million pending events gets the same turn as one with ten.
  • Enforces a per-endpoint in-flight cap (Example: 10 by default, raised for large customers on request) and a per-account cap.
  • Never assigns more work to an endpoint whose breaker is open.

The delivery sequence for one healthy endpoint:

7.2 Deep dive 2: retries, backoff and circuit breaking

Retry schedule (Example, each delay with plus or minus 20% jitter):

AttemptDelay after previousCumulative
1immediate0
25 s5 s
31 minabout 1 min
410 minabout 11 min
51 habout 1 h 11 min
63 habout 4 h 11 min
76 habout 10 h 11 min
812 habout 22 h 11 min
924 habout 46 h 11 min
1024 habout 70 h 11 min (just under 3 days)
Option for dead endpointsBehaviourVerdict
A. Retry each delivery on its own schedule180 million pending deliveries each retried on their ownWastes capacity on known-dead endpoints
B. Circuit breaker per endpointAfter failures, stop sending; probe periodically; release backlog on recoveryChosen
C. Disable endpoint after first failuresFast, but drops events for brief outagesOnly after sustained failure

Choice: B, then C after sustained failure. Reason: an endpoint is usually down as a whole, so its deliveries should wait together. The breaker opens after Example: 10 consecutive failures or more than 50% failures over 5 minutes, sends one probe delivery per backoff interval, and on success closes and drains the backlog at the endpoint's cap so recovery does not flood the customer. Deliveries still respect their own expiry: after about 3 days without success they become failed and stay replayable for 30 days. After Example: 5 days of continuous failure the endpoint is disabled and the customer is notified by email and in the dashboard, as the specification recommends.

7.3 Deep dive 3: ordering

OptionGuaranteeCostVerdict
A. No orderingNone; receivers fetch current state if neededNoneDefault
B. FIFO per endpointStrict orderOne failing event blocks all events to that endpointRejected
C. FIFO per ordering key (resource ID) within an endpoint, opt-inOrder per resource, parallel across resourcesHead-of-line blocking per resourceOpt-in mode

Choice: A by default, C for endpoints that opt in. Reason: strict ordering turns any single failure into a full stop, and most receivers only need the latest state. Every payload carries the event creation time and a per-resource sequence number so receivers can discard older updates. In ordered mode the scheduler releases the next delivery for a key only after the previous one succeeded or expired, and the dashboard shows blocked keys.

7.4 Deep dive 4: signing, endpoint verification and SSRF

Signing (Standard Webhooks v1.0.0):

  • One secret per endpoint, 24 to 64 random bytes, shown once with the whsec_ prefix; stored in a key management service.
  • Symmetric signatures use HMAC-SHA256 (RFC 2104) with the v1 prefix; asymmetric signatures use ed25519 with the v1a prefix for customers who must not hold a shared secret.
  • Sign the exact bytes sent; never re-serialise the body after signing.
  • Rotation sends two signatures during the overlap period.
  • Customer documentation tells receivers to compare signatures in constant time, reject timestamps outside a tolerance (Example: 5 minutes) to stop replays, and deduplicate by webhook-id.

Endpoint verification: on registration and on URL change, the platform sends a webhook.verification event containing a random challenge; the endpoint is activated only after a 2xx response that echoes the challenge. This proves the customer controls the URL and stops the platform from being used to send traffic to third parties.

SSRF protection (OWASP Server Side Request Forgery Prevention Cheat Sheet):

ControlDetail
HTTPS onlyReject http:// URLs in production; TLS 1.2 or later
Validate at registration and at send timeDNS can change after registration, so check on every connection
Resolve, check, then connect to that IPBlock loopback, private, link-local (including cloud metadata), carrier-grade NAT, multicast and IPv6 equivalents; pin the checked address to stop DNS rebinding
No redirects3xx is a failure (4.3)
Egress proxyAll delivery traffic leaves through a filtering proxy (Example: an open-source SSRF proxy such as Stripe's smokescreen) in a network segment with no route to internal services
Port allow-list443 and [8443] only
Response limitsRead at most Example: 64 KB of the response; store a 1 KB excerpt

How real systems do it (paraphrased from Stripe's public webhook documentation; see 12.4). Stripe tells integrators that live-mode events are retried with exponential backoff for up to three days, that delivery order is not guaranteed and the same event can arrive more than once, so receivers should record processed event IDs. Each request carries a signature header with a timestamp and an HMAC-SHA256 signature over the timestamp and raw body; the official libraries reject timestamps older than a default tolerance of five minutes, and a new signature and timestamp are generated for each retry. Redirect responses count as failures. Secrets can be rolled with a period during which both old and new secrets produce signatures. Receivers are told to return a 2xx quickly and do heavy work asynchronously. Lesson for this design: publish the same plain contract (at least once, unordered, signed, retried for a stated period) and give receivers the tools to follow it.

7.5 Customer-facing observability and replay

  • Delivery log per endpoint: event ID, type, attempt number, status code, latency, error class (timeout, TLS, DNS, refused, HTTP status) and a response excerpt.
  • Endpoint health page: success rate over 24 hours, p95 latency, breaker state, backlog size and the time of the next attempt.
  • Replay: by event ID, by filter, or by time range; replays create new deliveries flagged replay=true, keep the original webhook-id, and are rate-limited per endpoint.
  • Notifications: email and dashboard banner when the breaker opens, again before the endpoint is disabled, and a summary when it recovers.
  • Events API: customers can list recent events through the API to reconcile anything they missed, which is the safety net behind at-least-once delivery.

8. Scalability and performance

ConcernApproachLimit before redesign
Delivery rateScheduler partitioned by endpoint; stateless workersExample: about 1,000 deliveries/s per partition
Slow endpointsPer-endpoint in-flight caps; 10 s timeoutWorker in-flight capacity
Big customer burstsPer-account caps; fair rounds across endpointsCustomer's own endpoint capacity
Pending backlogDurable due-time index; breakersStorage, not memory
Payload storageObject storage with lifecycle rulesCost, not technology
Egress proxyHorizontally scaled, connection reuse per destinationProxy connection table

Latency budget for the first attempt to a healthy endpoint (target p99 5 s from event commit):

StepBudget
Outbox relay to event log500 ms
Fan-out and delivery creation500 ms
Scheduler pickup1,000 ms
Signing and proxy checks50 ms
Network and customer processingCustomer-dependent (excluded)
Headroom2,950 ms

9. Reliability, security and operations

9.1 Failure modes

ComponentFailureDetectionBlast radiusMitigationRTO
Customer endpointDown or slowBreaker state, attempt errorsThat endpoint onlyBreaker, backoff, notifications, replayCustomer-dependent
Scheduler partitionHost crashPartition lease lostAbout 0.4% of endpoints (1 of 256) delayedLease moves to another host; state rebuilt from storeExample: 30 s
Delivery workersCrash mid-requestLease timeout on deliverySome deliveries sent twiceAt-least-once contract; receivers deduplicateExample: 30 s
Egress proxyDownProxy health, connect errorsAll deliveries in the regionMultiple instances per zone; deliveries wait and retry, never bypass the proxyExample: 5 min
Key managementUnavailableSigning errorsAll deliveriesCache data keys in memory for a bounded time; deliveries wait if expiredExample: 15 min
Event logUnavailableOutbox relay lagNew events delayedOutbox holds events in each service's databaseLog RTO
Fan-out bugEvents sent to wrong endpointAccount mismatch check before sendPotential data leak across customersPre-send assertion that delivery account equals event account; kill switchExample: immediate stop
[Component][Failure][Signal][Scope][Mitigation][RTO]

9.2 Security

ThreatControl
SSRF to internal services or metadataEgress proxy, address checks at send time, no redirects (7.4)
Spoofed webhooks to customersSignatures; documented verification; asymmetric option
Replay of captured requestsTimestamp in the signed content; receiver tolerance window
Secret leakageSecrets in KMS; shown once; rotation API; secrets never logged
Data sent to the wrong customerAccount assertion before send; endpoint verification
Sensitive data in payloadsMinimal payloads with IDs; customers fetch details through the authenticated API
Abuse as a traffic amplifierEndpoint verification; per-account limits
[Threat][Control]

Run a threat model (Threat Model Template, security/threat-model) on the egress path and the fan-out account check before launch.

9.3 Observability (operator)

SignalSourceAlert threshold
First-attempt latency p99Pipeline timestampsExample: above 5 s for 10 min
Fan-out lagEvent log consumer lagExample: above 60 s
Open breakersSchedulerSudden rise across many endpoints (suggests our egress, not customers)
Proxy rejections by reasonEgress proxyAny spike in private-address rejections
Success rate excluding open breakersAttemptsExample: below 98%
Pending backlogDeliveries tableGrowth beyond [n] per hour

9.4 Cost estimate

ItemUnit costQuantityMonthly cost
Delivery workers and schedulers[USD per instance-month]Example: 32 + 16[USD]
Egress proxy and NAT[USD per GB][GB per month][USD]
Delivery and attempt storage[USD per TB-month]Example: about 22 TB[USD]
Payload object storage[USD per TB-month]Example: 240 TB raw, less after compression[USD]
Total[USD]

10. Trade-offs and alternatives

DecisionOptionsChosenWhyWhat we give up
GuaranteeAt most once; at least onceAt least onceNo silent lossReceivers must deduplicate
OrderingNone; per endpoint; per key opt-inNone by default, per key opt-inAvoids head-of-line blockingReceivers handle out-of-order events
IsolationShared queue; broker queue per endpoint; virtual queuesVirtual queuesStrong isolation without broker sprawlCustom scheduler to build and run
PayloadFull object; thin (ID only)Full object, small, with option for thinFewer API calls for receiversData duplication; stale snapshots
SignatureSymmetric; asymmetricSymmetric default, asymmetric optionSimple for most receiversShared secret to protect
Build or buyBuild; webhook-as-a-service vendor[Decide][Reason][Cost]
What changes at 10x1 million deliveries/s, 5 million endpointsMore scheduler partitions, regional delivery fleets near customers, tiered payload storageScheduler partition throughput and egress IP reputation bind firstMore regions to operate; customers must allow more source IPs
What changes at 0.1x10,500 deliveries/sA single queue table with per-endpoint locking and a managed queue may suffice; or use a vendorTeam cost dominatesWeaker isolation unless caps are kept

11. Delivery plan and risks

11.1 Milestones

MilestoneScopeExit criterionTarget date
M1Egress proxy and SSRF controls on the existing senderPenetration retest passesYYYY-MM-DD
M2New pipeline in shadow mode (deliver to a sink, compare)Same deliveries as legacy for 7 daysYYYY-MM-DD
M3Signed deliveries, per-endpoint scheduler, delivery logIsolation fault test passesYYYY-MM-DD
M4Replay, ordered mode, endpoint verificationCustomer beta feedback addressedYYYY-MM-DD

11.2 Rollout and rollback

[Example: Move accounts in cohorts from the legacy sender to the new pipeline. Signatures are added before the cutover with at least 60 days' notice so customers can enable verification. Rollback routes a cohort back to the legacy sender; deliveries already created in the new pipeline complete there.]

11.3 Risks

IDRiskLikelihoodImpactMitigationOwner
R-01Example: Customers do not verify signaturesHighMediumSDK helpers, docs, verification tool, test events[@name]
R-02Example: Duplicate deliveries during migrationMediumMediumKeep the same event IDs; announce at-least-once contract[@name]
R-03Example: Egress IP changes break customer allow-listsMediumHighPublish IP list with 30 days' notice of changes[@name]
R-04Example: Ordered mode causes long stallsMediumMediumDashboard shows blocked keys; expiry releases them[@name]
[R-nn][Risk][L / M / H][L / M / H][Mitigation][@name]

12. Appendices

12.1 Open questions

IDQuestionOwnerDue
OQ-01Example: Offer thin events (ID only) as the default for new endpoints?[@name]YYYY-MM-DD
OQ-02Example: Should enterprise customers get dedicated egress IPs?[@name]YYYY-MM-DD
[OQ-nn][Question][@name]YYYY-MM-DD

12.2 Traceability

RequirementDesign sectionVerification
FR-02, NFR-027.1, 9.1Reconciliation job comparing events and deliveries
FR-037.4Signature conformance with Standard Webhooks reference libraries
FR-047.2Endpoint outage simulation of 2 days, then recovery drain
FR-067.5Replay tests by ID and by range
NFR-037.1One endpoint slowed to timeout; other endpoints unchanged
NFR-057.4SSRF test suite: private ranges, DNS rebinding, redirects, IPv6

12.3 Glossary

TermMeaning
EndpointA customer URL registered to receive events
DeliveryOne event destined for one endpoint
AttemptOne HTTP request for a delivery
Circuit breakerPer-endpoint switch that stops attempts after repeated failures and probes for recovery
Ordering keyResource identifier used for optional per-resource FIFO
SSRFServer-side request forgery: tricking a server into calling an address it should not reach
ReplayRe-sending past events to an endpoint on request

12.4 References

ReferenceUse
Standard Webhooks specification v1.0.0 (github.com/standard-webhooks/standard-webhooks, Apache 2.0)Headers, signed content, secret format, status handling, retry guidance (4.2, 4.3, 7.4)
Stripe documentation, "Receive Stripe events in your webhook endpoint" (docs.stripe.com/webhooks)Inspiration for the box in 7.4 (paraphrased)
OWASP Server Side Request Forgery Prevention Cheat SheetSSRF controls in 7.4
Stripe smokescreen (github.com/stripe/smokescreen)Example egress proxy
RFC 2104 HMAC; RFC 9110 HTTP Semantics; RFC 9457 Problem DetailsSigning primitive, status codes, management API errors
Notification Service System Design Template (system-design/design-notification-service)Device, email and SMS notifications
Message Queue System Design Template (system-design/design-message-queue)Event log semantics
Rate Limiter System Design Template (system-design/design-rate-limiter)Per-account caps
Resilience and Load Shedding Design Template (system-design/resilience-load-shedding-design)Circuit breaker policy

Standard and licence note

Based on the Standard Webhooks specification v1.0.0 for the request format and signatures, on the OWASP SSRF Prevention Cheat Sheet for egress controls, and on RFC 2104, RFC 9110 and RFC 9457. Stripe material is used as inspiration only and is paraphrased, not copied. All numbers are illustrative examples. Check the current version of each specification before you implement. Original text written for this collection. Template licence: MIT.

Ähnliche Vorlagen