Performance Pipeline
Introduction
Section titled “Introduction”The Performance Pipeline measures how long commands and queries take to execute and logs a warning when their execution time exceeds the configured threshold.
You enable it through AppBuilder.addPipeline().
The pipeline supports two levels of configuration:
thresholdMs: global threshold used for all intents.intentThresholdMs: optional thresholds for specific intents.
When an intent has a specific threshold configured, that value takes precedence over the global threshold.
Enable the Performance Pipeline
Section titled “Enable the Performance Pipeline”Add the pipeline when configuring your application:
const app = new AppBuilder() .addPipeline() .build()Calling addPipeline() enables the CQRS pipelines, including the Performance Pipeline.
Configure the Global Threshold
Section titled “Configure the Global Threshold”Use config.performance.thresholdMs to define the default threshold for commands and queries.
const app = new AppBuilder() .addPipeline((config) => { config.performance.thresholdMs = 500 }) .build()The default value is:
500The value is expressed in milliseconds.
The global threshold is used whenever the current request intent does not have a specific threshold configured.
Configure Thresholds by Intent
Section titled “Configure Thresholds by Intent”You can configure a different threshold for individual intents with config.performance.intentThresholdMs.
The object key is the request intent, which corresponds to the token associated with the registered handler.
const app = new AppBuilder() .addPipeline((config) => { config.performance.thresholdMs = 500
config.performance.intentThresholdMs = { CREATE_USER_HANDLER: 300, } }) .build()In this example:
- all requests use
500msby default; - requests with intent
CREATE_USER_HANDLERuse300ms; - the specific
CREATE_USER_HANDLERthreshold overrides the global threshold.
This is useful when different application operations have different expected execution times.
Global and Intent-Specific Thresholds
Section titled “Global and Intent-Specific Thresholds”You can configure multiple intents independently:
const app = new AppBuilder() .addPipeline((config) => { config.performance.thresholdMs = 500
config.performance.intentThresholdMs = { CREATE_USER_HANDLER: 300, UPDATE_USER_HANDLER: 400, DELETE_USER_HANDLER: 250, GET_USER_HANDLER: 100, } }) .build()The effective threshold for a request is selected in this order:
config.performance.intentThresholdMs[request.intent]config.performance.thresholdMs- the default global threshold of
500ms
For example, with:
config.performance.thresholdMs = 500
config.performance.intentThresholdMs = { CREATE_USER_HANDLER: 300,}the behavior is:
| Intent | Effective threshold |
|---|---|
CREATE_USER_HANDLER |
300ms |
UPDATE_USER_HANDLER |
500ms |
DELETE_USER_HANDLER |
500ms |
| Any unconfigured intent | 500ms |
An intent-specific threshold is therefore an override, not an additional threshold.
Configure Only Specific Intents
Section titled “Configure Only Specific Intents”You can keep the global threshold and override only the operations that require different limits:
const app = new AppBuilder() .addPipeline((config) => { config.performance.thresholdMs = 1000
config.performance.intentThresholdMs = { CREATE_USER_HANDLER: 300, CHECKOUT_HANDLER: 800, } }) .build()Here:
CREATE_USER_HANDLERuses300ms;CHECKOUT_HANDLERuses800ms;- every other intent uses
1000ms.
Performance Warnings
Section titled “Performance Warnings”When execution exceeds the effective threshold, the pipeline logs a warning:
Performance warning: CREATE_USER_HANDLER took 342.17msThe warning contains:
- the request intent;
- the measured execution time in milliseconds.
A warning is logged only when the execution time is greater than the effective threshold.
For example, with a threshold of 300ms:
299ms→ no warning;300ms→ no warning;301ms→ warning.
Threshold Validation
Section titled “Threshold Validation”All thresholds must be positive integers.
For example, this configuration is invalid:
const app = new AppBuilder() .addPipeline((config) => { config.performance.thresholdMs = 0
config.performance.intentThresholdMs = { CREATE_USER_HANDLER: -100, } })Threshold values must be greater than zero and must be integers.
For intent-specific thresholds, each configured value is validated independently.
Complete Example
Section titled “Complete Example”The following example configures a global threshold together with different thresholds for selected handlers:
const app = new AppBuilder() .addPipeline((config) => { // Fallback threshold for all intents. config.performance.thresholdMs = 500
// Overrides for specific handler intents. config.performance.intentThresholdMs = { CREATE_USER_HANDLER: 300, UPDATE_USER_HANDLER: 400, CHECKOUT_HANDLER: 1000, } }) .build()The resulting behavior is:
CREATE_USER_HANDLER → 300msUPDATE_USER_HANDLER → 400msCHECKOUT_HANDLER → 1000msEverything else → 500msCommands and Queries
Section titled “Commands and Queries”The Performance Pipeline applies to both commands and queries executed through the configured CQRS pipeline.
The intent-specific configuration works the same way for both:
config.performance.intentThresholdMs = { CREATE_USER_HANDLER: 300, GET_USER_HANDLER: 100,}The intent identifies the operation being executed, regardless of whether it is a command or query.
Troubleshooting
Section titled “Troubleshooting”My intent-specific threshold is ignored
Section titled “My intent-specific threshold is ignored”Check that the key in intentThresholdMs exactly matches the request intent:
config.performance.intentThresholdMs = { CREATE_USER_HANDLER: 300,}
// Check if you added the handler in the container with the same keycontainer.addScoped('CREATE_USER_HANDLER', () => new CreateUserHandler())
// Check if you are using the correct intent in the command or queryexport class CreateUserCommand extends Command<null> { constructor() { super('CREATE_USER_HANDLER') }}
// Che if you are using the correct key in the registryexport type MyRegistry { CREATE_USER_HANDLER: CreateUserHandler}The key must be the same intent associated with the handler.
If the intent does not match, Xeno.JS falls back to:
config.performance.thresholdMsI expected a warning at exactly the threshold
Section titled “I expected a warning at exactly the threshold”The pipeline logs a warning only when execution time is greater than the threshold.
With:
config.performance.thresholdMs = 500an execution time of exactly 500ms does not generate a warning.
My threshold value is rejected
Section titled “My threshold value is rejected”Check that the value is a positive integer.
Valid:
3005001000Invalid:
0-100250.5Related Documentation
Section titled “Related Documentation”Support Us
Section titled “Support Us”Xeno.JS is an MIT-licensed open source project. It can grow thanks to the support of these awesome people. If you’d like to join them, please read more at support section
