Cross-resource side effects
When a change in one resource needs to update another, subscribe instead of reaching in. Say you keep anotesCount on each user so a profile page doesn’t have to aggregate. Rather than incrementing the counter inside every notes endpoint, the users resource owns the rule and listens to notes events:
Soft deletes flow through
notes.update, since deleting a note sets deletedAt. Filtering deletedAt: null in the count keeps a deleted note out of the total. Wire a notes.delete handler too only if you hard-delete.Decoupling history and audit
Want to keep a record of every change to a resource without threading audit logic through its endpoints? Let the audit resource subscribe. Theusers resource has no idea it’s being audited:
prevDocs gives you the before-and-after for free — no diff library, no change payload to assemble. This is the inverse of importing a historyService into the users endpoints: the dependency points into the audit resource, not out of users.
Integrating external systems
Events are the natural place to fan out to anything outside your database — analytics, sockets, email, webhooks. Ship ships two of these in the base template.Analytics
users/handlers/sync-analytics.ts subscribes to users.insert and tracks a “New user created” event through analyticsService.Realtime sockets
users/handlers/to-sockets.ts subscribes to users.update and pushes the updated row to that user’s browser over Socket.IO via ioEmitter.publishToUser.When to use an event vs. a method
Not every consequence belongs in a handler. A quick rule:- Use an event when the side effect belongs to a different resource, is best-effort, or fans out to an external system — analytics, sockets, audit logs, denormalised counts, webhooks.
- Use a method or do it inline when the work is part of the same transaction or is required for the write to be correct (e.g. validating a foreign key). Events fire after the write; they’re reactions, not preconditions.
Next steps
- The event shape and types: Mutation events.
- How to write and register one: Event handlers.
