
Webiny Event Handler Pattern
EventHandler implementation pattern, handle method, event payloads, filtering, DI...
Install
npx skills add webiny/webiny-js --skill webiny-event-handler-pattern -g -a claude-code -y- Repository
- webiny/webiny-js8.1k
- Category
- Engineering
- Updated
- 5d ago
- License
- See repository
- Context cost
- Mediumabout 2,691 tokens
- Runs scripts
- No, instructions only
What it does
EventHandler implementation pattern, handle method, event payloads, filtering, DI, domain event definition, publishing events from UseCases, and reacting to external events. Use this skill to implement any Webiny EventHandler (before/after hooks) or to define and publish your own domain events.
EventHandler Pattern
What It Is
An EventHandler reacts to domain events in the Webiny lifecycle (e.g., EntryBeforeCreateEventHandler, TenantAfterDeleteEventHandler). Each handler is a DI abstraction with a single handle method.
Naming Convention
{Entity}Before{Operation}EventHandler, fires before persistence, can validate/transform/reject{Entity}After{Operation}EventHandler, fires after persistence, for side effects
Interface Shape
interface SomeEventHandler.Interface {
handle(event: SomeEventHandler.Event): Promise<void>;
}
The Event is a DomainEvent<Payload> where the payload contains the entity and input data.
Architecture Rule: Always Wrap Logic in a Reusable Abstraction (MANDATORY)
Never put business logic directly inside an EventHandler. EventHandlers are thin orchestrators, they receive an event and delegate to an injected service or use case. The real logic lives in a dedicated abstraction.
Why: Inline handler logic cannot be reused by other handlers, GraphQL resolvers, or CLI commands.
Always follow this structure:
features/
├── myService/ ← the reusable abstraction
│ ├── abstractions.ts
│ ├── feature.ts
│ └── MyService.ts
└── syncOnCreate/ ← thin handler that injects the service
├── feature.ts
└── EntryAfterCreateHandler.ts
The EventHandler feature and the service feature are registered separately in Extension.ts.
How to Implement
import { SomeEventHandler } from "webiny/api/<category>";
import { MyService } from "../myService/abstractions.js";
// ✅ Handler is a thin orchestrator, no business logic here
class MyHandler implements SomeEventHandler.Interface {
constructor(private myService: MyService.Interface) {}
async handle(event: SomeEventHandler.Event) {
const { entity, model } = event.payload;
// For CMS handlers: ALWAYS filter by model
if (model.modelId !== "myModel") return;
