Function
Source:
src/AWS/Lambda/Function.ts
An AWS Lambda host resource that combines code bundling, IAM role provisioning, and runtime binding collection.
Function is the canonical runtime host for AWS. Alchemy automatically
bundles your TypeScript entry module with Rolldown, creates an IAM
execution role, and uploads the zip artifact. On subsequent deploys, the
function is only updated when the bundle hash changes.
There are two ways to define a Lambda Function:
- Async — plain handler export, no Effect runtime in the bundle.
- Effect — Effect implementation with typed bindings and event sources.
See the {@link https://alchemy.run/guides/async-lambda | Async Lambda Guide} for plain handler patterns, or the {@link https://alchemy.run/guides/lambda | Effect Lambda Guide} for the full Effect-based approach with bindings, event sources, and sinks.
Async Functions
Section titled “Async Functions”Point main at a file that exports a standard Lambda handler. No
Effect runtime is included in the bundle. Useful when migrating
existing Lambda functions or when you don’t need Effect.
Defining an async Lambda in your stack
import * as AWS from "alchemy/AWS";
const func = yield* AWS.Lambda.Function("ApiFunction", { main: "./src/handler.ts", url: true,});Writing the async handler
export const handler = async (event: any) => { return { statusCode: 200, body: JSON.stringify({ message: "Hello from Lambda!" }), };};Effect Functions
Section titled “Effect Functions”Pass the Effect implementation as the third argument. Bindings attach IAM permissions and environment variables at deploy time, while the runtime execution context collects listeners and exports.
export default class ApiFunction extends AWS.Lambda.Function<ApiFunction>()( "ApiFunction", { main: import.meta.filename, url: true }, Effect.gen(function* () { // init: bind resources const getItem = yield* DynamoDB.GetItem.bind(table);
return { // runtime: use them fetch: Effect.gen(function* () { const request = yield* HttpServerRequest; const url = new URL(request.url); const id = url.searchParams.get("id"); const result = yield* getItem({ Key: { pk: { S: id! } } }); return yield* HttpServerResponse.json(result.Item); }), }; }),) {}Configuration
Section titled “Configuration”Function with URL
const func = yield* AWS.Lambda.Function("ApiFunction", { main: "./src/handler.ts", url: true,});Function in a VPC
const func = yield* AWS.Lambda.Function("VpcFunction", { main: "./src/handler.ts", vpc: { subnetIds: ["subnet-abc123", "subnet-def456"], securityGroupIds: ["sg-xyz789"], },});S3 Bindings
Section titled “S3 Bindings”Bind S3 operations in the init phase to give the function IAM permissions and inject the bucket name as an environment variable.
// initconst getObject = yield* S3.GetObject.bind(bucket);const putObject = yield* S3.PutObject.bind(bucket);
return { fetch: Effect.gen(function* () { // runtime yield* putObject({ Key: "hello.txt", Body: "Hello!" }); const obj = yield* getObject({ Key: "hello.txt" }); return HttpServerResponse.text("OK"); }),};DynamoDB Bindings
Section titled “DynamoDB Bindings”Bind DynamoDB operations in the init phase to grant table-scoped IAM permissions.
// initconst getItem = yield* DynamoDB.GetItem.bind(table);const putItem = yield* DynamoDB.PutItem.bind(table);
return { fetch: Effect.gen(function* () { // runtime yield* putItem({ Item: { pk: { S: "user#1" }, name: { S: "Alice" } } }); const result = yield* getItem({ Key: { pk: { S: "user#1" } } }); return yield* HttpServerResponse.json(result.Item); }),};SQS Bindings
Section titled “SQS Bindings”Bind SQS operations in the init phase to send messages to a queue.
// initconst sendMessage = yield* SQS.SendMessage.bind(queue);
return { fetch: Effect.gen(function* () { // runtime yield* sendMessage({ MessageBody: JSON.stringify({ orderId: "123" }), }); return HttpServerResponse.text("Queued"); }),};SNS Bindings
Section titled “SNS Bindings”Bind SNS operations in the init phase to publish messages to a topic.
// initconst publish = yield* SNS.Publish.bind(topic);
return { fetch: Effect.gen(function* () { // runtime yield* publish({ Message: JSON.stringify({ event: "order.created" }), Subject: "OrderCreated", }); return HttpServerResponse.text("Published"); }),};Kinesis Bindings
Section titled “Kinesis Bindings”Bind Kinesis operations in the init phase to put records into a stream.
// initconst putRecord = yield* Kinesis.PutRecord.bind(stream);
return { fetch: Effect.gen(function* () { // runtime yield* putRecord({ PartitionKey: "order-123", Data: new TextEncoder().encode(JSON.stringify({ orderId: "123" })), }); return HttpServerResponse.text("Sent"); }),};Event Sources
Section titled “Event Sources”Lambda functions can be triggered by event sources like SQS queues, DynamoDB streams, S3 notifications, SNS topics, and Kinesis streams.
Process SQS messages
yield* SQS.messages(queue).process( Effect.fn(function* (message) { yield* Effect.log(`Received: ${message.body}`); }),);Process DynamoDB stream changes
yield* DynamoDB.streams(table, { StreamViewType: "NEW_AND_OLD_IMAGES",}).process( Effect.fn(function* (record) { yield* Effect.log(`Change: ${record.eventName}`); }),);Process S3 notifications
yield* S3.notifications(bucket, { events: ["s3:ObjectCreated:*"],}).subscribe((stream) => stream.pipe( Stream.runForEach((event) => Effect.log(`New object: ${event.key}`), ), ),);