Seneca Microservices Framework
Seneca is a mature Node.js microservices framework designed to help organize application business logic through a pattern-matching approach to message passing. Currently at stable version 3.38.0, its release cadence is active but irregular, with a focus on stability and a smaller core. Key differentiators include its flexible pattern-matching for defining commands, transport independence that abstracts message delivery, and a robust ecosystem of plugins for common microservice concerns like data storage, user management, and distributed logic. The framework emphasizes breaking down applications into 'stuff that happens' rather than strict data models, providing a flexible toolkit for building Minimum Viable Products and complex distributed systems. It supports Node.js versions 10 and above and ships with TypeScript types.
Common errors
-
Error: Seneca: Plugin 'seneca-entity' not found.
cause The `seneca-entity` plugin, responsible for database entity operations, was removed from Seneca's core distribution in v2.0.0 and must now be explicitly installed and loaded.fixInstall the plugin via `npm install seneca-entity` and add `seneca.use('entity')` to your Seneca instance initialization. -
Error: Seneca: No matching action for pattern { cmd: 'my-command', ... }cause The message sent via `seneca.act()` does not match any registered action patterns (`seneca.add()`). This can be due to a typo, an unloaded plugin that defines the action, or incorrect message parameters.fixVerify the exact pattern used in `seneca.act()` matches an existing `seneca.add()` definition. Ensure all necessary plugins defining actions are loaded using `seneca.use()`, and check that message properties align with the pattern's requirements. -
TypeError: Seneca is not a constructor
cause This error typically occurs when attempting to call `new Seneca()` or `Seneca()` when `Seneca` was imported using a CommonJS `require` statement, but the module is expecting a default export in an ESM context, or vice-versa.fixIf using CommonJS, ensure you're using `const Seneca = require('seneca'); const seneca = Seneca();`. If using ESM, ensure `import Seneca from 'seneca'; const seneca = Seneca();` and that your Node.js environment is configured for ESM. -
Error: listen() failed: port already in use
cause The specified port for a Seneca transport listener (e.g., HTTP) is already being used by another process or another instance of your application.fixEnsure that no other applications or services are running on the desired port. If running multiple Seneca instances, configure each to use a unique port for its listeners, or ensure previous processes are properly shut down before starting new ones.
Warnings
- breaking Seneca v3.0.0 removed all default plugins (except `seneca-transport`) to make the core smaller and more stable. Applications upgrading from v2.x or earlier must explicitly install and load any previously implicitly available plugins (e.g., `seneca-basic`, `seneca-web`, etc.).
- breaking Seneca v2.0.0 made a significant change by no longer installing and using the `seneca-entity` plugin by default. Projects relying on database entity interactions implicitly will encounter errors.
- gotcha Since v3.0.0, Seneca defaults to JSON output for logs. If you relied on the previous 'pretty' logging format or had custom log handlers, you will need to adjust your logging configuration or use the `seneca-legacy-logger` plugin.
- gotcha Seneca v3.3.0 introduced a change allowing action callbacks to omit the Error parameter (hapi style). While this adds flexibility, it can lead to inconsistent callback signatures if not managed carefully across your codebase.
- gotcha Earlier versions of Seneca (prior to v3.7.0 and v3.2.0) had known memory leak issues, specifically related to the history mechanism and Gate Executor timeouts. Running older 3.x versions might lead to resource exhaustion over time.
Install
-
npm install seneca -
yarn add seneca -
pnpm add seneca
Imports
- Seneca
import Seneca from 'seneca'
const Seneca = require('seneca') - Seneca
const Seneca = require('seneca')import Seneca from 'seneca'
- Seneca.util
const Seneca = require('seneca'); const { Eraro, Jsonic, Nid, Patrun } = Seneca.util;
Quickstart
'use strict'
var Seneca = require('seneca')
function rejector () {
this.add('cmd:run', (msg, done) => {
return done(null, {tag: 'rejector'})
})
}
function approver () {
this.add('cmd:run', (msg, done) => {
return done(null, {tag: 'approver'})
})
}
function local () {
this.add('cmd:run', function (msg, done) {
this.prior(msg, (err, reply) => {
return done(null, {tag: reply ? reply.tag : 'local'})
})
})
}
Seneca()
.use(approver)
.listen({type: 'http', port: '8260', pin: 'cmd:*'})
Seneca()
.use(rejector)
.listen(8270)
function handler (err, reply) {
console.log(err, reply)
}
Seneca()
.use(local)
.act('cmd:run', handler)
Seneca()
.client({port: 8270, pin: 'cmd:run'})
.client({port: 8260, pin: 'cmd:run'})
.use(local)
.act('cmd:run', handler)
Seneca()
.client({port: 8260, pin: 'cmd:run'})
.client({port: 8270, pin: 'cmd:run'})
.use(local)
.act('cmd:run', handler)