openmesh-nodeApplication runtimeHTTP, routing, lifecycle, typed route shorthand and application mesh facade.
OpenMesh is a TypeScript service runtime for Node.js. Use the native HTTP runtime by itself, add your existing database client, then turn on discovery, traffic policy, workload identity and service-to-service calls only when the application needs them.
The default path is ordinary HTTP. No sidecar, controller class or custom query layer is required.
npm install openmesh-node
import openmesh, { created } from 'openmesh-node';
import { bodyParser } from 'openmesh-node/plugins';
const app = openmesh();
app.use(bodyParser());
app.post('/users/:id', {
body: NewUser,
response: {
201: User,
409: Problem
}
}, async ({ body, params }) => {
return created(await users.create({
id: params.id,
...body
}));
});
await app.listen({ port: 3000 });
Routing, body parsing, Standard Schema validation, typed response contracts and graceful lifecycle all stay inside the Node.js process.
openmesh-nodeApplication runtimeHTTP, routing, lifecycle, typed route shorthand and application mesh facade.
openmesh-node/pluginsRequest pluginsBody parsers, health checks and ecosystem integration points.
openmesh-node/dbDatabase lifecycleKeep Prisma, Drizzle, Kysely, TypeORM or your existing client API.
openmesh-node/meshPeer data planePeer selection, admission, deadlines, retries, circuits and streams.
openmesh-node/servicesControl planeRegistration, discovery, config snapshots, watches and managed pools.
openmesh-node/otelMetrics bridgeOpenTelemetry-compatible metrics without coupling core to the SDK.
OpenMesh 0.5 adds Standard Schema input inference and response contracts directly to
app.get/post/.... The advanced functional contract API remains optional.
Use openmesh-node/http when routes need to exist as immutable values for tooling, client generation, policy inspection or contract-first tests.
openmesh-node/db does not invent a query language. It gives your existing client application lifecycle, readiness and an optional typed transaction boundary.
import { database } from 'openmesh-node/db';
const db = database(prisma, {
name: 'primary',
connect: client => client.$connect(),
disconnect: client => client.$disconnect(),
transaction: (client, work) => client.$transaction(work)
});
app.register(db);
app.get('/users', async () => db.client.user.findMany());
Configure the application once, then use lazy app.mesh(name) handles.
The first real call creates one managed service pool and reuses its discovery, pressure and failure state.
const app = openmesh({
service: 'gateway',
mesh: {
control: {
url: process.env.OPENMESH_CONTROL_URL!,
token: process.env.OPENMESH_TOKEN!
}
}
});
const payments = app.mesh('payments');
const charge = await payments.post('/charges', {
key: user.id,
body: { userId: user.id, amount: order.total }
});
0.5 separates traffic targeting from peer selection. That keeps canaries, regional failover and affinity composable with the same retries, circuits and concurrency controls.
Ordered rules can select a subset from inbound request metadata without blindly forwarding those headers.
Split traffic across version/metadata groups. A request key keeps weighted selection sticky.
Prefer zones or regions in order, then move outward only when eligible local peers are unavailable.
Control-plane config revisions can replace traffic policy without rebuilding the service pool or restarting the process.
A service can bind itself to a SPIFFE-style identity. OpenMesh validates the local certificate before startup, requires authenticated inbound peers and verifies the expected service identity on outbound mesh calls.
const payments = openmesh({
service: 'payments',
identity: {
trustDomain: 'mesh.example.internal',
ca,
cert,
key,
allow: ['gateway']
}
});
// Expected URI SAN:
// spiffe://mesh.example.internal/service/payments
app.workload.rotate(...) swaps the inbound secure context for new connections and rotates outbound mesh TLS agents with an optional drain grace period.
Registration leases, membership revisions and configuration epoch + revision make distributed state changes explicit. Authenticated SSE watches are the steady-state path; polling remains a compatibility fallback.
Application and peer lifecycle events are emitted only when observers are configured. The OpenTelemetry bridge consumes those events without making the SDK a core runtime dependency.
request start, finish, error and actual response completion.
attempt, success, failure, cancellation, queue pressure and adaptive limit changes.
request IDs and W3C traceparent propagate through AsyncLocalStorage and mesh calls.
the metrics bridge avoids raw paths, bodies, tokens and arbitrary high-cardinality values.