AWS Lambda Functions
June 10, 2026 · View on GitHub
If you are using AWS as a provider, all functions inside the service are AWS Lambda functions.
Configuration
All of the Lambda functions in your serverless service can be found in serverless.yml under the functions property.
# serverless.yml
service: myService
provider:
name: aws
runtime: nodejs24.x
runtimeManagement: auto # optional, set how Lambda controls all functions runtime. AWS default is auto; this can either be 'auto' or 'onFunctionUpdate'. For 'manual', see example in hello function below (syntax for both is identical)
memorySize: 512 # optional, in MB, default is 1024
timeout: 10 # optional, in seconds, default is 6
versionFunctions: false # optional, default is true
tracing:
lambda: true # optional, enables tracing for all functions (can be true (true equals 'Active') 'Active' or 'PassThrough')
functions:
hello:
handler: handler.hello # required, handler set in AWS Lambda
name: ${sls:stage}-lambdaName # optional, Deployed Lambda name
description: Description of what the lambda function does # optional, Description to publish to AWS
runtime: python3.14 # optional overwrite, default is provider runtime
runtimeManagement:
mode: manual # syntax required for manual, mode property also supports 'auto' or 'onFunctionUpdate' (see provider.runtimeManagement)
arn: <aws runtime arn> # required when mode is manual
memorySize: 512 # optional, in MB, default is 1024
timeout: 10 # optional, in seconds, default is 6
provisionedConcurrency: 3 # optional, Count of provisioned lambda instances
reservedConcurrency: 5 # optional, reserved concurrency limit for this function. By default, AWS uses account concurrency limit
tracing: PassThrough # optional, overwrite, can be 'Active' or 'PassThrough'
If provider.runtime is omitted for AWS services, osls defaults to the latest supported Node.js Lambda runtime. Today that is nodejs24.x.
We still recommend explicitly setting the runtime you want to deploy, either at provider.runtime or per function, so your service does not change runtimes when that default advances.
For new services, prefer nodejs24.x, python3.14, java25, dotnet10, ruby4.0, and provided.al2023 for custom runtimes.
The handler property points to the file and module containing the code you want to run in your function.
// handler.js
module.exports.functionOne = async (event) => {};
You can add as many functions as you want within this property.
# serverless.yml
service: myService
provider:
name: aws
runtime: nodejs24.x
functions:
functionOne:
handler: handler.functionOne
description: optional description for your Lambda
functionTwo:
handler: handler.functionTwo
functionThree:
handler: handler.functionThree
Your functions can either inherit their settings from the provider property.
# serverless.yml
service: myService
provider:
name: aws
runtime: nodejs24.x
memorySize: 512 # will be inherited by all functions
functions:
functionOne:
handler: handler.functionOne
Or you can specify properties at the function level.
# serverless.yml
service: myService
provider:
name: aws
runtime: nodejs24.x
functions:
functionOne:
handler: handler.functionOne
memorySize: 512 # function specific
You can specify an array of functions, which is useful if you separate your functions in to different files:
# serverless.yml
---
functions:
- ${file(./foo-functions.yml)}
- ${file(./bar-functions.yml)}
# foo-functions.yml
getFoo:
handler: handler.foo
deleteFoo:
handler: handler.foo
Permissions
Every AWS Lambda function needs permission to interact with other AWS infrastructure resources within your account. These permissions are set via an AWS IAM Role. You can set permission policy statements within this role via the provider.iam.role.statements property.
# serverless.yml
service: myService
provider:
name: aws
runtime: nodejs24.x
iam:
role:
statements: # permissions for all of your functions can be set here
- Effect: Allow
Action: # Gives permission to DynamoDB tables in a specific region
- dynamodb:DescribeTable
- dynamodb:Query
- dynamodb:Scan
- dynamodb:GetItem
- dynamodb:PutItem
- dynamodb:UpdateItem
- dynamodb:DeleteItem
Resource: 'arn:aws:dynamodb:us-east-1:*:*'
functions:
functionOne:
handler: handler.functionOne
memorySize: 512
Another example:
# serverless.yml
service: myService
provider:
name: aws
iam:
role:
statements:
- Effect: 'Allow'
Action:
- 's3:ListBucket'
# You can put CloudFormation syntax in here. No one will judge you.
# Remember, this all gets translated to CloudFormation.
Resource: { 'Fn::Join': ['', ['arn:aws:s3:::', { 'Ref': 'ServerlessDeploymentBucket' }]] }
- Effect: 'Allow'
Action:
- 's3:PutObject'
Resource:
Fn::Join:
- ''
- - 'arn:aws:s3:::'
- 'Ref': 'ServerlessDeploymentBucket'
- '/*'
functions:
functionOne:
handler: handler.functionOne
memorySize: 512
You can also use an existing IAM role by adding your IAM Role ARN in the iam.role property. For example:
# serverless.yml
service: new-service
provider:
name: aws
iam:
role: arn:aws:iam::YourAccountNumber:role/YourIamRole
See the documentation about IAM for function level IAM roles.
Lambda Function URLs
A Lambda Function URL is a simple solution to create HTTP endpoints with AWS Lambda. Function URLs are ideal for getting started with AWS Lambda, or for single-function applications like webhooks or APIs built with web frameworks.
You can create a function URL via the url property in the function configuration in serverless.yml. By setting url to true, as shown below, the URL will be public without CORS configuration.
functions:
func:
handler: index.handler
url: true
Alternatively, you can configure it as an object, and provide values for authorizer, cors and invokeMode options.
The authorizer property can be set to aws_iam to enable AWS IAM authorization on your function URL.
functions:
func:
handler: index.handler
url:
authorizer: aws_iam
When using IAM authorization, the URL will only accept HTTP requests with AWS credentials allowing lambda:InvokeFunctionUrl (similar to API Gateway IAM authentication).
You can also configure CORS headers so that your function URL can be called from other domains in browsers. Setting cors to true will allow all domains via the following CORS headers:
functions:
func:
handler: index.handler
url:
cors: true
| Header | Value |
|---|---|
| Access-Control-Allow-Origin | * |
| Access-Control-Allow-Headers | Content-Type, X-Amz-Date, Authorization, X-Api-Key, X-Amz-Security-Token |
| Access-Control-Allow-Methods | * |
You can also additionally adjust your CORS configuration by setting allowedOrigins, allowedHeaders, allowedMethods, allowCredentials, exposedResponseHeaders, and maxAge properties as shown in example below.
functions:
func:
handler: index.handler
url:
cors:
allowedOrigins:
- https://url1.com
- https://url2.com
allowedHeaders:
- Content-Type
- Authorization
allowedMethods:
- GET
allowCredentials: true
exposedResponseHeaders:
- Special-Response-Header
maxAge: 6000 # In seconds
In the table below you can find how the cors properties map to CORS headers
| Configuration property | CORS Header |
|---|---|
| allowedOrigins | Access-Control-Allow-Origin |
| allowedHeaders | Access-Control-Allow-Headers |
| allowedMethods | Access-Control-Allow-Methods |
| allowCredentials | Access-Control-Allow-Credentials |
| exposedResponseHeaders | Access-Control-Expose-Headers |
| maxAge | Access-Control-Max-Age |
It is also possible to remove the values in CORS configuration that are set by default by setting them to null instead.
functions:
func:
handler: index.handler
url:
cors:
allowedHeaders: null
The invokeMode property can be set to RESPONSE_STREAM to enable streaming response. If not specified, BUFFERED invoke mode is assumed.
functions:
func:
handler: index.handler
url:
invokeMode: RESPONSE_STREAM
Referencing container image as a target
Alternatively lambda environment can be configured through docker images. Image published to AWS ECR registry can be referenced as lambda source (check AWS Lambda – Container Image Support). In addition, you can also define your own images that will be built locally and uploaded to AWS ECR registry.
osls will create an ECR repository for your image, but it currently does not manage updates to it. An ECR repository is created only for new services or the first time that a function configured with an image is deployed. In service configuration, you can configure the ECR repository to scan for CVEs via the provider.ecr.scanOnPush property, which is false by default. (See documentation)
You can also configure an ECR lifecycle policy to automatically clean up old images by setting provider.ecr.maxImageCount to a positive integer. When set, images exceeding this count will be expired. (See documentation)
In service configuration, images can be configured via provider.ecr.images. To define an image that will be built locally, you need to specify path property, which should point to valid docker context directory. Optionally, you can also set file to specify Dockerfile that should be used when building an image. It is also possible to define images that already exist in AWS ECR repository. In order to do that, you need to define uri property, which should follow <account>.dkr.ecr.<region>.amazonaws.com/<repository>@<digest> or <account>.dkr.ecr.<region>.amazonaws.com/<repository>:<tag> format.
Additionally, you can define arguments that will be passed to the docker build command via the following properties:
buildArgs: With thebuildArgsproperty, you can define arguments that will be passed todocker buildcommand with--build-argflag. They might be later referenced viaARGwithin yourDockerfile. (See Documentation)buildOptions: With thebuildOptionsproperty, you can define options that will be passed directly to thedocker buildcommand. TreatbuildOptionsas trusted input. Options such as--ssh,--secret,--network,--add-host, and additional build contexts can expose local resources or alter Docker build isolation. Do not run deployments or packaging for untrusted projects, templates, or pull requests that define Docker build options, and avoid placing secret values directly inbuildOptionsorbuildArgsbecause command arguments may appear in local logs or error output. (See Documentation)cacheFrom: ThecacheFromproperty can be used to specify which images to use as a source for layer caching in thedocker buildcommand with--cache-fromflag. (See Documentation)platform: Theplatformproperty can be used to specify the architecture target in thedocker buildcommand with the--platformflag. If not specified, Docker will build for your computer's architecture by default. AWS Lambda typically usesx86architecture unless otherwise specified in the Lambda's runtime settings. In order to avoid runtime errors when building on an ARM-based machine (e.g. Apple M1 Mac),linux/amd64must be used here. The options for this flag arelinux/amd64(x86-based Lambdas),linux/arm64(arm-based Lambdas), orwindows/amd64. (See Documentation)provenanceUse theprovenanceproperty to disable multi-architecture manifest generated from BuildKit ordocker buildx, allows the architecture specified inplatformto be recognized by AWS Lambda during deployment.
When uri is defined for an image, buildArgs, buildOptions, cacheFrom, and platform cannot be defined.
Example configuration
service: service-name
provider:
name: aws
ecr:
scanOnPush: true
maxImageCount: 10
images:
baseimage:
path: ./path/to/context
file: Dockerfile.dev
buildArgs:
STAGE: ${opt:stage}
cacheFrom:
- my-image:latest
platform: linux/amd64
provenance: false
anotherimage:
uri: 000000000000.dkr.ecr.sa-east-1.amazonaws.com/test-lambda-docker@sha256:6bb600b4d6e1d7cf521097177dd0c4e9ea373edb91984a505333be8ac9455d38
When configuring functions, images should be referenced via image property, which can point to an image already defined in provider.ecr.images or directly to an existing AWS ECR image, following the same format as uri above.
Both handler and runtime properties are not supported when image is used.
Example configuration:
service: service-name
provider:
name: aws
ecr:
images:
baseimage:
path: ./path/to/context
functions:
hello:
image: 000000000000.dkr.ecr.sa-east-1.amazonaws.com/test-lambda-docker@sha256:6bb600b4d6e1d7cf521097177dd0c4e9ea373edb91984a505333be8ac9455d38
world:
image: baseimage
It is also possible to provide additional image configuration via workingDirectory, entryPoint and command properties of to functions[].image. The workingDirectory accepts path in form of string, where both entryPoint and command needs to be defined as a list of strings, following "exec form" format. In order to provide additional image config properties, functions[].image has to be defined as an object, and needs to define either uri pointing to an existing AWS ECR image or name property, which references image already defined in provider.ecr.images.
Example configuration:
service: service-name
provider:
name: aws
ecr:
images:
baseimage:
path: ./path/to/context
functions:
hello:
image:
uri: 000000000000.dkr.ecr.sa-east-1.amazonaws.com/test-lambda-docker@sha256:6bb600b4d6e1d7cf521097177dd0c4e9ea373edb91984a505333be8ac9455d38
workingDirectory: /workdir
command:
- executable
- flag
entryPoint:
- executable
- flag
world:
image:
name: baseimage
command:
- command
entryPoint:
- executable
- flag
During the first deployment when locally built images are used, the CLI will automatically create a dedicated ECR repository to store these images, with name serverless-<service>-<stage>. By default, older versions of images uploaded to ECR are not removed as they still might be in use by versioned functions. To automatically expire old images, set provider.ecr.maxImageCount to limit the number of images retained in the repository. During sls remove, the created ECR repository will be removed. During deployment, the CLI will attempt to docker login to ECR if needed. Depending on your local configuration, docker authorization token might be stored unencrypted. Please refer to documentation for more details: https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Instruction set architecture
By default, Lambda functions are run by 64-bit x86 architecture CPUs. However, using arm64 architecture (AWS Graviton2 processor) may result in better pricing and performance.
To switch all functions to AWS Graviton2 processor, configure architecture at provider level as follows:
provider:
...
architecture: arm64
To toggle instruction set architecture per function individually, set it directly at functions[] context:
functions:
hello:
...
architecture: arm64
Runtime Management
Runtime Management allows for fine-grained control of the runtime being used for a lambda function in the rare event of compatibility issues with a function.
If you wish to keep runtimeManagement set to auto, that's the default so you don't need to specify it explicitly. If you wish for the runtime to only be updated when the function is redeployed, set it to onFunctionUpdate.
To configure runtime management for all functions, configure runtimeManagement at provider level as follows:
provider:
...
runtimeManagement: onFunctionUpdate
To toggle instruction set architecture per function individually, set it directly at functions[] context:
functions:
hello:
...
runtimeManagement:
mode: manual
arn: <aws runtime arn>
Finally, auto and onFunctionUpdate can be set as the mode property as well for completeness (and to allow for the scenario where this value comes from another variable source, for example).
SnapStart
Lambda SnapStart can improve startup performance for latency-sensitive applications on supported runtimes.
To enable SnapStart for your lambda function you can add the snapStart object property in the function configuration which can be put to true and will result in the value PublishedVersions for this function.
functions:
hello:
...
runtime: java25
snapStart: true
Note: SnapStart support and limitations are defined by AWS and may change over time. See the AWS SnapStart documentation for the current supported runtimes and restrictions.
AWS Lambda Durable Functions
AWS Lambda Durable Functions enable long-running, fault-tolerant workflows without custom chaining or external state management. Durable functions use checkpoint-and-replay mechanisms to reliably execute workflows that can run for up to one year.
To configure a durable function, add durableConfig to the function configuration:
functions:
orderProcessor:
handler: handler.processOrder
runtime: nodejs24.x
durableConfig:
executionTimeout: 3600
retentionPeriodInDays: 30
executionTimeout is required and accepts a value from 1 to 31,622,400 seconds. retentionPeriodInDays is optional and accepts a value from 1 to 90 days.
Durable functions require qualified Lambda invocations. When durableConfig is configured, osls automatically publishes a function version even when function versioning is otherwise disabled. osls also creates a stable durable alias for generated event targets and Lambda Function URLs so invocations are qualified. provisionedConcurrency remains supported for durable functions; osls attaches the provisioned concurrency configuration to the generated durable alias instead of creating a separate provisioned alias.
CloudFormation marks the top-level AWS::Lambda::Function.DurableConfig property as a replacement property: adding durableConfig to an already deployed function, or removing it, requires CloudFormation to replace the Lambda function. osls gives Lambda functions explicit names, so CloudFormation cannot perform the replacement invisibly; a replacement-requiring update of a custom-named resource fails and forces an explicit migration. Changing executionTimeout or retentionPeriodInDays values on an existing durable function updates with no interruption; osls publishes a new version and retargets the durable alias. Plan enable or disable migrations carefully, for example by deploying a new function name, shifting event sources, or recreating the stack when appropriate.
When using Lambda event source mappings, durable execution timeout must be 900 seconds or less. Event source mappings invoke durable functions synchronously through the generated durable alias. AWS Lambda Durable Functions support dead-letter queues and event source mapping destinations, but do not support Lambda asynchronous destinations configured through functions[].destinations. Functions configured with durableConfig also cannot declare cloudFront (Lambda@Edge) events.
Event source mappings do not support durable execution-name idempotency at launch. If retries must not start duplicate durable executions, implement idempotency in your function code or use an intermediary standard Lambda function that invokes the durable function with a DurableExecutionName.
The top-level functions[].maximumRetryAttempts Lambda asynchronous invocation setting is not supported with durableConfig; configure durable step retries in the AWS Durable Execution SDK instead. Event source mapping retry settings, such as stream.maximumRetryAttempts, remain supported where AWS supports them for that event source. maximumEventAge is still deployed for durable functions via the durable alias; AWS has not documented whether it is honored for durable executions.
When you configure a function with durableConfig, osls automatically adds inline lambda:CheckpointDurableExecution and lambda:GetDurableExecutionState permissions to the generated Lambda execution role. If you configure a custom function or provider IAM role, you must attach equivalent durable execution permissions yourself. For least privilege, scope the permissions to durable execution ARNs for the function, for example arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:my-service-dev-orderProcessor:*/durable-execution/*/*.
Lambda Function URLs for durable functions are configured on the generated durable alias. Function URLs are synchronous HTTP invoke endpoints, so use asynchronous invocation for durable executions that may run longer than a synchronous request can wait.
You can provide an execution name when invoking a durable function:
serverless invoke --function orderProcessor --qualifier durable --durable-execution-name order-12345
If you invoke a function with an execution name that already exists, Lambda handles the invocation idempotently only when the payload matches. A matching running execution returns existing execution information, and a matching closed execution returns the closed result. A different payload for the same execution name returns an error. Execution names must be 1-64 characters and can contain alphanumeric characters, hyphens, or underscores.
Use serverless deploy after code or durable configuration changes so CloudFormation can publish a new function version and update generated aliases and event targets. Adding or removing durableConfig may still require Lambda function replacement as described above. serverless deploy function and serverless rollback function are not supported for functions configured with durableConfig locally or already deployed with durable configuration because they update $LATEST without publishing and retargeting the durable alias.
Functions currently configured with durableConfig are skipped by osls function pruning because durable executions may depend on retained versions for replay.
osls supports durable functions for managed runtimes nodejs22.x, nodejs24.x, python3.13, python3.14, java17, java21, and java25, plus compatible container images. Durable functions with snapStart: true are limited to the runtime intersection supported by both features: python3.13, python3.14, java17, java21, and java25. Durable functions with SnapStart cannot use container images, EFS, provisioned concurrency, or ephemeral storage larger than 512 MB.
Recursive Loop Detection
By default, AWS Lambda detects and stops recursive invocation loops between supported AWS services. To allow recursive loops for a function, set recursiveLoop to Allow. To explicitly enforce termination (the default behavior), set it to Terminate.
functions:
hello:
handler: handler.hello
recursiveLoop: Allow
VPC Configuration
You can add VPC configuration to a specific function in serverless.yml by adding a vpc object property in the function configuration. This object should contain the securityGroupIds and subnetIds array properties needed to construct VPC for this function. Here's an example configuration:
# serverless.yml
service: service-name
provider: aws
functions:
hello:
handler: handler.hello
vpc:
securityGroupIds:
- securityGroupId1
- securityGroupId2
subnetIds:
- subnetId1
- subnetId2
Or if you want to apply VPC configuration to all functions in your service, you can add the configuration to the higher level provider object, and overwrite these service level config at the function level. For example:
# serverless.yml
service: service-name
provider:
name: aws
vpc:
securityGroupIds:
- securityGroupId1
- securityGroupId2
subnetIds:
- subnetId1
- subnetId2
functions:
hello: # this function will overwrite the service level vpc config above
handler: handler.hello
vpc:
securityGroupIds:
- securityGroupId1
- securityGroupId2
subnetIds:
- subnetId1
- subnetId2
users: # this function will inherit the service level vpc config above
handler: handler.users
Then, when you run serverless deploy, VPC configuration will be deployed along with your lambda function.
If you have a provider VPC set but wish to have specific functions with no VPC, you can set the vpc value for these functions to ~ (null). For example:
# serverless.yml
service: service-name
provider:
name: aws
vpc:
securityGroupIds:
- securityGroupId1
- securityGroupId2
subnetIds:
- subnetId1
- subnetId2
functions:
hello: # this function will have no vpc configured
handler: handler.hello
vpc: ~
users: # this function will inherit the service level vpc config above
handler: handler.users
VPC IAM permissions
The Lambda function execution role must have permissions to create, describe and delete Elastic Network Interfaces (ENI). When VPC configuration is provided the default AWS AWSLambdaVPCAccessExecutionRole will be associated with your Lambda execution role. In case custom roles are provided be sure to include the proper ManagedPolicyArns. For more information please check configuring a Lambda Function for Amazon VPC Access
VPC Lambda Internet Access
By default, when a Lambda function is executed inside a VPC, it loses internet access and some resources inside AWS may become unavailable. In order for S3 resources and DynamoDB resources to be available for your Lambda function running inside the VPC, a VPC end point needs to be created. For more information please check VPC Endpoint for Amazon S3. In order for other services such as Kinesis streams to be made available, a NAT Gateway needs to be configured inside the subnets that are being used to run the Lambda, for the VPC used to execute the Lambda. For more information, please check Enable Outgoing Internet Access within VPC
VPC Lambda Internet IPv6 Access
Alternatively to setting up a NAT Gateway, you can also use an egress-only internet gateway and allow your functions in a VPC to access the internet or other AWS services via IPv6. This eliminates the need for a NAT Gateway, reducing costs and simplifying architecture. In this case, VPC-configured Lambda functions can be allowed to access the internet using egress-only internet gateway by adding a ipv6AllowedForDualStack option to either the functions VPC specification:
# serverless.yml
service: service-name
provider: aws
functions:
hello:
handler: handler.hello
vpc:
ipv6AllowedForDualStack: true
securityGroupIds:
- securityGroupId1
- securityGroupId2
subnetIds:
- subnetId1
- subnetId2
Or if you want to apply VPC configuration to all functions in your service, you can add the configuration to the higher level provider object, and overwrite these service level config at the function level. For example:
# serverless.yml
service: service-name
provider:
name: aws
vpc:
ipv6AllowedForDualStack: true
securityGroupIds:
- securityGroupId1
- securityGroupId2
subnetIds:
- subnetId1
- subnetId2
functions: ...
For more information, please check Announcing AWS Lambda’s support for Internet Protocol Version 6 (IPv6) for outbound connections in VPC
Environment Variables
You can add environment variable configuration to a specific function in serverless.yml by adding an environment object property in the function configuration. This object should contain a key-value pairs of string to string:
# serverless.yml
service: service-name
provider: aws
functions:
hello:
handler: handler.hello
environment:
TABLE_NAME: tableName
Or if you want to apply environment variable configuration to all functions in your service, you can add the configuration to the higher level provider object. Environment variables configured at the function level are merged with those at the provider level, so your function with specific environment variables will also have access to the environment variables defined at the provider level. If an environment variable with the same key is defined at both the function and provider levels, the function-specific value overrides the provider-level default value. For example:
# serverless.yml
service: service-name
provider:
name: aws
environment:
SYSTEM_NAME: mySystem
TABLE_NAME: tableName1
functions:
hello:
# this function will have SYSTEM_NAME=mySystem and TABLE_NAME=tableName1 from the provider-level environment config above
handler: handler.hello
users:
# this function will have SYSTEM_NAME=mySystem from the provider-level environment config above
# but TABLE_NAME will be tableName2 because this more specific config will override the default above
handler: handler.users
environment:
TABLE_NAME: tableName2
If you want your function's environment variables to have the same values from your machine's environment variables, please read the documentation about Referencing Environment Variables.
Tags
Using the tags configuration makes it possible to add key / value tags to your functions.
Those tags will appear in your AWS console and make it easier for you to group functions by tag or find functions with a common tag.
functions:
hello:
handler: handler.hello
tags:
foo: bar
Or if you want to apply tags configuration to all functions in your service, you can add the configuration to the higher level provider object. Tags configured at the function level are merged with those at the provider level, so your function with specific tags will get the tags defined at the provider level. If a tag with the same key is defined at both the function and provider levels, the function-specific value overrides the provider-level default value. For example:
# serverless.yml
service: service-name
provider:
name: aws
tags:
foo: bar
baz: qux
functions:
hello:
# this function will inherit the service level tags config above
handler: handler.hello
users:
# this function will overwrite the foo tag and inherit the baz tag
handler: handler.users
tags:
foo: quux
Real-world use cases where tagging your functions is helpful include:
- Cost estimations (tag functions with an environment tag:
environment: Production) - Keeping track of legacy code (e.g. tag functions which use outdated runtimes:
runtime: legacy) - ...
Layers
Using the layers configuration makes it possible for your function to use
Lambda Layers
functions:
hello:
handler: handler.hello
layers:
- arn:aws:lambda:region:XXXXXX:layer:LayerName:Y
Layers can be used in combination with runtime: provided.al2023 to implement your own custom runtime on
AWS Lambda.
To publish Lambda Layers, check out the Layers documentation.
Log Group Resources
By default, osls will create LogGroups for your Lambdas. This makes it easy to clean up your log groups in the case you remove your service, and make the lambda IAM permissions much more specific and secure.
You can opt out of the default behavior by setting disableLogs: true
You can also specify the duration for CloudWatch log retention by setting logRetentionInDays.
You can specify the DataProtectionPolicy for the LogGroup by setting logDataProtectionPolicy. On how to define the policy consult the aws docs.
functions:
hello:
handler: handler.hello
disableLogs: true
goodBye:
handler: handler.goodBye
logRetentionInDays: 14
logDataProtectionPolicy:
Name: data-protection-policy
Versioning Deployed Functions
By default, osls creates function versions for every deploy. This behavior is optional, and can be turned off in cases where you don't invoke past versions by their qualifier. If you would like to do this, you can invoke your functions as arn:aws:lambda:....:function/myFunc:3 to invoke version 3 for example.
Older versions are not removed automatically unless you enable provider.pruneFunctionVersions. When enabled, osls deletes function and layer versions beyond the configured limit after a full service deploy (serverless deploy), keeping the newest versions. Function versions referenced by an alias are never deleted; layer versions are pruned purely by recency. serverless deploy function does not publish new versions and does not prune.
To turn off function versioning, set the provider-level option versionFunctions. pruneFunctionVersions cannot be used when versionFunctions is false, unless the only functions publishing versions are durable: at least one function configures durableConfig and no other function sets versionFunction: true. Functions configured with durableConfig are always skipped by function pruning, so in this configuration only layer versions are pruned.
provider:
versionFunctions: false
Enable automatic pruning after deploy:
provider:
pruneFunctionVersions: true # keeps 10 versions (default)
# pruneFunctionVersions:
# number: 20
number is how many of the newest versions to keep; the currently-deployed version is always retained. Replicated Lambda@Edge versions that AWS will not delete are skipped with a warning rather than failing the deploy.
Dead Letter Queue (DLQ)
When AWS lambda functions fail, they are retried. If the retries also fail, AWS has a feature to send information about the failed request to a SNS topic or SQS queue, called the Dead Letter Queue, which you can use to track and diagnose and react to lambda failures.
You can setup a dead letter queue for your serverless functions with the help of a SNS topic and the onError config parameter.
Note: You can only provide one onError config per function.
DLQ with SNS
The SNS topic needs to be created beforehand and provided as an arn on the function level.
service: service
provider:
name: aws
runtime: nodejs24.x
functions:
hello:
handler: handler.hello
onError: arn:aws:sns:us-east-1:XXXXXX:test # Ref, Fn::GetAtt and Fn::ImportValue are supported as well
DLQ with SQS
Although Dead Letter Queues support both SNS topics and SQS queues, the onError config currently only supports SNS topic arns due to a race condition when using SQS queue arns and updating the IAM role.
We're working on a fix so that SQS queue arns will be supported in the future.
KMS Keys
AWS Lambda uses AWS Key Management Service (KMS) to encrypt your environment variables at rest.
The kmsKeyArn config variable enables you a way to define your own KMS key which should be used for encryption.
service:
name: service-name
provider:
name: aws
kmsKeyArn: arn:aws:kms:us-east-1:XXXXXX:key/some-hash
environment:
TABLE_NAME: tableName1
functions:
hello: # this function will OVERWRITE the service level environment config above
handler: handler.hello
kmsKeyArn: arn:aws:kms:us-east-1:XXXXXX:key/some-hash
environment:
TABLE_NAME: tableName2
goodbye: # this function will INHERIT the service level environment config above
handler: handler.goodbye
Secrets using environment variables and KMS
When storing secrets in environment variables, AWS strongly suggests encrypting sensitive information. AWS provides a tutorial on using KMS for this purpose.
AWS X-Ray Tracing
You can enable AWS X-Ray Tracing on your Lambda functions through the optional tracing config variable:
service: myService
provider:
name: aws
runtime: nodejs24.x
tracing:
lambda: true
You can also set this variable on a per-function basis. This will override the provider level setting if present:
functions:
hello:
handler: handler.hello
tracing: Active
goodbye:
handler: handler.goodbye
tracing: PassThrough
Asynchronous invocation
When intention is to invoke function asynchronously you may want to configure following additional settings:
Destinations
Target can be the other lambdas you also deploy with a service or other qualified target (externally managed lambda, EventBridge event bus, SQS queue or SNS topic) which you can address via its ARN or reference
functions:
asyncHello:
handler: handler.asyncHello
destinations:
onSuccess: otherFunctionInService
onFailure: arn:aws:sns:us-east-1:xxxx:some-topic-name
asyncGoodBye:
handler: handler.asyncGoodBye
destinations:
onFailure:
# For the case using CF intrinsic function for `arn`, to ensure target execution permission exactly, you have to specify `type` from 'sns', 'sqs', 'eventBus', 'function'.
type: sns
arn:
Ref: SomeTopicName
Maximum Event Age and Maximum Retry Attempts
maximumEventAge accepts values between 60 seconds and 6 hours, provided in seconds.
maximumRetryAttempts accepts values between 0 and 2.
The top-level functions[].maximumRetryAttempts setting is not supported for durable functions because Lambda asynchronous retry attempts do not apply to durable executions. Use retry strategies in the AWS Durable Execution SDK for durable workflow steps. Event source mapping retry settings are separate and remain available where AWS supports them.
functions:
asyncHello:
handler: handler.asyncHello
maximumEventAge: 7200
maximumRetryAttempts: 1
EFS Configuration
You can use Amazon EFS with Lambda by adding a fileSystemConfig property in the function configuration in serverless.yml. fileSystemConfig should be an object that contains the arn and localMountPath properties. The arn property should reference an existing EFS Access Point, where the localMountPath should specify the absolute path under which the file system will be mounted. Here's an example configuration:
# serverless.yml
service: service-name
provider: aws
functions:
hello:
handler: handler.hello
fileSystemConfig:
localMountPath: /mnt/example
arn: arn:aws:elasticfilesystem:us-east-1:111111111111:access-point/fsap-0d0d0d0d0d0d0d0d0
vpc:
securityGroupIds:
- securityGroupId1
subnetIds:
- subnetId1
Ephemeral storage
By default, Lambda allocates 512 MB of ephemeral storage in functions under the /tmp directory.
You can increase its size via the ephemeralStorageSize property. It should be a numerical value in MBs, between 512 and 10240.
functions:
helloEphemeral:
handler: handler.handler
ephemeralStorageSize: 1024
Logging Configuration
Configuring Lambda advanced logging options
This can be configured at the provider level (applies to all functions) or individually per function:
# Provider-level configuration (applies to all functions)
provider:
logs:
lambda:
logFormat: JSON
applicationLogLevel: INFO
systemLogLevel: WARN
logGroup: /aws/lambda/global-log-group
# Function-level configuration (overrides provider settings)
functions:
helloLogging:
handler: handler.handler
logs:
applicationLogLevel: DEBUG
logFormat: JSON
logGroup: helloLoggingLogGroup
systemLogLevel: DEBUG