Moleculer API Gateway Version Routing Lacks Configurable Traffic Split
0 reputation · 20 Mar 2021, 13:57 UTC
0 reputation · 20 Mar 2021, 13:57 UTC
The goal is to enable a gradual, percentage‑based shift of incoming requests from an existing service version to a new version while keeping both versions deployed in the same Moleculer broker, using only the framework’s built‑in API gateway.
Currently the gateway can route to a specific version based on a static header or URL pattern, but it does not provide a way to specify a traffic split (e.g., 90 % v1, 10 % v2) or to adjust the split dynamically without manually editing the gateway configuration.
Is it possible to configure the gateway to route a configurable percentage of requests to each version? If not, what extension point or middleware would be required to achieve this behavior within Moleculer? Are there any plans to add native canary‑style traffic splitting to the versioning feature?
34275 reputation · 20 Mar 2021, 19:40 UTC
No, Moleculer’s built‑in API gateway cannot route a configurable percentage of requests to different service versions; it only supports static version matching.
version string or array, but there is no weight, split or traffic‑split option in the source (packages/moleculer-web/src/gateway.js).The gateway treats version as a deterministic selector; adding probabilistic distribution would require a layer that decides which version to target before the gateway’s internal lookup.
X-API-Version header or URL path).ctx.meta.version to that value.next() so the gateway proceeds with its normal version lookup using the overridden meta.use array) before the default handler.// trafficSplitMiddleware.js
function trafficSplitMiddleware({ weights }) {
return function (ctx, next) {
// assume version is supplied via header X-API-Version; fallback to 'v1'
const header = ctx.meta.headers?.['x-api-version'] || 'v1';
const rand = Math.random();
let acc = 0;
let chosen = header;
for (const [ver, w] of Object.entries(weights)) {
acc += w;
if (rand <= acc) {
chosen = ver;
break;
}
}
// override the version used by the gateway
ctx.meta.version = chosen;
return next();
};
}
// gateway configuration
const gatewayOptions = {
routes: [
{
path: '/api',
aliases: { ... },
// versioning still works; the middleware decides which version to send
}
],
use: [ trafficSplitMiddleware({ weights: { v1: 0.9, v2: 0.1 } }) ]
};
const apiGateway = broker.createService(require('moleculer-web'), gatewayOptions);
To finalize the middleware you need to confirm how your clients indicate the desired version (header, query string, or URL prefix). Let me know which method you use so the example can be adjusted.
Use comments to ask for clarification. Post a solution as an answer.
5,580 reputation · 20 Mar 2021, 22:01 UTC
While the gateway can only match a static version, you can inject a lightweight middleware that decides the target version at request time. The middleware reads a weight map (e.g., from env vars), generates a random number, and sets ctx.meta.version before the request reaches the gateway’s internal lookup. Because it runs before the default handler, the gateway still applies its caching and rate‑limit logic untouched.
To keep the split hot‑reloadable, expose the weight values through a config file or environment variable and reload the broker (or use broker.reload()) when they change. Verify the distribution with a simple load test and Moleculer metrics.