AWS Lambda
BoxLang Runtime for AWS Lambda! Serverless for the win!

What is AWS Lambda?

AWS Lambda is a serverless computing service provided by Amazon Web Services (AWS) that lets you run code without provisioning or managing servers. It automatically scales applications by running code in response to events and allocates compute resources as needed, allowing developers to focus on writing code rather than managing infrastructure (https://docs.aws.amazon.com/lambda/).
The BoxLang AWS Runtime allows you to code in BoxLang and create Lambda functions in this ecosystem. We provide you a nice template so you can work with serverless: https://github.com/ortus-boxlang/bx-aws-lambda-template. This template will give you a turnkey application with features like:
Unit and Integration Testing
Java dependency management via Maven
BoxLang dependency management
Automatic shading and packaging
Class compilation caching for improved performance
Connection pooling for database operations
Configuration management with environment overrides
SAM CLI integration for local testing
GitHub actions to: test, build and release automatically to AWS
Performance monitoring and debugging capabilities
BoxLang Lambda Handler

Our BoxLang AWS Handler acts as a front controller to all incoming Lambda executions. It provides you with:
Automatic request management to an
event
structureAutomatic logging and tracing
Execution of your Lambda classes by convention
Automatic error management and exception handling
Automatic response management and serialization
Life-Cycle Events via our
Application.bx
NEW: Class compilation caching for improved performance
NEW: Connection pooling for database operations
NEW: Performance metrics and debugging capabilities
NEW: Custom method resolution via headers
The BoxLang AWS runtime provides a pre-built Java handler for Lambda already configured to accept JSON in as a BoxLang Struct and then output either by returning a simple or complex object or using our response
convention struct. Our runtime will automatically convert your results to JSON.
The default handler you configure your lambda with is:
ortus.boxlang.runtime.aws.LambdaRunner::handleRequest
The handler will look for a Lambda.bx
in your package and execute the run()
method by convention.
class {
function run( event, context, response ){
}
}
Environment Variables
The following are all the environment variables the Lambda runtime can read and detect. If they are set by you or the AWS Lambda runner, then it will use those values to alter operations. This doesn't mean that they will exist at runtime, it just means you can set them to alter behavior.
BOXLANG_LAMBDA_CLASS
Absolute path to the lambda to execute. The default path is: /var/task/Lambda.bx
Which is your lambda deployed within your zip file.
BOXLANG_LAMBDA_DEBUGMODE
Turn runtime debug mode on or off. When enabled, provides performance metrics and detailed logging.
BOXLANG_LAMBDA_CONFIG
Absolute path to a custom boxlang.json
configuration for the runtime. Defaults to /var/task/boxlang.json
BOXLANG_LAMBDA_CONNECTION_POOL_SIZE
NEW: Configure the connection pool size for database operations. Default is 2 connections.
LAMBDA_TASK_ROOT
Lambda deployment root directory. Defaults to /var/task
You can also leverage ANY environment variable to configure the BoxLang runtime using our runtime environment conventions.
Performance Environment Variables
The runtime now includes several performance optimizations that can be controlled via environment variables:
Class Compilation Caching: Lambda classes are automatically cached to avoid recompilation
Connection Pooling: Database connections are pooled and reused across invocations
Performance Metrics: Debug mode provides timing and memory usage information
BoxLang AWS Template
The BoxLang default template for AWS lambda can be found here: https://github.com/ortus-boxlang/bx-aws-lambda-template. The structure of the project is the following:
/.vscode - Some useful vscode tasks and settings
/gradle - The gradle runtime, keep in source control
/src
+ main
+ bx
+ Application.bx (Your life-cycle class)
+ Lambda.bx (Your BoxLang Lambda function)
+ resources
+ boxlang.json (A custom BoxLang configuration file)
+ boxlang_modules (Where you will install BoxLang modules)
+ test
+ java
+ com
+ myproject
+ LambdaRunnerTest.java (An integration test for your Lambda)
+ TestContext.java (A testing context for lambda)
+ TestLogger.java (A testing logger for lambda)
/workbench - AWS lambda utilities and scripts
+ config.env - Default configuration settings
+ config.local.env - Local configuration overrides (create from config.env)
+ sampleEvents/ - Sample Lambda event payloads for testing
+ template.yml - SAM template for local testing and deployment
+ *.sh - Deployment and management scripts
/box.json - Your project's dependency descriptor for CommandBox
/build.gradle - The gradle build configuration
/gradle.properties - Where you store your version and metadata
/gradlew - The gradle shell executor, keep in source control
/gradlew.bat - The gradle shell executor, keep in source control
/settings.gradle - The project settings
The BoxLang AWS Lambda runtime will look for a Lambda.bx
in your package by convention and execute the run()
method for you.
Key Template Features
Configuration Management: Hierarchical configuration system using
config.env
→config.local.env
→ environment variablesSAM Integration: Full AWS SAM support for local testing and deployment
Maven Dependency Resolution: Automatic dependency management via Maven
Performance Optimizations: Class caching, connection pooling, and performance monitoring built-in
Local Testing: Multiple Gradle tasks for local development and testing
AI Development Support: Comprehensive GitHub Copilot instructions for enhanced development experience
Building and Testing
# Create local configuration (customize as needed)
cp workbench/config.env workbench/config.local.env
# Run the tests
./gradlew test
# Build the project, create the lambda zip
# The location is /build/distributions/{project}-{version}.zip
./gradlew build
# Local testing with SAM
./gradlew runLocal # Basic Lambda execution
./gradlew runLocalApi # API Gateway event
./gradlew runLocalLegacy # Legacy API Gateway event
# Start local HTTP server for API testing
./gradlew startSamServerBackground
# Clean build artifacts
./gradlew clean
Lambda.bx
The Lambda function is a BoxLang class with a single function called run()
.
/**
* My BoxLang Lambda
*/
class{
function run( event, context, response ){
response.body = {
"error": false,
"messages": [],
"data": "====> Incoming event " & event.toString()
};
response.statusCode = 200;
}
}
Arguments
It accepts three arguments:
event
Struct
All the incoming JSON as a BoxLang struct
context
com.amazonaws.services.lambda.runtime.Context
The AWS context object. You can find much more information here.
response
Struct
A BoxLang struct convention for a response.
You can find more information about the AWS Context object here: https://docs.aws.amazon.com/lambda/latest/dg/java-context.html
Event
The event
structure is a snapshot of the input to your lambda. We deserialize the incoming JSON for you and give you a nice struct.
Context
This is an Amazon Java class that provides extensive information about the request. For more information, check out the API in the Amazon Docs (https://docs.aws.amazon.com/lambda/latest/dg/java-context.html)
Context methods
getRemainingTimeInMillis()
– Returns the number of milliseconds left before the execution times out.getFunctionName()
– Returns the name of the Lambda function.getFunctionVersion()
– Returns the version of the function.getInvokedFunctionArn()
– Returns the Amazon Resource Name (ARN) that's used to invoke the function. Indicates if the invoker specified a version number or alias.getMemoryLimitInMB()
– Returns the amount of memory that's allocated for the function.getAwsRequestId()
– Returns the identifier of the invocation request.getLogGroupName()
– Returns the log group for the function.getLogStreamName()
– Returns the log stream for the function instance.getIdentity()
– (mobile apps) Returns information about the Amazon Cognito identity that authorized the request.getClientContext()
– (mobile apps) Returns the client context that's provided to Lambda by the client application.getLogger()
– Returns the logger object for the function.
Response
The response
argument is our convention to help you build a nice return structure. However, it is completely optional. You can easily return a simple or complex object from your lambda, and we will convert it to JSON.
response : {
statusCode : 200,
headers : {
content-type : "application/json",
access-control-allow-origin : "*",
},
body : YourLambda.run() results
}
/**
* My BoxLang Lambda Simple Return
*/
class{
function run( event, context, response ){
return "Hello World!"
}
}
/**
* My BoxLang Lambda Complex Return
*/
class{
function run( event, context, response ){
return {
age : 1,
when : now(),
data : [ 12,3234,23423 ]
};
}
}
Now you can go ahead and build your function. You can use TestBox to unit test your Lambda.bx
or we even include a src/test
folder in Java, that simulates the full life-cycle of the runtime. Just run gradle test
or use VSCode BoxLang IDE to run the tests. Now we go to production!
Performance Enhancements
The BoxLang AWS Lambda runtime includes several performance optimizations:
Class Compilation Caching
Lambda classes are automatically cached between invocations to avoid recompilation overhead:
// Your Lambda classes are compiled once and cached
class {
function run( event, context, response ) {
// This class is cached after first compilation
return processEvent( event );
}
}
Connection Pooling
Database connections are pooled and reused across Lambda invocations:
// Configure connection pool size via environment variable
// BOXLANG_LAMBDA_CONNECTION_POOL_SIZE=5
function run( event, context, response ) {
// Connections are automatically pooled and reused
var results = queryExecute( "SELECT * FROM users" );
return results;
}
Performance Monitoring
Enable debug mode to get performance metrics:
# Set environment variable for performance monitoring
BOXLANG_LAMBDA_DEBUGMODE=true
This provides:
Class compilation timing
Memory usage metrics
Request processing duration
Connection pool statistics
Convention-Based URI Routing
NEW in v1.5.0: The runtime now supports automatic routing using PascalCase conventions, allowing you to build multi-class Lambda functions with BoxLang easily following our conventions.
When your Lambda is exposed as a URL, the runtime can automatically route to different BoxLang classes based on the URI path:
// URL: /products -> Products.bx
// URL: /home-savings -> HomeSavings.bx
// URL: /user-profile -> UserProfile.bx
Example Multi-Class Structure
/src/main/bx/
├── Lambda.bx # Default handler (fallback)
├── Products.bx # Handles /products
├── HomeSavings.bx # Handles /home-savings
└── UserProfile.bx # Handles /user-profile
Each class should implement a handler
function (or run
as fallback):
// Products.bx
class {
function handler( event, context ) {
return {
"statusCode" : 200,
"body" : serializeJSON( getProductCatalog() )
};
}
function getProductCatalog() {
return [
{ "id": 1, "name": "BoxLang Runtime" },
{ "id": 2, "name": "CommandBox" }
];
}
}
URI to Class Name Conversion
The routing follows these conventions:
/products
→Products.bx
/home-savings
→HomeSavings.bx
/user-profile
→UserProfile.bx
/api/users
→Api/Users.bx
Hyphens are converted to PascalCase, and forward slashes create subdirectory structure.
Multiple Functions Header
The runtime also allows you to create other functions inside of your Lambda that can be targeted if your AWS Lambda is exposed as an URL. You will be able to target different functions in your Lambda.bx
by using the following header when executing your lambda:
x-bx-function=methodName
This makes it incredibly flexible where you can respond to that incoming header in a different function than the one by convention.
Lambda Modules
You can use any BoxLang module with the BoxLang Lambda runtime by installing them to the src/resources/boxlang_modules
folder. All modules placed there during the build process will be packaged into your lambda deployment.
# Using CommandBox to install modules directly
box install id=bx-module directory=src/resources/boxlang_modules
# Or add them to box.json and install
cd src/resources && box install
Local Development & Testing
The template provides comprehensive local development and testing capabilities:
SAM CLI Integration
# Test your function locally with different event types
./gradlew runLocal # Basic Lambda execution
./gradlew runLocalApi # API Gateway event simulation
./gradlew runLocalLegacy # Legacy API Gateway event
# Start a local HTTP server for API testing
./gradlew startSamServerBackground
./gradlew stopSamServer
Sample Events
The template includes sample event files in workbench/sampleEvents/
:
api.json
- API Gateway eventevent.json
- Basic Lambda eventevent-live.json
- Production-like event for testing
Testing Framework
The Java integration tests simulate the complete Lambda lifecycle:
// Example from LambdaRunnerTest.java
@Test
public void testLambdaExecution() {
LambdaRunner runner = new LambdaRunner();
String result = runner.handleRequest(sampleEvent, testContext);
assertThat(result).contains("success");
}
Deploy to AWS
You can deploy your lambda using the provided deployment scripts or GitHub Actions. The template includes a comprehensive deployment system with configuration management.
Configuration-Based Deployment
The template uses a hierarchical configuration system:
Base Configuration:
workbench/config.env
- Default settingsLocal Overrides:
workbench/config.local.env
- Your custom settingsEnvironment Variables: Final overrides
# Create your local configuration
cp workbench/config.env workbench/config.local.env
# Edit your settings
vim workbench/config.local.env
Example configuration:
# AWS Settings
AWS_LAMBDA_BUCKET=my-lambda-deployments
STACK_NAME=my-boxlang-app
FUNCTION_NAME=my-function
LAMBDA_MEMORY=512
LAMBDA_TIMEOUT=30
ENVIRONMENT=development
Deployment Scripts
The template provides several deployment scripts:
# Check AWS credentials and configuration
./workbench/0-check-aws.sh
# Create S3 bucket for deployments
./workbench/1-create-bucket.sh
# Deploy your Lambda function
./workbench/2-deploy.sh
# Invoke your deployed function
./workbench/3-invoke.sh
# Clean up resources
./workbench/4-cleanup.sh
GitHub Actions Deployment
Below is the enhanced GitHub Action that uses the new configuration system:
- name: Deploy BoxLang Lambda
run: |
./workbench/2-deploy.sh
env:
AWS_REGION: ${{ secrets.AWS_REGION }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_PUBLISHER_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_PUBLISHER_KEY }}
AWS_LAMBDA_BUCKET: ${{ secrets.AWS_LAMBDA_BUCKET }}
ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }}
SAM Template Integration
The template includes a parameterized SAM template (workbench/template.yml
) that:
Creates the Lambda function with proper configuration
Sets up IAM roles and permissions
Configures environment variables
Provides function outputs (name, ARN) for integration
Required Configuration
The automated deployment requires storing your credentials in your repository's secrets or environment variables:
AWS_REGION
- The region to deploy toAWS_PUBLISHER_KEY_ID
- The AWS access keyAWS_SECRET_PUBLISHER_KEY
- The AWS secret keyAWS_LAMBDA_BUCKET
- S3 bucket for deployment artifacts
Environment-Based Deployments
The build process supports multiple environments based on Git branches:
Development Branch →
staging
environmentMain/Master Branch →
production
environment
The template automatically creates appropriately named functions:
{functionName}-staging
- For development/staging{functionName}-production
- For production releases
The {functionName}
comes from your FUNCTION_NAME
configuration setting.

Log in to the Lambda Console and click on Create function
button.

Now let's add the basic information about our deployment:
Add a function name:
{projectName}-staging or production
Choose
Java 21
as your runtimeChoose
x86_64
as your architecture
TIP: If you choose ARM processors, you can save some money.

Now, let's upload our test code. You can choose a zip/jar or s3 location. We will do a simple zip from our template:



Now important, let's choose the AWS Lambda Runtime Handler in the Edit runtime settings

And make sure you use the following handler address: ortus.boxlang.runtime.aws.LambdaRunner::handleRequest
This is inside the runtime to execute our Lambda.bx
function.
Please note that the RAM you chose for your lambda determines your CPU as well. So make sure you increase the RAM accordingly. We have seen great results with 4GB+.
Testing in AWS
Now click on the Test
tab and an event name MyTestEvent
. You can also add anything you like in the Event JSON
to test the input of your lambda. Then click on Test
and watch it do its magic. Now go have some good fun!

Runtime Source Code
The AWS Runtime source code can be found here: https://github.com/ortus-boxlang/boxlang-aws-lambda
Latest Runtime Features
The BoxLang AWS Lambda runtime includes several recent enhancements:
Maven Dependency Management: Automatic resolution of runtime dependencies
Class Compilation Caching: Improved cold start performance through class caching
Connection Pooling: Database connection pooling for better performance
Performance Metrics: Detailed performance monitoring in debug mode
Enhanced Error Handling: Better error messages and stack traces
Configuration Flexibility: Hierarchical configuration system
SAM Integration: Full AWS SAM support for local development
Performance Best Practices
For optimal performance with the BoxLang AWS Lambda runtime:
Enable Class Caching: Use
trustedCache=true
in yourboxlang.json
for productionConfigure Connection Pooling: Set
BOXLANG_LAMBDA_CONNECTION_POOL_SIZE
for database workloadsMemory Allocation: Allocate sufficient memory (2GB+ recommended) for better CPU performance
Static Initialization: Use static blocks for expensive one-time setup
Early Returns: Validate input early and return immediately on errors
We welcome any pull requests, testing, documentation contributions, and feedback.
Last updated
Was this helpful?