Use case
The Metrics class has a fluent interface where methods like addMetric(), addDimension(), and publishStoredMetrics() return this. Currently, users who are not using the decorator or Middy middleware must either call publishStoredMetrics() manually or wrap their handler logic in try/finally to ensure metrics are flushed on error paths:
const metrics = new Metrics({ namespace: 'serverlessAirline', serviceName: 'orders' });
export const handler = async () => {
try {
metrics.addMetric('successfulBooking', MetricUnit.Count, 1);
// business logic
} finally {
metrics.publishStoredMetrics();
}
};
JavaScript's Explicit Resource Management proposal (Stage 3, shipping in Node.js 24) introduces the using keyword, which calls [Symbol.dispose]() automatically when a binding goes out of scope — including when an exception is thrown. Since the fluent methods already return this, making Metrics implement Disposable is a natural fit.
Solution/User Experience
Implement [Symbol.dispose]() on the Metrics class, delegating to publishStoredMetrics(). This allows users to write:
const metrics = new Metrics({ namespace: 'serverlessAirline', serviceName: 'orders' });
export const handler = async () => {
using _ = metrics.addMetric('successfulBooking', MetricUnit.Count, 1);
metrics.addDimension('region', 'us-west-2');
// metrics are automatically flushed when scope exits, including on exceptions
};
The implementation is straightforward. Add the method to the Metrics class:
public [Symbol.dispose](): void {
this.publishStoredMetrics();
}
And the corresponding signature to MetricsInterface:
[Symbol.dispose](): void;
No AsyncDisposable is needed since publishStoredMetrics() is synchronous. The method is safe to call on an already-flushed instance — publishStoredMetrics() checks hasStoredMetrics() and simply logs a warning if the buffer is empty, which is the same behaviour that already occurs with the decorator and middleware patterns.
On the TypeScript side, ESNext.Disposable needs to be added to the lib compiler option since the Disposable types have not yet been promoted to any yearly ES lib (including ES2024). This is purely a compile-time type concern — it does not change emitted code or require runtime polyfills:
{
"compilerOptions": {
"target": "ES2023",
"lib": ["ES2023", "ESNext.Disposable"]
}
}
The using keyword requires Node.js 24+. The [Symbol.dispose] method itself is harmless on older runtimes (the symbol exists from Node 18+, it simply won't be called without the using syntax). Unit and e2e tests for this feature should be gated with describe.skipIf(process.versions.node < '24').
Alternative solutions
The existing decorator (@metrics.logMetrics()) and Middy middleware already provide automatic flushing. The using pattern is a lighter-weight alternative for users who prefer not to adopt those patterns.
Acknowledgment
The using/IDisposable pattern is native to .NET and could be considered there. Python and Java do not have an equivalent language feature.
Future readers
Please react with 👍 and your use case to help us understand customer demand.
Use case
The Metrics class has a fluent interface where methods like
addMetric(),addDimension(), andpublishStoredMetrics()returnthis. Currently, users who are not using the decorator or Middy middleware must either callpublishStoredMetrics()manually or wrap their handler logic intry/finallyto ensure metrics are flushed on error paths:JavaScript's Explicit Resource Management proposal (Stage 3, shipping in Node.js 24) introduces the
usingkeyword, which calls[Symbol.dispose]()automatically when a binding goes out of scope — including when an exception is thrown. Since the fluent methods already returnthis, makingMetricsimplementDisposableis a natural fit.Solution/User Experience
Implement
[Symbol.dispose]()on theMetricsclass, delegating topublishStoredMetrics(). This allows users to write:The implementation is straightforward. Add the method to the
Metricsclass:And the corresponding signature to
MetricsInterface:No
AsyncDisposableis needed sincepublishStoredMetrics()is synchronous. The method is safe to call on an already-flushed instance —publishStoredMetrics()checkshasStoredMetrics()and simply logs a warning if the buffer is empty, which is the same behaviour that already occurs with the decorator and middleware patterns.On the TypeScript side,
ESNext.Disposableneeds to be added to thelibcompiler option since theDisposabletypes have not yet been promoted to any yearly ES lib (including ES2024). This is purely a compile-time type concern — it does not change emitted code or require runtime polyfills:{ "compilerOptions": { "target": "ES2023", "lib": ["ES2023", "ESNext.Disposable"] } }The
usingkeyword requires Node.js 24+. The[Symbol.dispose]method itself is harmless on older runtimes (the symbol exists from Node 18+, it simply won't be called without theusingsyntax). Unit and e2e tests for this feature should be gated withdescribe.skipIf(process.versions.node < '24').Alternative solutions
The existing decorator (
@metrics.logMetrics()) and Middy middleware already provide automatic flushing. Theusingpattern is a lighter-weight alternative for users who prefer not to adopt those patterns.Acknowledgment
The
using/IDisposablepattern is native to .NET and could be considered there. Python and Java do not have an equivalent language feature.Future readers
Please react with 👍 and your use case to help us understand customer demand.