BeforeEventsDispatch handler is a custom module hook that allows you to intercept and process a batch of events
received from supported message providers before it is dispatched to GraphQL subscription clients.
Unlike OnReceiveEvents, this handler runs once per batch,
before the batch is fanned out to any subscriber.
This handler is particularly useful for:
- Event filtering: Remove unwanted events before they reach any subscriber
- Data transformation: Modify event payloads to match client expectations
- Event enrichment: Add additional data to events from external sources
- Monitoring and analytics: Log or track events for observability
This handler is very similar to the
This comes with a trade-off. Event processing with this handler is much more lightweight because on a Router with 1000 subscribers this handler runs once instead of 1000 times. The downside is that you can’t do per-subscriber decisions in this hook. For that you need to use the
OnReceiveEvents but in contrast only runs once per batch, whereas the OnReceiveEvents handler runs for each active subscriber.This comes with a trade-off. Event processing with this handler is much more lightweight because on a Router with 1000 subscribers this handler runs once instead of 1000 times. The downside is that you can’t do per-subscriber decisions in this hook. For that you need to use the
OnReceiveEvents handler.
A rule of thumb is to use this hook when you want to change the event for every client the same way.If there is no active subscription this handler is not executed, even if new messages arrive at the provider.
This is because the Router will not listen for messages on the provider topic/queue until at least one
client subscribes to a particular subscription.
Handler Interface
In order to use theBeforeEventsDispatch handler you need to create a Custom Module which implements
the StreamBeforeEventsDispatchHandler interface.
Execution Order and Performance Considerations
BeforeEventsDispatch runs before OnReceiveEvents. The router calls it once for the whole batch as soon as it is
received from the provider, and only afterwards fans the (possibly modified) batch out to each active subscriber’s
OnReceiveEvents handler.
If you register multiple modules implementing BeforeEventsDispatch, they are executed sequentially, with each
handler receiving the events returned by the previous one.
Because this handler runs once per batch instead of once per subscriber, there is no max_concurrent_handlers
option to configure. You can, however, configure how long the router waits for the handler(s) to finish before
giving up on the batch:
OnReceiveEvents does not run for that batch. A warning is logged in both cases.
It is recommended to use ctx.Context(), which is cancelled in such situations.
You can use this context to abort any long-running operations:
Error Handling
When theBeforeEventsDispatch handler returns an error, the router takes the following actions:
- Batch Dropped: The entire batch of events is discarded and never delivered to any subscriber
- No Subscription Closure: Unlike
OnReceiveEvents, subscriptions stay open; the router simply waits for the next batch from the provider - Error Logging: The error is logged by the router with details about the provider and field name
- No Error Propagation: The error is not sent to any GraphQL client
Usage Example
Complete Custom Module with Event Bypass
The following example contains a complete Custom Module implementation, including handler registration, with a handler that will simply bypass events unchanged. This is not useful on it’s own but demonstrates how to register yourBeforeEventsDispatch Custom Module.
Restrict Handler to run on certain subscriptions and providers
Most of the time you want your hook to only deal with a certain subscription. TheBeforeEventsDispatch Handler is run for every subscription configured for Cosmo Streams.
You can access the name of the subscription you care for and return early if it’s not the right one.