Learn about Feathers real-time event system for broadcasting service changes to connected clients
Feathers provides a powerful real-time event system built on Node’s EventEmitter. Services automatically emit events when data changes, enabling real-time applications with minimal code.
// When create() is calledconst user = await service.create({ email: '[email protected]'})// Event 'created' is emittedservice.on('created', (user, context) => { console.log('New user created:', user)})
// When update() is calledconst user = await service.update(1, { email: '[email protected]', name: 'New Name'})// Event 'updated' is emittedservice.on('updated', (user, context) => { console.log('User updated:', user)})
// When patch() is calledconst user = await service.patch(1, { name: 'Updated Name'})// Event 'patched' is emittedservice.on('patched', (user, context) => { console.log('User patched:', user)})
// When remove() is calledconst user = await service.remove(1)// Event 'removed' is emittedservice.on('removed', (user, context) => { console.log('User removed:', user)})
Control which clients receive events using publishers:
// Only send to authenticated usersapp.service('messages').publish('created', async (data, context) => { return app.channel('authenticated')})// Send to specific usersapp.service('messages').publish('created', async (data, context) => { // Send to message recipient return app.channel(`user/${data.recipientId}`)})// Conditional publishingapp.service('users').publish('created', async (data, context) => { // Don't send to the user who created it return app.channel('authenticated').filter(connection => { return connection.user.id !== data.id })})
Publishing requires a transport like @feathersjs/socketio or @feathersjs/primus and channel configuration.
Multiple independent systems need to know about changes
You’re building real-time features
You need loose coupling between services
You want to broadcast to multiple clients
// Good use of eventsservice.on('created', async (user) => { await emailService.sendWelcomeEmail(user) await analyticsService.track('user_signup', user) await notificationService.notify(user.friends, 'New user joined')})
Use hooks when:
You need to modify data before/after operations
You need to validate or authorize requests
The logic must complete before the method returns
You need access to the full context
You want to prevent the operation
// Good use of hooksservice.hooks({ before: { create: [ authenticate('jwt'), validateData(schema), setDefaults() ] }, after: { all: [removePassword()] }})