Prompt
How do I forward incoming webhooks to multiple internal services with filtering?
Latest observation
Oct 5, 2026
OpenAI APIWeb search: off
A good pattern is to put a small webhook router in front of your internal services:
- Receive the external webhook at one public endpoint.
- Validate/authenticate it once.
- Inspect the payload and decide which internal services should get it.
- Fan out to those services, usually by:
- calling them directly over HTTP, or
- publishing to a queue/event bus if you want reliability and buffering.
- Apply filters per destination so only matching events are forwarded.
Simple architecture
External Provider
|
v
Webhook Router / Gateway
|
+--> Service A (if event.type == "order.created")
+--> Service B (if payload.customer.tier == "enterprise")
+--> Service C (if event.source == "github" and action in [...])
Filtering options
You can filter by:
- event type:
payment.succeeded,user.created - source/provider: GitHub, Stripe, Slack, etc.
- payload fields: region, tenant, customer tier, status
- headers/metadata: signature, topic, account ID
- custom rules: regex, JSONPath, CEL, JQ, Lua, etc.
Example rule table:
| Destination | Filter |
|---|---|
| Billing service | event.type in ["invoice.paid","payment.succeeded"] |
| CRM service | payload.customer.exists == true |
| Audit service | always true |
| Enterprise notifier | payload.customer.plan == "enterprise" |
Implementation approaches
1) In-app router
A small service written in Node/Python/Go:
- receives webhook
- validates signature
- evaluates rules
- forwards matching requests
Best when your needs are simple and you want full control.
2) API gateway / webhook gateway
Use something like:
- Kong
- NGINX + custom logic
- AWS API Gateway + Lambda
- GCP Cloud Run + Pub/Sub
- Azure Functions / API Management
Best when you want managed scaling and auth controls.
3) Event bus / queue-based fan-out
Instead of forwarding synchronously:
- webhook router writes event to Kafka / SNS / Pub/Sub / SQS
- consumers subscribe with their own filters
Best for:
- reliability
- retries
- slow consumers
- decoupling
This is usually the most robust option.
Recommended reliable pattern
If multiple internal services must get the webhook, use:
- Webhook receiver
- Normalize event
- Persist raw event in DB/object storage
- Publish event to bus
- Each service consumes only what it needs
This avoids losing events if one service is down.
Example logic
Pseudocode:
def handle_webhook(request):
verify_signature(request)
event = parse_json(request.body)
destinations = []
if event["type"] in ["order.created", "order.paid"]:
destinations.append("billing")
if event.get("customer", {}).get("tier") == "enterprise":
destinations.append("enterprise-notifications")
if event["source"] == "github":
destinations.append("devops")
for service in destinations:
forward_async(service, event)
return 200
Things to watch out for
- Idempotency: external webhooks may be retried, so dedupe by event ID.
- Retries: retry failed forwards with backoff.
- Dead-letter queue: store failures for later inspection.
- Timeouts: don’t block the webhook provider too long.
- Security: verify signatures, restrict internal endpoints, use mTLS or service auth.
- Schema evolution: version your event format.
- Observability: log event ID, destinations, filter decisions.
If you want a quick recommendation
- Small/simple setup: one router service with per-destination rules.
- Production/multi-team setup: router → message bus → consumers with subscriptions.
- Need low latency and direct calls: router forwards synchronously, but add retries and dedupe.
If you want, I can give you:
- a Node.js example
- a Python/FastAPI example
- a Docker/Kubernetes setup
- or a Kafka/SNS/PubSub design for this.