ADR-0004. WebhookConfig table instead of static routing config
| Field | Value |
|---|---|
| Status | Accepted |
| Date | 2026-03-08 |
| Deciders | payment-team |
| Supersedes | — |
Context
- Payment fires webhooks on transaction/attempt state changes. Subscribers (sale, finance, custom integrations) need their endpoints to receive these events.
- Two ways to configure routing:
- Static config (env vars / yaml) — endpoints baked into deployment.
- Dynamic registry —
WebhookConfigrows stored in DB; admins can register new subscribers at runtime.
Decision
Use a WebhookConfig table with CRUD endpoints (POST /webhook-configs). Each row has url, eventTypes[], status, optional signingMethod + secret, and per-row metadata (timeout, max retries).
WebhookEventHandlerHelper.handle() queries active configs filtered by event type, dispatches to each.
Consequences
| Pros | Cons |
|---|---|
| New subscribers added without redeploy | Config drift between environments (DB-managed) |
| Per-subscriber retry/timeout/HMAC | Authorization required to manage webhook configs (security) |
Enable/disable subscribers via status | DB query on every event — needs (status, eventTypes GIN) index for performance |
| Audit trail via Configuration history (if implemented) | Test endpoints may leak in prod if not cleaned up |
Schema decisions
eventTypes: text[](Postgres array) — supports filter viaeventTypes @> ARRAY[event].metadata: jsonbwith{ timeoutMs: 30000, maxRetries: 3 }defaults — per-row tunable.- Soft-delete supported (deactivate via
statusis preferred for audit).
Alternatives Considered
| Option | Pros | Cons | Why rejected |
|---|---|---|---|
| Hardcoded URLs in env | Simple | No runtime change; doesn't scale to many subscribers | Inflexible |
| Service mesh routing (e.g., Istio) | Decouples application from URL | Heavy infrastructure | Overkill |
| External pub/sub (Kafka topics) | Decouples; subscribers consume | Asymmetric — sale already uses HTTP webhook pattern | Migration cost not justified |
References
core/src/models/schemas/public/webhook-config/schema.tscontrollers/webhook-config/controller.tshelpers/webhook-event-handler/helper.ts