-
Notifications
You must be signed in to change notification settings - Fork 207
Open
Description
Feature Request
Motivation
- Svix currently supports filtering by event type (
filterTypes
) andchannels
, but cannot filter by message payload content. - Many domains require content-aware routing without forking publisher logic per consumer.
- In Web3 specifically, on-chain events often share the same event type but differ by contract address, token ID, chain ID, value thresholds, or allowlists.
Representative Web3 scenarios:
- Deliver only ERC-20 transfers above a threshold:
payload.event == "Transfer" && payload.value > 10_000 * pow(10, payload.decimals)
- Deliver events from specific contracts or chains:
payload.contractAddress == "0xabc..." && payload.chainId == 1
- NFT collection and token range:
payload.event == "Transfer" && payload.contractAddress == "0xNFT..." && payload.tokenId in [1,2,3]
- Stablecoin-only transfers:
payload.symbol in ["USDC", "USDT", "DAI"] && payload.value > 0
- Wallet allowlist or blocklist:
payload.to in ["0xAlice...", "0xBob..."]
This reduces noise and cost for consumers by skipping irrelevant deliveries.
Proposal
- Add an optional
filter
field on endpoint create/update that evaluates a boolean expression against the message JSON payload. - Recommended expression language: Google CEL (Common Expression Language) for safety, performance, and expressiveness (non–Turing-complete, no side effects, widely adopted).
Example request:
{
"url": "https://operational-webhook-destination.com/webhook/",
"filterTypes": ["user.create", "user.updated"],
"filter": "payload.user.age < 18"
}
Server behavior:
- During dispatch, after existing
filterTypes
andchannels
checks, evaluatefilter
against the payload. - If
filter
is absent, proceed as today. - If evaluation fails (syntax/type/runtime), fail-closed for that endpoint (skip delivery) and emit logs/operational webhook.
Performance and safety:
- Precompile/cache expressions per endpoint.
- Evaluate only after other pruning to minimize work.
- Restrict accessible variables to
payload
and safe stdlib; enforce time/memory limits.
Potential drawbacks:
- Slight dispatch overhead per endpoint due to expression evaluation (mitigated by precompilation and caching).
- Complexity in error handling (decide reject on invalid expressions vs. accept-but-disabled; proposed: reject with validation error).
Alternatives
- Publisher-side filtering: Shifts complexity to producers, often infeasible for multi-tenant or shared pipelines; duplicates logic across clients.
- Overloading
channels
as pseudo-filters: Coarse-grained, not expressive for payload content (e.g., numeric thresholds, nested fields). - Custom DSL: Higher maintenance and security burden vs adopting a well-known, safe, non–Turing-complete language like CEL.
- Consumer-side filtering: Increases delivery volume, wastes bandwidth and compute, adds latency and cost.
CEL was chosen for:
- Strong safety guarantees, no loops/recursion, no side effects.
- Good performance with precompilation and a small runtime surface.
- Sufficient expressiveness for Web3 and general content-based routing.
Metadata
Metadata
Assignees
Labels
No labels