Spin up a real NATS server in milliseconds — for tests, local dev, and CI.
Like mongodb-memory-server, but for NATS.
It downloads the official nats-server binary once, runs it on a random free port, and tears it
down cleanly when you're done.
- 🚀 Zero config —
create().build().start()and you have a live server - 🎯 The real thing — runs the official
nats-serverbinary, not a mock - 🔌 Auto free port — no collisions when test suites run in parallel
- 🔒 Checksum-verified downloads — the binary is checked against the release
SHA256SUMS - 🧰 Fluent builder with full TypeScript types
- 🌊 JetStream ready
- 🌐 Proxy aware —
httpProxy/httpsProxy/noProxy - 🧹 Clean teardown —
stop()and the process is gone
npm install nats-memory-server
# or
yarn add nats-memory-serverThe official
nats-serverbinary is downloaded automatically onpostinstall.
const { NatsServerBuilder } = require('nats-memory-server');
const { connect } = require('nats');
// Starts on a random free port and resolves once the server is ready
const server = await NatsServerBuilder.create().build().start();
const nc = await connect({ servers: server.getUrl() });
// ... publish / subscribe ...
await nc.close();
await server.stop();A fuller publish/subscribe round-trip:
const { NatsServerBuilder } = require('nats-memory-server');
const { connect, StringCodec } = require('nats');
(async () => {
// Start the server (a free port is picked automatically if none is set)
const server = await NatsServerBuilder.create().build().start();
console.log(`NATS server started at ${server.getUrl()}`);
try {
const nc = await connect({ servers: server.getUrl() });
const sc = StringCodec();
const sub = nc.subscribe('hello');
(async () => {
for await (const m of sub) {
console.log(`[${sub.getProcessed()}]: ${sc.decode(m.data)}`);
}
})();
nc.publish('hello', sc.encode('world'));
await nc.drain(); // flush in-flight messages, then close
} catch (err) {
console.error(err);
} finally {
await server.stop();
}
})();💡 Runnable version: example.js.
Configuration drives two things:
-
Installation — which
nats-serverbinary to download or build (duringpostinstall). -
Runtime — how the server instance behaves (
port,ip,args, …).
Provide it via any of: nats-memory-server.json · nats-memory-server.js · nats-memory-server.ts · the natsMemoryServer key in package.json.
| Option | Type | Default | Description |
|---|---|---|---|
download |
boolean |
true |
Download the binary during postinstall. |
downloadDir |
string |
node_modules/.cache/nats-memory-server |
Where the downloaded binary is cached. |
version |
string |
v2.9.16 |
nats-server version to download. |
buildFromSource |
boolean |
false |
Build from source instead of downloading (requires Go). |
binPath |
string |
(cache path above) | Path to the nats-server binary. |
httpProxy |
string |
– | Proxy URL for HTTP requests. |
httpsProxy |
string |
– | Proxy URL for HTTPS requests. |
noProxy |
string |
– | Domains that bypass the proxy. |
verifyChecksum |
'strict' | 'warn' | 'off' |
warn |
Integrity-check the download against the release SHA256SUMS. |
🔒
verifyChecksum— a checksum mismatch always aborts the install (onlyoffskips the check entirely).warn(default) additionally just warns when a checksum can't be obtained (customdownloadUrl,buildFromSource, or an unreachableSHA256SUMS);strictaborts in that case too.
| Option | Type | Default | Description |
|---|---|---|---|
port |
number |
(random free port) | Port to listen on. |
ip |
string |
127.0.0.1 |
Bind address. Use 0.0.0.0 to expose on all interfaces — |
verbose |
boolean |
true |
Verbose logging. |
args |
string[] |
[] |
Extra arguments passed straight to nats-server. |
Example config files
nats-memory-server.json
{
"version": "v2.9.16",
"verbose": false,
"port": 4222
}In package.json
{
"natsMemoryServer": {
"version": "v2.9.16",
"port": 4222
}
}Full default configuration
{
"download": true,
"downloadDir": "node_modules/.cache/nats-memory-server",
"version": "v2.9.16",
"buildFromSource": false,
"binPath": "node_modules/.cache/nats-memory-server/nats-server",
"verifyChecksum": "warn",
"verbose": true,
"ip": "127.0.0.1"
}Fluent builder for NatsServer instances — every setter returns this, so calls chain.
| Method | Description |
|---|---|
static create(options?) |
Create a new builder, optionally seeded with partial options. |
setPort(port: number) |
Set the listen port. |
setIp(ip: string) |
Set the bind address. |
setVerbose(verbose: boolean) |
Toggle verbose logging. |
setArgs(args: string[]) |
Set extra nats-server arguments. |
setBinPath(binPath: string) |
Set the path to the nats-server binary. |
setLogger(logger: Logger) |
Provide a custom logger (log, error, warn, debug). |
build() |
Build and return a NatsServer. |
| Method | Returns | Description |
|---|---|---|
start() |
Promise<this> |
Start the server; resolves once it is ready (rejects if it can't). |
stop() |
Promise<void> |
Stop the server. |
getUrl() |
string |
Connection URL, e.g. nats://127.0.0.1:4222. |
getHost() |
string |
The bind host. |
getPort() |
number |
The listen port. |
Enable JetStream with setArgs (or constructor options):
const os = require('os');
const { NatsServerBuilder } = require('nats-memory-server');
await NatsServerBuilder.create()
.setArgs(['--jetstream', '--store_dir', os.tmpdir()])
.build()
.start();Using the constructor directly
const os = require('os');
const { NatsServer, DEFAULT_NATS_SERVER_OPTIONS } = require('nats-memory-server');
new NatsServer({
...DEFAULT_NATS_SERVER_OPTIONS,
args: ['--jetstream', '--store_dir', os.tmpdir()],
});Spin up one server per suite — start it in beforeAll, tear it down in afterAll:
const { NatsServerBuilder } = require('nats-memory-server');
const { connect } = require('nats');
let server;
let nc;
beforeAll(async () => {
server = await NatsServerBuilder.create().build().start();
nc = await connect({ servers: server.getUrl() });
});
afterAll(async () => {
await nc.close();
await server.stop();
});
test('should publish and subscribe', async () => {
// your test logic here
});- Node.js ≥ 16
-
Go ≥ 1.19 — optional, only needed when
buildFromSourceis enabled
Contributions are welcome! Found a bug or have an idea? Open an issue or a pull request.
Please follow the Code of Conduct.