New Lambda implementation in LocalStack 2.0

LocalStack v2.0 offers a completely rewritten implementation of our local Lambda service with improved performance, feature coverage, AWS parity, and many more improvements. This new lambda provider v2 (formerly known as asf) supports 95% of all Lambda API operations and behaves like in AWS. Our documentation describes migrating to Lambda v2 in detail.

Highlights

  • Feature coverage: LocalStack supports 95% of all Lambda API operations.
  • AWS Parity: The local Lambda API behaves like in AWS with 90% parity test coverage.
  • Official AWS images: Lambda functions use the official Docker base images pulled from public.ecr.aws/lambda/.
  • Lambda runtimes: All supported managed runtimes from AWS are available and tested in LocalStack. The new provider added nodejs18.x, python3.10, and java17.
  • ARM support: Run arm64 and x86_64 Lambda functions on hosts with multi-architecture support.
  • Extensions API: Use third-party extensions to customize the Lambda execution environment. This deep integration enables monitoring, observability, or advanced developer tooling.
  • Lambda concurrency: Prevent cold-starts with provisioned concurrency and limit the number of concurrent function instances with reserved concurrency.
  • Performance: 10ms warm-start and 600ms cold-start for an Echo Python Lambda
  • Hot reloading: Continuously apply code changes to Lambda functions and layers (Pro) for all managed runtimes.
  • Persistence and Cloud Pods: Save your Lambda state across restarts and share a snapshot of your Lambda infrastructure.

Improvements

  • Permissions: CRUD operations for resource-based policies are now fully supported and thoroughly tested (e.g., AddPermission).
  • API-level validations: Stricter input validation detects syntax errors early and raises the same exceptions as in AWS. For example, r1 is an invalid execution role because it does not match ARN format arn:aws:iam::000000000000:role/lambda-role.
  • Function state lifecycle: Creating and updating lambda functions happens asynchronously following the Lambda state lifecycle. Functions are always created in the Pending state and move to Active once ready to accept invocations.
  • Runtime parity: Compared to AWS, Lambda functions run as the same user with (almost) the same environment variables and mostly the same quota (some ulimits are intentionally opt-in).
  • Function versions and aliases: Improved support and thorough test coverage.
  • Layer CRUD Open-Source: Basic CRUD operations are available in LocalStack Community but using any layers at runtime requires a Pro subscription.
  • Shared Lambda layers (Pro): Fetching shared lambda layers hosted on AWS is faster and supports ARM layers. Get inspired by awesome-layers.
  • Asynchronous event handling: Handle asynchronous events with retries and exceptions.
  • Lambda function URLs: Improved handling and better test coverage.
  • Invocation response: Improved capturing and rendering of invocation results (e.g., Payload, LogResult, FunctionError) when invoking functions.
  • Function timeouts: Reliably enforced like in AWS.
  • X-Ray (Pro): Integrated the official AWS X-Ray daemon for collecting distributed traces from instrumented handlers.

Migrating to Lambda v2

This section describes the behavioral changes related to the Lambda API, Docker Execution Environment, Configuration, and Hot Reloading.

Lambda API

Improved parity compared to AWS: Lambda API methods in LocalStack behave like in AWS. This was not always the case in the old provider without systematic testing. If you discover a difference between LocalStack and AWS in the new provider, please report a bug on GitHub.

Stricter input validation: Expect more exceptions in the new provider due to invalid input. For example, the old provider accepted arbitrary strings such as r1 as a lambda role when creating a function. The new provider validates the role ARN in the format arn:aws:iam::000000000000:role/lambda-role using an appropriate regex but currently does not check whether it exists.

Asynchronous function creation: Creating and updating lambda functions now happens asynchronously following the AWS Lambda state model. The old provider created functions synchronously by blocking until the function state was active. In the new provider, functions are always created in the Pending state and move to Active once they are ready to accept invocations. Migration instructions are provided in the troubleshooting example Function in Pending state.

Docker Execution Environment

Docker socket mounting required: Mounting the Docker socket into the LocalStack container is now required to run lambda functions. Please add the Docker volume mount "/var/run/docker.sock:/var/run/docker.sock" to your LocalStack startup as exemplified in our official docker-compose.yml. If mounting the Docker socket is impossible and no external DOCKER_HOST is available, self-managed worker containers will be available (coming soon).

Local executor mode is discontinued: The Lambda Executor Modes such as LAMBDA_EXECUTOR=local are discontinued in the new provider. In the old provider, lambda functions were executed within the LocalStack container in the local executor mode. It was primarily used as a fallback if the Docker socket was unavailable in the LocalStack container. Hence, many users unintentionally used the local executor mode despite configuring LAMBDA_EXECUTOR=docker. The new provider requires no such configuration and now behaves similarly to the old docker-reuse executor.

No container restart after each invocation: Lambda containers are reused between invocations. Therefore, filesystem changes (for example, in /tmp) persist between subsequent invocations if dispatched to the same container. It is called a “warm start” (see Operating Lambda). If you want to force “cold starts”, you could set LAMBDA_KEEPALIVE_MS to 0 milliseconds.

Official AWS-provided Lambda images: The new provider uses the official AWS base images for Lambda pulled from public.ecr.aws/lambda/ instead of lambci images. Hence, Lambda functions’ filesystem now matches the AWS Lambda production environment.

ARM64 lambda functions: Lambda now supports ARM containers for compatible runtimes based on Amazon Linux 2. ARM-compatible hosts can create functions with the arm64 architecture.
More details are provided under ARM64 support.

Transparent endpoint injection in LocalStack Pro: Lambda functions resolve AWS domains such as s3.amazonaws.com to the LocalStack container. This domain resolution is now completely DNS-based and can be disabled by setting DNS_ADDRESS=0. For more details, please refer to Transparent Endpoint Injection. The old provider provided patched AWS SDKs to redirect AWS API transparently calls to LocalStack.

Configuration

The new provider offers new configuration options documented under Configuration. Please open a feature request on GitHub and motivate your scenario if you miss something.

The following configuration options from the old provider are discontinued in the new provider:

  • LAMBDA_EXECUTOR and, in particular, LAMBDA_EXECUTOR=local should be removed (see “Local executor mode is discontinued” above).
  • LAMBDA_STAY_OPEN_MODE is now the default behavior and can be removed. Instead, LAMBDA_KEEPALIVE_MS can be used to configure how long containers should be kept running in-between invocations.
  • LAMBDA_REMOTE_DOCKER is not used anymore because the new provider always copies zip files and automatically configures hot reloading.
  • LAMBDA_CODE_EXTRACT_TIME is no longer used because function creation now happens asynchronously.
  • LAMBDA_CONTAINER_REGISTRY is not used anymore. Use the more flexible LAMBDA_RUNTIME_IMAGE_MAPPING to customize individual runtimes.
  • LAMBDA_FALLBACK_URL is not supported anymore.
  • LAMBDA_FORWARD_URL is not supported anymore.
  • LAMBDA_JAVA_OPTS is currently not directly supported anymore. It is configurable via a custom wrapper script.
  • HOSTNAME_FROM_LAMBDA is not supported anymore.
  • LAMBDA_XRAY_INIT is no longer needed because the X-Ray daemon is always initialized.
  • SYNCHRONOUS_KINESIS_EVENTS and SYNCHRONOUS_SNS_EVENTS are not supported anymore.

The new provider still supports the following configuration options:

  • BUCKET_MARKER_LOCAL has a new default value, hot-reload (new), because the former default __local__ (old) is an invalid bucket name.
  • LAMBDA_TRUNCATE_STDOUT
  • LAMBDA_DOCKER_NETWORK
  • LAMBDA_DOCKER_FLAGS
  • LAMBDA_REMOVE_CONTAINERS
  • LAMBDA_DOCKER_DNS is supported in LocalStack >2.1 (latest since 2023-06-06)

Hot Reloading

Hot Reloading (formerly known as hot swapping) continuously applies code changes to Lambda functions without manual redeployment.

Default S3 bucket name changed: The default magic S3 bucket name changed from __local__ to hot-reload. Please change your deployment configuration accordingly, or use the BUCKET_MARKER_LOCAL configuration to customize the value.

Delay in code change detection: It can take up to 700ms to detect code changes.
In the meantime, invocations still execute the former code. Hot reloading triggers after 500ms without changes can take up to 200ms until the change is notified. In the old provider, changes were reflected instantly using code mounting but container restarting added extra delay.

Runtime restart after each code change: The runtime inside the container is restarted after every code change. During the runtime restart, the handler function re-executes any initialization code outside your handler function. The container itself is not restarted. Therefore, filesystem changes persist between code changes for invocations dispatched to the same container.

File sharing permissions with Docker Desktop on macOS: If using Docker Desktop on macOS, you might need to allow file sharing for your target folders. MacOS may prompt you to grant Docker access to your target folders.

Startup configuration automated: Hot reloading now works without additional LocalStack startup configuration. In the old provider, starting LocalStack with LAMBDA_REMOTE_DOCKER=0 was required. This configuration is not used anymore because the new provider always copies zip files and automatically configures hot reloading.

FAQ

How can I use the new Lambda provider?

Update to LocalStack ≥2.0 and the new Lambda provider is active by default.

What do I need to do to use the new Lambda provider?

Please check out our guide about migrating to Lambda v2. Most likely,

  1. Add the Docker volume mount "/var/run/docker.sock:/var/run/docker.sock"
  2. Before invoking a function, wait until the function becomes Active using a waiter.
  3. If using hot reloading, change the magic S3 bucket name from __local__ to hot-reload

How can I fix errors related to Docker not available?

Add the Docker volume mount "/var/run/docker.sock:/var/run/docker.sock"
to your LocalStack startup as exemplified in our official docker-compose.yml.
Check out our troubleshooting guide.

How can I fix the ResourceConflictException when trying to invoke a function?

Wait until the function transitions from the state Pending to Active using a waiter, for example, awslocal lambda wait function-active-v2 --function-name my-function
Check out our troubleshooting guide.

How can I use the old Lambda provider (deprecated)?

The old lambda provider is temporarily available in LocalStack v2 using PROVIDER_OVERRIDE_LAMBDA=legacy but we highly recommend migrating to the new lambda provider. Please let us know on GitHub or LocalStack Pro Support if you experience any issues.

10 Likes