> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fjall.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Lambda Function

> Create serverless AWS Lambda functions with IAM policies, event sources, and Function URLs using Fjall CDK constructs.

## Overview

The Lambda Function resource provides serverless compute with automatic scaling, built-in high availability, and pay-per-use pricing. It covers both standard functions and singleton functions for AWS Custom Resources.

## Resource Classes

```typescript theme={null}
import {
  LambdaFunction,
  SingletonFunction,
} from "@fjall/components-infrastructure/lib/resources/aws/compute/lambda";
```

## Basic Usage

### Standard Function

```typescript theme={null}
const lambda = new LambdaFunction(this, "MyFunction", {
  code: Code.fromAsset("lambda"),
  handler: "index.handler",
  runtime: Runtime.NODEJS_20_X,
  inlinePolicy: [
    new PolicyStatement({
      actions: ["s3:GetObject"],
      resources: ["arn:aws:s3:::my-bucket/*"],
    }),
  ],
});
```

### Singleton Function

```typescript theme={null}
const singleton = new SingletonFunction(this, "CustomResource", {
  code: Code.fromInline("exports.handler = async () => ({ statusCode: 200 })"),
  handler: "index.handler",
  runtime: Runtime.NODEJS_20_X,
  uuid: "unique-function-id",
  inlinePolicy: [],
});
```

## Configuration Options

### Core Properties

| Property       | Type                | Description           | Default  |
| -------------- | ------------------- | --------------------- | -------- |
| `code`         | `Code`              | Function code source  | Required |
| `handler`      | `string`            | Handler function      | Required |
| `runtime`      | `Runtime`           | Lambda runtime        | Required |
| `inlinePolicy` | `PolicyStatement[]` | IAM policy statements | Required |

### Function Configuration

| Property               | Type            | Description                 | Default        |
| ---------------------- | --------------- | --------------------------- | -------------- |
| `timeout`              | `number`        | Timeout in seconds          | `300`          |
| `memorySize`           | `number`        | Memory in MB (128-10240)    | `128`          |
| `ephemeralStorageSize` | `number`        | Ephemeral storage in MiB    | -              |
| `architecture`         | `Architecture`  | CPU architecture            | `x86_64`       |
| `lambdaDescription`    | `string`        | Function description        | `${id} Lambda` |
| `roleDescription`      | `string`        | IAM role description        | -              |
| `environment`          | `KeyValue`      | Environment variables       | `{}`           |
| `functionName`         | `string`        | Explicit function name      | Auto-generated |
| `vpc`                  | `IVpc`          | Place the function in a VPC | -              |
| `logGroupRetention`    | `RetentionDays` | Log retention period        | `ONE_WEEK`     |

### Function URL Configuration

| Property                | Type                     | Description                                      | Default   |
| ----------------------- | ------------------------ | ------------------------------------------------ | --------- |
| `enableFunctionUrl`     | `boolean`                | Enable HTTP endpoint                             | `false`   |
| `functionUrlAuthType`   | `FunctionUrlAuthType`    | Auth type                                        | `AWS_IAM` |
| `functionUrlCors`       | `FunctionUrlCorsOptions` | CORS configuration                               | -         |
| `functionUrlInvokeMode` | `InvokeMode`             | Invoke mode (use RESPONSE\_STREAM for streaming) | -         |

### Secrets Configuration

| Property         | Type                           | Description                      | Default                            |
| ---------------- | ------------------------------ | -------------------------------- | ---------------------------------- |
| `secrets`        | `string[]`                     | SSM Parameter Store secret names | -                                  |
| `ssmSecretsPath` | `string`                       | Base path for SSM secrets        | `/<appName>/lambda/<functionName>` |
| `secretsImport`  | `Record<string, SecretImport>` | Secrets Manager imports          | -                                  |

## Code Sources

### From Local Directory

```typescript theme={null}
const lambda = new LambdaFunction(this, "LocalCode", {
  code: Code.fromAsset("src/lambda"),
  handler: "app.handler",
  runtime: Runtime.NODEJS_20_X,
  inlinePolicy: [],
});
```

### From Inline Code

```typescript theme={null}
const lambda = new LambdaFunction(this, "InlineCode", {
  code: Code.fromInline(`
    exports.handler = async (event) => {
      console.log("Event:", JSON.stringify(event));
      return {
        statusCode: 200,
        body: JSON.stringify({ message: "Hello World" })
      };
    };
  `),
  handler: "index.handler",
  runtime: Runtime.NODEJS_20_X,
  inlinePolicy: [],
});
```

### From S3 Bucket

```typescript theme={null}
const lambda = new LambdaFunction(this, "S3Code", {
  code: Code.fromBucket(
    s3.Bucket.fromBucketName(this, "CodeBucket", "my-code-bucket"),
    "lambda-code.zip",
  ),
  handler: "main.handler",
  runtime: Runtime.PYTHON_3_11,
  inlinePolicy: [],
});
```

### From Docker Image

```typescript theme={null}
const lambda = new LambdaFunction(this, "ContainerFunction", {
  code: Code.fromEcrImage(repository, {
    tag: "latest",
  }),
  handler: Handler.FROM_IMAGE,
  runtime: Runtime.FROM_IMAGE,
  inlinePolicy: [],
});
```

## IAM Policies

The `inlinePolicy` property accepts an array of `PolicyStatement` objects. Each statement is added directly to the Lambda function's execution role.

### S3 Access

```typescript theme={null}
const lambda = new LambdaFunction(this, "S3Function", {
  code: Code.fromAsset("lambda"),
  handler: "index.handler",
  runtime: Runtime.NODEJS_20_X,
  inlinePolicy: [
    new PolicyStatement({
      actions: ["s3:GetObject", "s3:PutObject"],
      resources: [`${bucket.bucketArn}/*`],
    }),
  ],
});
```

### DynamoDB Access

```typescript theme={null}
const lambda = new LambdaFunction(this, "DynamoFunction", {
  code: Code.fromAsset("lambda"),
  handler: "index.handler",
  runtime: Runtime.NODEJS_20_X,
  inlinePolicy: [
    new PolicyStatement({
      actions: [
        "dynamodb:GetItem",
        "dynamodb:PutItem",
        "dynamodb:Query",
        "dynamodb:Scan",
      ],
      resources: [table.tableArn],
    }),
  ],
});
```

### Multiple Policy Statements

```typescript theme={null}
const lambda = new LambdaFunction(this, "MultiPolicyFunction", {
  code: Code.fromAsset("lambda"),
  handler: "index.handler",
  runtime: Runtime.NODEJS_20_X,
  inlinePolicy: [
    new PolicyStatement({
      actions: ["s3:GetObject"],
      resources: [`${bucket.bucketArn}/*`],
    }),
    new PolicyStatement({
      actions: ["dynamodb:Query"],
      resources: [table.tableArn],
    }),
    new PolicyStatement({
      actions: ["sqs:SendMessage"],
      resources: [queue.queueArn],
    }),
  ],
});
```

## Environment Variables

```typescript theme={null}
const lambda = new LambdaFunction(this, "EnvFunction", {
  code: Code.fromAsset("lambda"),
  handler: "index.handler",
  runtime: Runtime.NODEJS_20_X,
  environment: {
    TABLE_NAME: dynamoTable.tableName,
    BUCKET_NAME: s3Bucket.bucketName,
    STAGE: "production",
  },
  inlinePolicy: [],
});
```

## Function URL Configuration

### Basic HTTP Endpoint

```typescript theme={null}
const lambda = new LambdaFunction(this, "HttpFunction", {
  code: Code.fromAsset("lambda"),
  handler: "index.handler",
  runtime: Runtime.NODEJS_20_X,
  enableFunctionUrl: true,
  functionUrlAuthType: FunctionUrlAuthType.NONE,
  inlinePolicy: [],
});
```

### With CORS

```typescript theme={null}
const lambda = new LambdaFunction(this, "CorsFunction", {
  code: Code.fromAsset("lambda"),
  handler: "index.handler",
  runtime: Runtime.NODEJS_20_X,
  enableFunctionUrl: true,
  functionUrlAuthType: FunctionUrlAuthType.AWS_IAM,
  functionUrlCors: {
    allowedOrigins: ["https://example.com"],
    allowedMethods: [HttpMethod.GET, HttpMethod.POST],
    allowedHeaders: ["Content-Type", "Authorization"],
    maxAge: Duration.hours(1),
  },
  inlinePolicy: [],
});
```

## Performance Configuration

### High Memory Function

```typescript theme={null}
const mlFunction = new LambdaFunction(this, "MLFunction", {
  code: Code.fromAsset("lambda"),
  handler: "predict.handler",
  runtime: Runtime.PYTHON_3_11,
  memorySize: 10240, // Maximum: 10240 MB
  timeout: 900, // 15 minutes
  inlinePolicy: [
    new PolicyStatement({
      actions: ["s3:GetObject"],
      resources: ["arn:aws:s3:::ml-models/*"],
    }),
  ],
});
```

### ARM Architecture

```typescript theme={null}
const lambda = new LambdaFunction(this, "ArmFunction", {
  code: Code.fromAsset("lambda"),
  handler: "index.handler",
  runtime: Runtime.NODEJS_20_X,
  architecture: Architecture.ARM_64,
  inlinePolicy: [],
});
```

## Event Sources

The `LambdaFunction` class provides three built-in event-source methods: `addSqsEventSource`, `addDynamoDbEventSource`, and `addS3EventSource`.

### SQS Trigger

```typescript theme={null}
const processor = new LambdaFunction(this, "QueueProcessor", {
  code: Code.fromAsset("lambda"),
  handler: "queue.handler",
  runtime: Runtime.NODEJS_20_X,
  inlinePolicy: [
    new PolicyStatement({
      actions: ["sqs:ReceiveMessage", "sqs:DeleteMessage"],
      resources: [queue.queueArn],
    }),
  ],
});

processor.addSqsEventSource(queue, {
  batchSize: 10,
  maxBatchingWindow: 30,
  reportBatchItemFailures: true,
});
```

### DynamoDB Stream Trigger

```typescript theme={null}
const streamProcessor = new LambdaFunction(this, "StreamProcessor", {
  code: Code.fromAsset("lambda"),
  handler: "stream.handler",
  runtime: Runtime.NODEJS_20_X,
  inlinePolicy: [
    new PolicyStatement({
      actions: [
        "dynamodb:GetRecords",
        "dynamodb:GetShardIterator",
        "dynamodb:DescribeStream",
        "dynamodb:ListStreams",
      ],
      resources: [`${table.tableArn}/stream/*`],
    }),
  ],
});

streamProcessor.addDynamoDbEventSource(table, {
  startingPosition: "LATEST",
  batchSize: 100,
  reportBatchItemFailures: true,
});
```

### S3 Trigger

```typescript theme={null}
const fileProcessor = new LambdaFunction(this, "FileProcessor", {
  code: Code.fromAsset("lambda"),
  handler: "processor.handler",
  runtime: Runtime.NODEJS_20_X,
  inlinePolicy: [
    new PolicyStatement({
      actions: ["s3:GetObject"],
      resources: [`${bucket.bucketArn}/*`],
    }),
  ],
});

fileProcessor.addS3EventSource(bucket, {
  events: ["OBJECT_CREATED"],
  filters: [{ prefix: "uploads/", suffix: ".csv" }],
});
```

## Scheduling

The construct has no built-in scheduling method or prop. To run a function on a schedule, attach a standalone EventBridge Rule that targets the function.

```typescript theme={null}
import { Rule, Schedule } from "aws-cdk-lib/aws-events";
import { LambdaFunction as LambdaTarget } from "aws-cdk-lib/aws-events-targets";

const cleanup = new LambdaFunction(this, "DailyCleanup", {
  code: Code.fromAsset("lambda"),
  handler: "cron.handler",
  runtime: Runtime.NODEJS_20_X,
  inlinePolicy: [],
});

new Rule(this, "DailyCleanupSchedule", {
  schedule: Schedule.rate(Duration.days(1)),
  targets: [new LambdaTarget(cleanup)],
  description: "Daily cleanup job",
});
```

## Singleton Function Pattern

### Custom Resource Handler

```typescript theme={null}
const customResourceHandler = new SingletonFunction(
  this,
  "CustomResourceHandler",
  {
    uuid: "f7d4f730-4ee1-11e8-9c2d-fa7ae01bbebc",
    code: Code.fromInline(`
    const response = require("cfn-response");
    exports.handler = async (event, context) => {
      try {
        if (event.RequestType === "Delete") {
          // Cleanup logic
        } else {
          // Create/Update logic
        }
        await response.send(event, context, response.SUCCESS);
      } catch (error) {
        await response.send(event, context, response.FAILED);
      }
    };
  `),
    handler: "index.handler",
    runtime: Runtime.NODEJS_20_X,
    lambdaDescription: "Custom resource handler",
    inlinePolicy: [
      new PolicyStatement({
        actions: ["s3:ListBuckets"],
        resources: ["*"],
      }),
    ],
  },
);
```

## Methods

### Get Function URL

```typescript theme={null}
const url = lambda.getFunctionUrl();
// Returns: string | undefined (only when enableFunctionUrl is true)
```

### Get Execution Role

```typescript theme={null}
const role = lambda.executionRole;
// Returns: IRole | undefined
```

### Get Function ARN

```typescript theme={null}
const functionArn = lambda.functionArn;
```

### Get Function Name

```typescript theme={null}
const functionName = lambda.functionName;
```

## Outputs

The Lambda Function creates these CloudFormation outputs:

* `${id}FunctionArn` - Function ARN
* `${id}FunctionUrl` - Function URL (when enabled)

## Complete Example

```typescript theme={null}
import { LambdaFunction } from "@fjall/components-infrastructure/lib/resources/aws/compute/lambda";
import { Code, Runtime } from "aws-cdk-lib/aws-lambda";
import { PolicyStatement } from "aws-cdk-lib/aws-iam";
import { FunctionUrlAuthType, HttpMethod } from "aws-cdk-lib/aws-lambda";

// Create Lambda function
const userApi = new LambdaFunction(this, "UserAPIFunction", {
  code: Code.fromAsset("src/lambda/user-api"),
  handler: "index.handler",
  runtime: Runtime.NODEJS_20_X,
  memorySize: 256,
  timeout: 30,
  environment: {
    TABLE_NAME: userTable.tableName,
    REGION: this.region,
  },
  enableFunctionUrl: true,
  functionUrlAuthType: FunctionUrlAuthType.AWS_IAM,
  functionUrlCors: {
    allowedOrigins: ["*"],
    allowedMethods: [
      HttpMethod.GET,
      HttpMethod.POST,
      HttpMethod.PUT,
      HttpMethod.DELETE,
    ],
    allowedHeaders: ["*"],
  },
  inlinePolicy: [
    new PolicyStatement({
      actions: [
        "dynamodb:GetItem",
        "dynamodb:PutItem",
        "dynamodb:UpdateItem",
        "dynamodb:DeleteItem",
        "dynamodb:Query",
      ],
      resources: [userTable.tableArn],
    }),
  ],
});
```

## Tagging

The construct takes no `tags` prop. Apply tags through the CDK `Tags` aspect after construction.

```typescript theme={null}
import { Tags } from "aws-cdk-lib";

Tags.of(userApi).add("Environment", "production");
Tags.of(userApi).add("Application", "user-service");
```

## Best Practices

1. **Keep functions small** and focused on single tasks
2. **Use layers** for shared dependencies
3. **Set appropriate timeouts** (not always the maximum)
4. **Use environment variables** for configuration
5. **Use PolicyStatement arrays** for least-privilege IAM
6. **Consider ARM (Graviton2)** for cost savings
7. **Use secrets** for sensitive values rather than environment variables

## Performance Tips

* Minimise package size to reduce cold starts
* Reuse connections outside handler function
* Use provisioned concurrency for predictable traffic
* Choose appropriate memory (CPU scales with memory)
* Maximum memory is 10240 MB (10 GB)

## Next Steps

<CardGroup cols={2}>
  <Card title="Compute Factory" icon="microchip" href="/patterns/compute-factory">
    Provision compute through the higher-level factory pattern.
  </Card>

  <Card title="IAM Role" icon="key" href="/resources/security/iam-role">
    Scope execution permissions for your function.
  </Card>

  <Card title="Messaging Factory" icon="envelope" href="/patterns/messaging-factory">
    Create SQS queues to use as Lambda event sources.
  </Card>

  <Card title="Load Balancer" icon="scale-balanced" href="/resources/networking/load-balancer">
    Front your function with an Application Load Balancer.
  </Card>
</CardGroup>
