# Boxlang Runtime AWS Lambda

> Use this skill when building, deploying, or debugging BoxLang applications on AWS Lambda — including Lambda.bx structure, handler conventions, environment variables, SAM CLI testing, performance optimization, connection pooling, multi-function routing, and the boxlang-starter-aws-lambda project.

- Skill: `ortus-boxlang/boxlang-runtime-aws-lambda` (Agent Skill)
- Install (CLI): `npx skillmds@latest add ortus-boxlang/boxlang-runtime-aws-lambda`
- Raw SKILL.md: https://api.skillmd.com/api/skills/ortus-boxlang/boxlang-runtime-aws-lambda/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: ortus-boxlang (https://skillmd.com/u/ortus-boxlang)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/ortus-boxlang/boxlang-runtime-aws-lambda

---


# BoxLang on AWS Lambda

## Overview

The BoxLang AWS Runtime provides a pre-built Java handler for serverless Lambda
functions. You write BoxLang classes; the runtime handles request/response
lifecycle, serialization, logging, and error management.

---

## Handler Configuration

Set this as your Lambda handler in AWS:

```
ortus.boxlang.runtime.aws.LambdaRunner::handleRequest
```

The runtime automatically:
- Deserializes the incoming JSON event into a BoxLang `Struct`
- Calls your `Lambda.bx` class `run()` method
- Serializes the return value back to JSON
- Manages error handling and logging

---

## Lambda.bx Convention

The runtime looks for `Lambda.bx` in your deployment package root and calls `run()`:

```boxlang
class {

    /**
     * The main Lambda handler function.
     *
     * @param event    The incoming event struct (deserialized from JSON)
     * @param context  The AWS Lambda context object (Java LambdaContext)
     * @param response A pre-built response struct you can populate:
     *                 { statusCode: 200, body: "", headers: {} }
     */
    function run( event, context, response ){
        // Simple return value — auto-serialized to JSON
        return {
            statusCode: 200,
            body: {
                message: "Hello from BoxLang Lambda!",
                input:   event
            }
        }
    }

}
```

### Response Convention

You can either `return` a value or populate the `response` struct:

```boxlang
function run( event, context, response ){
    // Option 1: return a value (auto-serialized)
    return { statusCode: 200, body: "OK" }

    // Option 2: populate response struct
    response.statusCode = 200
    response.body       = jsonSerialize({ message: "Done" })
    response.headers    = { "Content-Type": "application/json" }
}
```

---

## Application Lifecycle (`Application.bx`)

Place `Application.bx` in your deployment package for lifecycle hooks:

```boxlang
class {
    this.name = "MyLambda"

    // Called once on cold start — initialize resources here
    boolean function onApplicationStart(){
        application.db = createObject("component","DataService").init()
        return true
    }

    // Called on every request before run()
    boolean function onRequestStart( required string targetPage ){
        return true
    }
}
```

---

## Project Structure (Starter Template)

Use the official starter: `https://github.com/ortus-boxlang/boxlang-starter-aws-lambda`

```
/src
  /main
    /bx
      Application.bx     -- Lifecycle class
      Lambda.bx          -- Your Lambda handler
    /resources
      boxlang.json        -- BoxLang runtime config
      boxlang_modules/    -- Installed BoxLang modules
  /test
    /java
      /com/myproject
        LambdaRunnerTest.java   -- Integration tests
        TestContext.java
        TestLogger.java
/workbench
  config.env              -- Default env config
  config.local.env        -- Local overrides (gitignored)
  sampleEvents/           -- Test event payloads (.json files)
  template.yml            -- SAM template for local testing + deploy
  *.sh                    -- Deploy/management scripts
/box.json                 -- BoxLang module dependencies
/build.gradle             -- Build config (shaded JAR)
```

---

## Environment Variables

| Variable | Description |
|----------|-----------|
| `BOXLANG_LAMBDA_CLASS` | Absolute path to Lambda class. Default: `/var/task/Lambda.bx` |
| `BOXLANG_LAMBDA_DEBUGMODE` | Enable debug mode + performance metrics (`true`/`false`) |
| `BOXLANG_LAMBDA_CONFIG` | Path to custom `boxlang.json`. Default: `/var/task/boxlang.json` |
| `BOXLANG_LAMBDA_CONNECTION_POOL_SIZE` | Database connection pool size. Default: `2` |
| `LAMBDA_TASK_ROOT` | Lambda deployment root. Default: `/var/task` |

Any `BOXLANG_*` env variable also maps to `boxlang.json` config overrides.

---

## Performance Enhancements

### Class Compilation Caching

Lambda classes are compiled and cached on the first (cold start) invocation.
Warm invocations reuse the cached bytecode — no re-compilation overhead.

Disable caching in development (debug mode):
```bash
BOXLANG_LAMBDA_DEBUGMODE=true
```

### Connection Pooling

Database connections are pooled and reused across warm invocations:

```bash
BOXLANG_LAMBDA_CONNECTION_POOL_SIZE=5
```

### Cold Start Optimization Tips

1. Use `Application.bx` `onApplicationStart()` to initialize shared resources
2. Minimize modules loaded at startup — only install what you use
3. Use the `asm` compiler (default) for better startup performance
4. Set `storeClassFilesOnDisk: true` in `boxlang.json`

---

## Multiple Lambda Functions (URI Routing)

Use the `x-bx-function` header to call a specific method on the class:

```bash
# Calls Lambda.bx run() method (default)
curl https://api.example.com/function

# Calls Lambda.bx processOrder() method
curl -H "x-bx-function: processOrder" https://api.example.com/function
```

In `Lambda.bx`:

```boxlang
class {

    function run( event, context, response ){
        return { message: "Default handler" }
    }

    function processOrder( event, context, response ){
        return orderService.process( event )
    }

    function getUsers( event, context, response ){
        return userService.list( event.limit ?: 20 )
    }

}
```

---

## Local Development with SAM CLI

```bash
# Install AWS SAM CLI
# https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html

# Start local Lambda API
sam local start-api --template workbench/template.yml

# Invoke a specific function locally
sam local invoke BoxLangFunction --event workbench/sampleEvents/test-event.json

# Build the shaded JAR (includes all dependencies)
./gradlew shadowJar
```

---

## Deploying to AWS

```bash
# Configure AWS credentials first
aws configure

# Build, package, and deploy via SAM
./gradlew shadowJar
sam deploy --guided --template workbench/template.yml

# Or use the included deploy scripts
chmod +x workbench/*.sh
./workbench/deploy.sh
```

---

## BoxLang Modules in Lambda

Install modules to the `src/main/resources/boxlang_modules/` directory using CommandBox:

```bash
# Install a module to the Lambda module directory
box install bx-mail --boxlang-home=src/main/resources

# The module will be zipped with the deployment package
```

---

## Production Checklist

- [ ] `Application.bx` initializes shared resources (connections, config) in `onApplicationStart()`
- [ ] `BOXLANG_LAMBDA_DEBUGMODE=false` in production
- [ ] Connection pool size tuned: `BOXLANG_LAMBDA_CONNECTION_POOL_SIZE`
- [ ] Secrets via AWS SSM Parameter Store or Secrets Manager, injected as env vars
- [ ] `boxlang.json` present in deployment package root
- [ ] Lambda timeout set generously for cold starts (30s+ recommended)
- [ ] Memory allocation ≥ 512MB (1024MB+ for better performance)
- [ ] Integration tests passing via `./gradlew test`

