Clarify requirements & constraints
- Throughput: millions/day (~10k–100k RPS peak)
- SLAs: per-customer latency and delivery guarantees
- External endpoints: variable reliability, unknown idempotency
- Security/compliance: signing, retry policies, data residency
High-level architecture
- Ingest → Event Store (immutable log) → Router → Per-destination queue (partitioned) → Delivery workers → DLQ
- Control plane for customer configs (rate limits, ordering, batching, retries, idempotency keys) and observability APIs/UI
Delivery semantics
- Default: at-least-once (simple, scalable)
- Exactly-once optional for customers who opt-in: requires consumer-side idempotency or transactional acknowledgement + dedupe store (e.g., Redis/SQL) per destination with TTL. Explain trade-off: higher latency, storage, complexity.
Retry & backoff
- Retry policy configurable per destination: attempts, base delay, max delay, jitter
- Use exponential backoff with full jitter to avoid thundering herd
- Circuit breaker: mark endpoints as unhealthy after N failures → escalate to probing schedule (sparse retries)
Per-destination rate limits & batching
- Enforce token-bucket per-destination in Router; reject/queue when over limit
- Support configurable batching (size or time window) for endpoints that accept bulk payloads; batcher respects ordering groups
Ordering guarantees
- Provide per-customer/per-resource ordering option by routing events with same ordering key to a single partition/worker
- Document trade-off: strict ordering reduces concurrency and throughput; offer best-effort option (out-of-order faster)
Dead-letter queue
- After retry budget exhausted, move to DLQ with failure metadata, last response, timestamps; allow manual re-delivery and auto-retry policies
Idempotency strategies
- Provide idempotency-key header generated by platform (event-id). Encourage consumers to honor it.
- For exactly-once: store delivered event IDs with TTL; dedupe on re-delivery
- Support idempotent endpoints guidance in docs and SDKs
Visibility & developer UX
- Real-time dashboard and REST API with:
- Delivery status (success/failure), attempts, latency, response codes
- Per-endpoint metrics: success rate, p50/p95 latency, error taxonomy
- Alerts and SLA reporting; replay tools for DLQ; configurable webhooks/callbacks for status changes
- Audit logs, searchable by event-id; sample payload/responses (masked) for debugging; integration with observability (PagerDuty, Slack)
Operational metrics & SLAs
- SLOs: e.g., 99.9% delivered within X minutes for healthy endpoints
- Monitor queue depth, worker utilization, error rates, retry storms
Trade-offs & roadmap
- Start with at-least-once + strong idempotency guidance for fastest scale.
- Offer exactly-once as premium feature with dedupe store and higher cost.
- Future: adaptive batching, client SDKs to encourage idempotency, machine-learning-based retry tuning.
This balances reliability, scale, and developer experience while enabling product choices per customer needs.