Skip to main content

ADR-003: Webhook Architecture

Status: Accepted Date: December 17, 2025 Decision Makers: CODITECT Engineering Team


Context

Stripe webhooks notify us of payment events. We need to:

  1. Handle events reliably (no missed events)
  2. Process idempotently (handle retries)
  3. Respond quickly (<5s per Stripe requirement)
  4. Handle high event volumes

Decision

Implement async webhook processing with idempotency.

Architecture

Stripe → Webhook Endpoint → Signature Verify → Idempotency Check → Queue → Worker


Quick Response (200 OK)

Key Events to Handle

EventAction
customer.subscription.createdProvision access
customer.subscription.updatedUpdate limits
customer.subscription.deletedRevoke access
invoice.paidRecord payment
invoice.payment_failedNotify, retry
checkout.session.completedComplete signup

Implementation

@app.post("/webhooks/stripe")
async def stripe_webhook(request: Request):
# 1. Verify signature (fail fast)
# 2. Check idempotency (skip duplicates)
# 3. Queue for processing
# 4. Return 200 immediately
await queue.enqueue(event)
return {"status": "queued"}

Consequences

Positive

  • Reliable event processing
  • Fast response times
  • Handles retries safely

Negative

  • Queue infrastructure required
  • Eventual consistency

Document Control:

  • Created: December 17, 2025