Deprecating Lambda compatibility mode

Lambda compatibility mode is being deprecated

TL;DR

  • June 1, 2027: New deploys containing functions in Lambda compatibility mode will fail to build.
  • December 31, 2027: existing functions in Lambda compatibility mode stop being invoked and will return errors.
  • What to do: migrate to the modern Netlify Functions API (recommended), or use @netlify/aws-lambda-compat to keep the AWS Lambda handler signature on the modern runtime.

What is Lambda compatibility mode?

When we launched Netlify Functions 2.0 in 2023, we kept supporting the previous AWS Lambda-style API under a “Lambda compatibility mode.” This is the mode that uses the exports.handler (or export const handler) signature with event / context arguments and a { statusCode, body } return value:

exports.handler = async (event, context) => {
  return { statusCode: 200, body: "Hello!" };
};

Modern Netlify Functions use a web-standard signature with a Request argument and a Response return value:

export default async (req, context) => {
  return new Response("Hello!");
};

If your functions use the first form, this announcement applies to you. If they use the second form, you’re already on the modern API and there’s nothing to do.

Why we’re deprecating it

When we launched the modern API, we stopped adding new features to Lambda compatibility mode. Every platform primitive we’ve shipped since then (Blobs, the Cache API, AI Gateway, per-function memory/vCPU/region configuration, typed event handlers, and context.waitUntil for background work) only works out of the box with the modern API.

We’re also moving some compute workloads outside of AWS Lambda, which means we can no longer guarantee that the raw AWS Lambda APIs will remain available indefinitely. Continuing to support the legacy mode forks our investment and constrains the platform improvements we can make.

Deprecating Lambda compatibility mode lets us focus on a single, well-supported API surface and unblocks a category of improvements that aren’t possible while we maintain the legacy path.

Timeline

  • Today through May 31, 2027: no change. Existing legacy functions continue to deploy and run as they do today. New deploys can still include legacy functions, but we’ll surface warnings in the build log to flag them. We recommend migrating any time before the cutoff.
  • June 1, 2027: deploys containing functions in Lambda compatibility mode will start failing. Existing legacy functions that were already deployed continue to be invoked normally up to the second cutoff.
  • December 31, 2027: invocations of legacy functions stop. Any function still using Lambda compatibility mode after this date will return an error when called.

We’re giving more than a year of advance notice and an additional seven months between the deploy-cutoff and the invocation-cutoff specifically to give teams time to plan, migrate, and verify before anything stops working.

What to do

You have two paths. Either works; pick the one that fits your code.

Option 1 (recommended): migrate to the modern API

Most legacy functions migrate in a few minutes. The signatures map cleanly:

Lambda compatibility Modern API
event.queryStringParameters?.name new URL(req.url).searchParams.get("name")
event.body await req.text() or await req.json()
event.headers["x-custom"] req.headers.get("x-custom")
return { statusCode, headers, body } return new Response(body, { status, headers })

For a step-by-step walkthrough, see our migration guide. If you’d rather not migrate by hand, an Agent Runner can do the migration for you in a single prompt.

This is the path we recommend for almost everyone. Once you’re on the modern API, you get access to every Netlify primitive and every new feature we ship.

Option 2: use @netlify/aws-lambda-compat

If you’d rather keep the AWS Lambda handler signature — for example, because you’re porting functions from another Lambda-based platform and want to avoid touching the code, or simply because you prefer the Lambda API — install @netlify/aws-lambda-compat and wrap your existing handler with withLambda:

import { withLambda } from "@netlify/aws-lambda-compat";

export default withLambda(async (event, context) => {
  return {
    statusCode: 200,
    headers: { "content-type": "application/json" },
    body: JSON.stringify({
      name: event.queryStringParameters?.name ?? "stranger"
    })
  };
});

Under the hood, this wraps your Lambda-style handler in a modern function, so it’s not affected by the deprecation, even though the code inside the wrapper still looks Lambda-shaped. The package is open-source; you can keep using it indefinitely.

Common questions

How will I know if my project uses Lambda compatibility mode?
After functions bundling, the Netlify build log will list any functions still using Lambda compatibility mode. Each entry tells you where the function came from (your repository, a build plugin, or a framework adapter) so you know the right action to take.

Will my existing functions break before the cutoff dates?
No. Existing legacy functions continue to deploy and run as they do today, all the way up to the respective cutoffs.

What do I do if my functions are generated by a framework adapter?
Update the framework adapter to a version that emits modern Netlify Functions. If no such version exists, please contact the adapter’s maintainer or open an issue with them.

What do I do if my functions are generated by a build plugin?
Update the build plugin. If you maintain the plugin, switch it to emit the modern API. If a third party maintains it, please contact them. When in doubt, feel free to post in this forum or open a support ticket with us.

Can I still use the AWS Lambda runtime properties (e.g. context.functionName, event.awsRequestId)?
Yes, via @netlify/aws-lambda-compat. The wrapper exposes the same HandlerEvent and HandlerContext shapes you’re used to.

What happens if I deploy after June 1, 2027 with a legacy function still in my project?
The deploy will fail at the functions bundling stage with an error listing the offending functions. You can either migrate them (Option 1) or wrap them with withLambda (Option 2), then redeploy.

Questions or concerns?

Reply in this thread. We’ll be reading and responding.