A utility to handle AWS Lambda timeouts gracefully by providing early detection and cleanup opportunities.
- Early timeout detection with configurable safety margin
- Support for user-provided cleanup handlers
- Graceful cleanup of resources before timeout
- Fallback timer mode for testing outside Lambda
- Configurable logging
npm install @hopdrive/lambda-timeout-wrapperimport{createTimeoutWrapper}from'@hopdrive/lambda-timeout-wrapper';// Create a wrapper with Lambda contextconstwrapper=createTimeoutWrapper({getRemainingTimeInMillis: context.getRemainingTimeInMillis,logger: console.log});// Use the wrapperconstresult=awaitwrapper(// Your main functionasync()=>{// Your long-running code herereturn{success: true};},// Timeout handlerasync()=>{// Cleanup code when timeout is imminentawaitcleanup();},// Optional user cleanup handlerasync()=>{// Additional cleanup specific to your use caseawaituserCleanup();});import{withTimeout}from'@hopdrive/lambda-timeout-wrapper';// Direct usage in Lambda handler with minimal configurationexportconsthandler=withTimeout(event,context,{// Main function to runrun: async()=>{// Your main Lambda logic herereturn{statusCode: 200,body: 'Success'};},// Cleanup handler - runs first when timeout occursonCleanup: async()=>{// Close any open resources},// Timeout handler - runs after cleanup when timeout is imminentonTimeout: async()=>{// Your timeout handling logicreturn{statusCode: 408,body: 'Request timed out'};}});This ultra-simplified API makes it easier to use the wrapper directly in your Lambda handlers. The wrapper automatically:
- Gets the remaining time from the Lambda context
- Sets sensible defaults (safetyMarginMs: 1000, logger: console.log)
- Handles the proper execution order of handlers when a timeout occurs
The wrapper accepts the following options:
interfaceTimeoutWrapperOptions{// Time in ms to start timeout handling before actual timeout (default: 5000)safetyMarginMs?: number;// Interval in ms to check for timeout (default: 1000)checkIntervalMs?: number;// Time in ms allocated for cleanup operations (default: 3000)cleanupTimeMs?: number;// Function to get remaining execution time in msgetRemainingTimeInMillis?: ()=>number;// Whether to use fallback timer instead of Lambda contextisUsingFallbackTimer?: boolean;// Logger function for timeout wrapper messageslogger?: (message: string)=>void;}The wrapper will throw a TimeoutError when a timeout is detected. This error includes:
interfaceTimeoutErrorextendsError{isLambdaTimeout: boolean;handlerError?: Error;}For testing outside of Lambda, you can use the fallback timer mode:
constwrapper=createTimeoutWrapper({isUsingFallbackTimer: true,getRemainingTimeInMillis: ()=>60000// 60 seconds});# Clone the repository
git clone https://github.com/hopdrive/lambda-timeout-wrapper.git
cd lambda-timeout-wrapper
# Install dependencies
npm install# Build all formats (CJS, ESM, and type declarations)
npm run build
# Build specific formats
npm run build:cjs
npm run build:esm
npm run build:types# Run tests
npm test# Standard deployment (specify version)
npm run deploy 1.0.1
# Force deployment (creates an empty commit, specify version)
npm run deploy-force 1.0.1
# Using the @hopdrive/package-deploy-scripts integration
npm run deploy-wrapper # Uses the wrapper around package-deploy-scriptsDuring deployment, the lib/version.js file is automatically generated using the genversion npm package. This file exports the current package version from package.json, making it accessible throughout the codebase.
This package includes several example implementations in the examples directory:
File:examples/simple-lambda-example.js
A basic example showing how to use the wrapper in a standard AWS Lambda function without any framework dependencies.
Files:
- JavaScript:
examples/netlify-function-example.js - TypeScript:
examples/netlify-function-example.ts
Shows how to use the wrapper in a Netlify Function, which runs on AWS Lambda, with database connection handling.
File:examples/local-fallback-example.js
Demonstrates how to use the wrapper with the fallback timer mode for local development and testing outside of a Lambda environment.
Install the package:
npm install @hopdrive/lambda-timeout-wrapper
For Netlify Functions:
- Create a
netlify/functionsdirectory in your project - Copy the example file and customize as needed
- Install TypeScript if using the TypeScript example:
npm install --save-dev typescript @netlify/functions
- Create a
netlify.tomlfile to configure function settings:[build] functions = "netlify/functions" [functions] # Extend the timeout to 30 seconds (default is 10)timeout = 30
- Create a
Deploy to AWS or Netlify:
- Follow standard AWS Lambda or Netlify deployment procedures
- Your functions will now gracefully handle timeouts
Install the package:
npm install @hopdrive/lambda-timeout-wrapper
Run the local example:
node examples/local-fallback-example.js
Customize timeout values:
- Adjust
getRemainingTimeInMillisto simulate different Lambda timeouts - Modify the simulated task duration to test timeout behavior
- Adjust
constwrapper=createTimeoutWrapper({// Get remaining time from Lambda context (for Lambda/Netlify)getRemainingTimeInMillis: context.getRemainingTimeInMillis,// OR use fallback timer for local testing// isUsingFallbackTimer: true,// getRemainingTimeInMillis: () => 10000, // 10 seconds// Set safety margin (how early to detect timeout)safetyMarginMs: 3000,// 3 seconds// Enable logginglogger: console.log});constresult=awaitwrapper(// Main function - your primary logicasync()=>{// Do your work herereturn{success: true};},// Timeout handler - runs when timeout is imminentasync()=>{// Handle timeout gracefullyreturn{timedOut: true};},// User cleanup handler - always runs after success or timeoutasync()=>{// Clean up resources here (database connections, etc.)});try{constresult=awaitwrapper(/* ... */);returnresult;}catch(error){// Check if it's a timeout errorif(error.isLambdaTimeout){// Handle timeout-specific error case}// Handle other errors}Directory Structure:
your-project/ ├── netlify.toml └── netlify/ └── functions/ └── your-function.jsRequired Dependencies:
- For JavaScript:
npm install @hopdrive/lambda-timeout-wrapper
- For TypeScript:
npm install @hopdrive/lambda-timeout-wrapper npm install --save-dev typescript @netlify/functions @types/node
- For JavaScript:
Running Locally:
npm install -g netlify-cli netlify dev
Testing: Access your function at:
http://localhost:8888/.netlify/functions/your-function
To test timeout behavior:
Increase task duration:
- Modify the setTimeout duration in the examples to exceed the timeout limit
Decrease safety margin:
- Set a smaller safetyMarginMs value to test different cleanup timing
Observe graceful shutdown:
- Watch how resources are properly cleaned up when timeout occurs
MIT