XMS: XyPriss Multi-Server Orchestration
Run multiple isolated server instances within a single Node.js process, each with independent ports, security policies, caching strategies, and route scopes while sharing the same underlying system resources.
Why XMS?
Process Efficiency
Shared memory and system overhead compared to running multiple independent Node.js processes.
Network Isolation
Different security levels for Admin vs Public APIs on distinct ports within the same process.
Unified Lifecycle
Start, stop, and monitor all services from a single entry point. One app.start() boots all configured instances.
Route Scoping
Granular control over which routes are served by which instance via allowedRoutes and prefix strategies.
Server Configuration
XMS is configured programmatically via the ServerOptions passed to createServer. Each entry in the servers array supports the following properties:
| Property | Type | Description |
|---|---|---|
| id | string | Required. Unique identifier for the server instance (used in logs). |
| port | number | Required. The port the instance will listen on. |
| host | string | Host address (default: 127.0.0.1). |
| routePrefix | string | A prefix to filter or inject into routes handled by this instance. |
| routePrefixStrategy | string | Prefix handling: auto-inject (default), strict-match, or both. |
| allowedRoutes | string[] | Patterns of routes this instance is allowed to serve (e.g., ["/api/*", "/login"]). |
| responseControl | object | Custom behaviour for unhandled routes on this instance. |
| ...ServerOptions | any | Any other ServerOptions (security, cache, fileUpload, etc.) to override per instance. |
import { createServer } from "xypriss";
const app = createServer({
multiServer: {
enabled: true,
servers: [
{
id: "public-api",
port: 8080,
routePrefix: "/api/v1",
routePrefixStrategy: "auto-inject",
allowedRoutes: ["/api/*"],
host: "0.0.0.0"
},
{
id: "admin-panel",
port: 8081,
routePrefix: "/admin",
security: { csrf: true, helmet: true }
}
]
}
});Global Configuration Merging
XyPriss implements a Global Merge Rule to reduce configuration redundancy. Options defined at the root of the ServerOptions object are treated as global defaults for all server instances.
The merge strategy is deep: nested objects like security.helmet or logger.format are intelligently combined. Server-level options always take precedence over root-level globals.
const app = createServer({
// --- GLOBAL SETTINGS ---
// All servers will use 'debug' level and have CSRF enabled
logger: { level: "debug" },
security: { csrf: true },
multiServer: {
enabled: true,
servers: [
{
id: "public",
port: 8080
// Inherits: logger { level: "debug" }, security { csrf: true }
},
{
id: "internal",
port: 8081,
logger: { level: "info" } // Overrides global logger level
// Inherits: security { csrf: true }
}
]
}
});Route Orchestration
Control how routes are distributed across instances using the routePrefixStrategy and allowedRoutes properties.
If a route is /login and the server has a prefix /auth, it will be served at /auth/login on that instance.
Only routes explicitly registered with the prefix (e.g., app.get("/auth/login")) are served.
The route is served at both its original path and the prefixed path.
Instance-Level Response Control
You can define what happens when a request hits a server port but doesn't match any allowed routes. This feature uses the global responseControl system, but can be applied per server instance for strong isolation.
{
"responseControl": {
"enabled": true,
"statusCode": 403,
"content": { "error": "Access Denied to this Server Instance" },
"contentType": "application/json",
"headers": { "X-XMS-Status": "Filtered" }
}
}See the NotFound vs Response Control guide for a detailed comparison of visual 404 handlers vs functional response interception.
Security & Isolation
Independent Security
One port can have strict CSRF and Helmet, while another is open for public Webhooks.
Isolated XEMS
If enabled, each instance can have its own Encrypted Memory Store for session isolation.
Custom Logging
Logs are prefixed with the server id for easy debugging in multi-instance environments.
Programmatic Usage
import { createServer } from "xypriss";
const app = createServer({
multiServer: {
enabled: true,
servers: [
{ id: "web", port: 3000 },
{ id: "api", port: 4000, routePrefix: "/api" }
]
}
});
// Routes are distributed based on the XMS config
app.get("/", (req, res) => res.send("Web Home"));
app.get("/api/data", (req, res) => res.json({ data: [] }));
app.start();multiServer is enabled, app.start() will boot all configured instances concurrently. Ensure your system has permissions to bind to the requested ports before starting.Understand the difference between visual 404 templates and functional response interception.
