Lambda "Unzipped Size Must Be Smaller Than 262144000 Bytes": Why pandas and pyarrow Alone Break the 250 MB Limit, and Every Fix for Python, Node.js, Layers and Container Images

Logeshwaran
—

AWS Lambda's "Unzipped size must be smaller than 262144000 bytes" means your function's code, once unzipped, plus every layer attached to it, adds up to more than 250 MB. Lambda counts a megabyte as 1,048,576 bytes here, so 250 MB is exactly 262,144,000 bytes. The size of your .zip file doesn't matter for this error, and uploading through S3 doesn't raise the limit: only a smaller unzipped total fixes it, or a switch to a container image, which can be 10 GB. Here's the surprise: two libraries are enough to hit it. pandas and pyarrow, installed by pip for Python 3.13, take 294.2 MB before you've written a line of your own code, and pyarrow alone is 164.1 MB. Most of the cure is leaving out what your function never needs: the tests folders inside those packages, and the bytecode pip compiled along the way. The same two libraries then come to 230.4 MB, and the function deploys. This page shows how to measure your real number in a minute, every cut that works for Python and Node.js, and when to stop trimming and use a layer, a container image or EFS instead.

Ethan, a developer, looks after the software for his friend Jake's phone repair shop. Jake wanted a nightly report: read the day's repair tickets, which an app saves in S3 as Parquet files, add them up with pandas, and email the totals. It worked on Ethan's laptop in an afternoon. Then he ran the deploy, and Lambda answered with a 262,144,000-byte complaint. His zip was 93 MB. "That's not even half," he said. This page is everything he found in the next hour.

⚡ Quick Answer

• What counts: your code unzipped plus every layer, against 250 MB. The zip file's size is a different limit. The limits.

• Measure first: zipinfo -t function.zip, or the small script below that also adds up your layers and names the biggest folders. Measure it.

• Python: install inside the Lambda image, leave out tests and __pycache__, and drop pyarrow if you don't need Parquet. The four cuts.

• Node.js: npm ci --omit=dev, then bundle with esbuild; the runtime already has the AWS SDK v3. Node fixes.

• Still over? A container image allows 10 GB and needs no trimming. Switch to an image.

Zip over 50 MB and getting RequestEntityTooLargeException? That's the upload limit, fixed by going through S3. The S3 route.

New to Lambda? A Lambda function is code that AWS runs for you when something happens, without a server of your own. You hand it your code and libraries as a .zip file, called the deployment package, or as a container image. This page is about what happens when that package gets too big. Our guides to Lambda and S3 cover the basics.

🧭 NEW HERE? READ THESE FIRST

New to Lambda and container images? These five pages make the rest of this one easy:

📌 Bookmark this; the size tables and the two scripts are the parts you will come back for.

What "Unzipped size must be smaller than 262144000 bytes" means

Lambda has three size limits for a function's code, plus two related numbers, and this error is about the second row:

LimitSizeWhat it applies to
Zip uploaded directly (console, CLI, SDK)50 MB, zippedThe .zip file you send in the request. Larger files go through S3.
Code plus layers, unzipped250 MB (262,144,000 bytes)Everything in your zip after extraction, plus every layer, plus a custom runtime if you use one
Container image10 GB, uncompressedThe whole image, including all its layers
Layers per function5Each one counts toward the 250 MB
/tmp storage512 MB to 10,240 MBScratch space while the function runs; not part of the package

The same problem can reach you as any of these messages:

Unzipped size must be smaller than 262144000 bytes
Function code combined with layers exceeds the maximum allowed size of 262144000 bytes
RequestEntityTooLargeException
The deployment package of your Lambda function is too large to enable inline code editing

The first two are this page: the unzipped total is over 250 MB. RequestEntityTooLargeException on an UpdateFunctionCode or CreateFunction call is usually the 50 MB upload limit instead, and the S3 route fixes it. The last one isn't an error at all: the function still works, but the console won't open a package that big in its code editor, so you edit the code on your own machine.

The 250 MB can't be raised; it isn't a quota you can request more of. Some people see the first message with a smaller number, such as 105288401 bytes. Whatever number yours shows, start the same way: measure everything unzipped, your code and every layer, and compare it with the limit.

Jake: "So the 93 MB file you uploaded is really almost 300 MB once Lambda opens it."

Ethan: "Right. Zip squeezes Python libraries to about a third. Lambda doesn't care how small the box is, only how much is inside it."

Measure the real number in one minute

On Linux, macOS or Kali, zipinfo prints the unzipped total on its last line:

zipinfo -t function.zip
1536 files, 241626585 bytes uncompressed, 75828972 bytes compressed:  68.6%

Compare the "bytes uncompressed" figure with 262,144,000. On Windows, or anywhere with Python, this one line gives the same number:

python -c "import sys, zipfile; print(sum(i.file_size for i in zipfile.ZipFile(sys.argv[1]).infolist()))" function.zip

Those count one zip. Lambda counts your code and all the layers together, and you also want to know which library is eating the space. Save this as lambda_size.py; it takes your function zip and any layer zips, adds them up, and lists the biggest folders:

import sys
import zipfile
from collections import Counter

LIMIT = 262_144_000  # 250 MB: function code plus every layer, unzipped
MB = 1_048_576
WRAPPERS = {"python", "nodejs", "node_modules", "lib", "site-packages"}

total = 0
folders = Counter()
for path in sys.argv[1:]:
    size = 0
    with zipfile.ZipFile(path) as z:
        for info in z.infolist():
            size += info.file_size
            parts = [p for p in info.filename.split("/")
                     if p and p not in WRAPPERS and not p.startswith("python3.")]
            folders[parts[0] if parts else "(root)"] += info.file_size
    print(f"{path:<34} {size / MB:8.1f} MB unzipped")
    total += size

print(f"{'TOTAL':<34} {total / MB:8.1f} MB of 250.0 MB")
if total > LIMIT:
    print(f"Over the limit by {(total - LIMIT) / MB:.1f} MB")
else:
    print(f"Room left: {(LIMIT - total) / MB:.1f} MB")

print("\nBiggest folders:")
for name, size in folders.most_common(8):
    print(f"  {name:<32} {size / MB:8.1f} MB")

Run it as python3 lambda_size.py function.zip, or python3 lambda_size.py function.zip layer1.zip layer2.zip when layers are attached. Here's Ethan's first zip, pandas and pyarrow exactly as pip installed them:

function.zip                          294.2 MB unzipped
TOTAL                                 294.2 MB of 250.0 MB
Over the limit by 44.2 MB

Biggest folders:
  pyarrow                             164.1 MB
  pandas                               63.7 MB
  numpy                                38.7 MB
  numpy.libs                           26.2 MB
  dateutil                              0.7 MB
  pandas-3.0.6.dist-info                0.4 MB
  numpy-2.5.4.dist-info                 0.2 MB
  pyarrow-26.0.0.dist-info              0.2 MB

Measure what's already deployed, layers included

If you didn't build the zip yourself, because a framework or a pipeline did, download what Lambda actually has. These commands list the function's layers, then fetch the function's code and one layer as zip files you can feed to the script:

aws lambda get-function --function-name repairs-report \
  --query "Configuration.Layers[].Arn" --output text

curl -s -o deployed.zip "$(aws lambda get-function --function-name repairs-report --query Code.Location --output text)"

curl -s -o layer1.zip "$(aws lambda get-layer-version-by-arn --arn arn:aws:lambda:us-east-1:111122223333:layer:pandas-pyarrow:3 --query Content.Location --output text)"

python3 lambda_size.py deployed.zip layer1.zip

The CodeSize fields that get-function returns are the sizes of the zip files, so they can look comfortably small while the unzipped total is over. The download links are short-lived (a layer's is valid for 10 minutes), so fetch them right after asking.

Why pandas and pyarrow alone break the limit

Data libraries ship compiled code for speed, and lots of it. They also ship their own test suites, which you never run on Lambda. Ethan's whole function is short:

import pandas as pd
import pyarrow


def lambda_handler(event, context):
    df = pd.DataFrame({"repair": ["screen", "battery", "charging port"], "count": [14, 9, 21]})
    df.to_parquet("/tmp/repairs.parquet")
    back = pd.read_parquet("/tmp/repairs.parquet")
    return {
        "rows": len(back),
        "total_repairs": int(back["count"].sum()),
        "pandas": pd.__version__,
        "pyarrow": pyarrow.__version__,
    }

The real one reads the day's files from S3 instead of building three rows, but the libraries are the same. Here's what they come to, measured for the python3.13 runtime on x86_64, in October 2026:

What's in the packageUnzippedAgainst 250 MB
pandas 3.0.6 + pyarrow 26.0.0 + numpy 2.5.4, as pip installs them in the Lambda image294.2 MB44.2 MB over
Same, installed by a Python 3.14 laptop for Python 3.13296.6 MB46.6 MB over, 44.6 MB of it bytecode Lambda can't use
Same, without tests folders, keeping bytecode243.2 MB6.8 MB left
Same, without tests or __pycache__230.4 MB19.6 MB left
pandas + numpy only, no pyarrow, trimmed the same way72.5 MB177.5 MB left
The AWS SDK for pandas layer (pandas, pyarrow, numpy and more), version 3.17.1186.6 MB63.4 MB left for your code

Two things stand out. First, pyarrow is the giant: 157.9 MB even after trimming. pandas 3 doesn't require it; you need it for Parquet files, as Ethan does. If your function only reads CSV or JSON, removing pyarrow from your requirements is the single biggest cut there is.

Second, about 64 MB of the original 294.2 MB is test suites and bytecode, and your function needs neither. That's the part to cut first, because it costs you nothing.

Jake: "Two libraries, and the box is already full."

Ethan: "Full of their homework, mostly. pandas ships its whole test suite. Lambda never opens it."

Shrink a Python package: the four cuts that matter

Here's the whole recipe, start to finish; the sections below explain each step:

  1. List your libraries in requirements.txt, one per line.
  2. Install them into a package folder inside the Lambda image, so pip picks Linux builds for Lambda's Python.
  3. Build the zip with build_zip.py, which leaves out tests and __pycache__ folders.
  4. Check the result with lambda_size.py, adding any layers the function uses.
  5. Upload the zip through S3 if it's over 50 MB.

If it's still over 250 MB, the cuts below go further. Measure after each one; most functions fit after the second.

1. Install inside the Lambda image, not on your laptop

Your laptop's pip picks packages for your laptop: Windows or macOS builds, your Python version, your processor. Lambda needs Linux builds for its Python. The simplest way to get exactly that is to let pip run inside AWS's own Lambda image, with Docker:

docker run --rm --platform linux/amd64 -v "$PWD":/work -w /work --entrypoint pip public.ecr.aws/lambda/python:3.13 install -r requirements.txt --target package

In PowerShell on Windows, write the folder part as -v "${PWD}:/work". Use --platform linux/arm64 instead if your function runs on arm64 (Graviton). This matters on a Mac with Apple silicon, where Docker would otherwise hand you arm64 packages for an x86_64 function, and you'd trade this error for "Unable to import module," which our import error guide untangles.

This also gets the bytecode right. pip compiles every .py file into a .pyc for the Python that runs it, and here that's the runtime's own Python 3.13.

No Docker? Use pip's platform options, with the right tag

pip install --platform manylinux_2_28_x86_64 --implementation cp --python-version 3.13 --only-binary=:all: --no-compile --target package -r requirements.txt

Watch the platform tag. The command you'll find in most Lambda packaging guides uses manylinux2014_x86_64, and with today's data libraries that has a quiet side effect: the newest pandas, pyarrow and numpy publish Linux builds only under newer tags such as manylinux_2_28, so pip skips them without a word and installs old releases instead. With the 2014 tag, Ethan got pandas 2.3.2 (August 2025), pyarrow 20.0.0 (April 2025) and numpy 2.2.6 (May 2025). With manylinux_2_28_x86_64, he got pandas 3.0.6, pyarrow 26.0.0 and numpy 2.5.4.

Which tag is right depends on the runtime's operating system:

  • python3.12, python3.13, python3.14 and python3.15 run on Amazon Linux 2023 (glibc 2.34): use manylinux_2_28_x86_64 or manylinux_2_28_aarch64.
  • python3.11 and python3.10 run on Amazon Linux 2 (glibc 2.26): stay with manylinux2014_x86_64. The newest builds won't load there, so the older releases are the right ones. Our GLIBC_2.28 guide explains why.

The --no-compile flag matters here too. Without it, pip compiles bytecode with your laptop's Python, not Lambda's. On a laptop with Python 3.14 building for Python 3.13, that was 44.6 MB of cpython-314 files that Lambda's Python 3.13 skips every time.

2. Leave out tests and bytecode when you zip

Rather than deleting files from your install folder, leave them out of the zip. This script builds the zip from the package folder and your handler, skipping every tests folder and every __pycache__ folder, and, if you ask it to, the AWS SDK. Save it as build_zip.py:

import argparse
import os
import zipfile

ALREADY_IN_LAMBDA = ("boto3", "botocore", "s3transfer", "jmespath")
SKIP_DIRS = {"tests", "__pycache__"}

ap = argparse.ArgumentParser()
ap.add_argument("package", help="folder that pip installed into")
ap.add_argument("handler", help="your function file, e.g. lambda_function.py")
ap.add_argument("output", help="zip to create, e.g. function.zip")
ap.add_argument("--skip-boto3", action="store_true", help="leave out the SDK the runtime already has")
args = ap.parse_args()

total = os.path.getsize(args.handler)
with zipfile.ZipFile(args.output, "w", zipfile.ZIP_DEFLATED, compresslevel=9) as z:
    z.write(args.handler, os.path.basename(args.handler))
    for root, dirs, files in os.walk(args.package):
        dirs[:] = [d for d in dirs if d not in SKIP_DIRS
                   and not (args.skip_boto3 and root == args.package
                            and d.lower().startswith(ALREADY_IN_LAMBDA))]
        for name in files:
            path = os.path.join(root, name)
            z.write(path, os.path.relpath(path, args.package))
            total += os.path.getsize(path)

print(f"{args.output}: {total / 1_048_576:.1f} MB unzipped (limit 250.0 MB with layers)")
print(f"zipped: {os.path.getsize(args.output) / 1_048_576:.1f} MB")
python3 build_zip.py package lambda_function.py function.zip
function.zip: 230.4 MB unzipped (limit 250.0 MB with layers)
zipped: 72.5 MB

From 294.2 MB to 230.4 MB, and the function ran exactly as before: it imported pandas and pyarrow, wrote a Parquet file to /tmp and read it back.

Why leave out bytecode even when it was compiled for the right Python? Bytecode built on another machine may not match Lambda's Python at all, and even when it does, there are two more reasons. It's 12.8 MB here, which you may need. And Python only trusts a .pyc file when the source file's timestamp still matches the one recorded inside it; a zip made with Python's own zipfile rounds timestamps to two seconds, so after unzipping, much of the bytecode is treated as out of date and compiled again anyway. Without bytecode, Python compiles your libraries in memory at each cold start, which makes that first start a little slower. If cold starts matter more to you than size, the container image keeps bytecode working.

3. Drop pyarrow if you don't read Parquet

Take it out of requirements.txt and rebuild. pandas and numpy alone came to 72.5 MB trimmed, against 230.4 MB with pyarrow. If you need Parquet only now and then, a separate function with the pandas layer can do that part.

4. Leave out boto3, if you're squeezed

Every Lambda Python runtime includes boto3, botocore and their helpers s3transfer and jmespath. If boto3 is in your package, perhaps because it's in your requirements.txt for local testing, it's about 21 MB, and build_zip.py --skip-boto3 leaves it out. It's a trade-off, not a free cut. Your function then uses whatever boto3 the runtime has, which Lambda updates over time and which can lag behind the newest release. And if your package carries some of the SDK's own dependencies, such as urllib3, which the requests library also installs, a runtime update can leave the two at mismatched versions and break the function. With room to spare, keep boto3 in the package for full control; when you're 20 MB over, it's a reasonable cut to make.

Jake: "So you didn't delete anything. You just stopped packing it."

Ethan: "Exactly. My laptop still has the tests if I ever want them. The zip only gets what the function uses."

Zip over 50 MB? Upload through S3 (it fixes a different error)

Ethan's trimmed zip is 72.5 MB: under the 250 MB unzipped limit, but over the 50 MB limit for uploading a zip directly. A direct upload that big fails with RequestEntityTooLargeException. The 50 MB is approximate, because the CLI and SDKs send the zip base64-encoded, which makes it about 30% bigger, and Lambda allows for that.

The fix is to put the zip in an S3 bucket in the same Region as the function, then point Lambda at it:

aws s3 cp function.zip s3://jake-shop-deploy/repairs-report/function.zip

aws lambda update-function-code --function-name repairs-report \
  --s3-bucket jake-shop-deploy --s3-key repairs-report/function.zip

This is the part that trips people up: S3 is the answer to the 50 MB upload limit only. It does nothing for the 250 MB unzipped limit, which Lambda checks after it fetches the zip, wherever it came from. If you see "Unzipped size must be smaller than 262144000 bytes" after switching to S3, you're seeing the limit S3 was never going to fix.

And if your "too large" error comes from invoking the function rather than deploying it, that's a different limit again: 6 MB for the data going in or out of a synchronous call. Our payload guide covers that one.

Layers don't add room: they share the 250 MB

A common first idea is to move the big libraries into a Lambda layer. Layers are a good way to share libraries between functions and to keep your own zip small and quick to upload, but they don't add space. A function can have up to five layers, and the function plus all its layers must fit in 250 MB unzipped. Moving pandas into a layer moves it, it doesn't shrink it.

If you do build your own layer, Python libraries go in a python folder at the top of the zip, and Node.js libraries in nodejs/node_modules. Upload it through S3 if it's over 50 MB, then attach it:

aws lambda publish-layer-version --layer-name pandas-pyarrow \
  --content S3Bucket=jake-shop-deploy,S3Key=layers/pandas-pyarrow.zip \
  --compatible-runtimes python3.13 --compatible-architectures x86_64

aws lambda update-function-configuration --function-name repairs-report \
  --layers arn:aws:lambda:us-east-1:111122223333:layer:pandas-pyarrow:1

Pass every layer the function needs in that --layers list, in the order Lambda should merge them.

The ready-made layer for pandas

For pandas and pyarrow specifically, AWS publishes a layer you can attach without building anything: the AWS SDK for pandas layer. Its version 3.17.1 for Python 3.13 on x86_64 is 186.6 MB unzipped and contains pandas 3.0.5, pyarrow 24.0.0 and numpy 2.5.1, plus database and file-format helpers, leaving 63.4 MB for your own code and any other layer. In us-east-1 it's:

arn:aws:lambda:us-east-1:336392948345:layer:AWSSDKPandas-Python313:16

The account number and the layer name stay the same across Regions; swap the Region, use -Arm64 at the end of the name for arm64 functions, and check the version number for your Region on the AWS SDK for pandas "Lambda Managed Layers" page, because it changes with each release. Ethan's function ran with only lambda_function.py in its zip and this layer attached.

Jake: "So a layer is like keeping the tools in the van instead of the toolbox. The van still has a weight limit."

Ethan: "Same truck, same limit. It just means you don't have to pack it every time."

Node.js: devDependencies and bundling

Node.js packages go over the limit for a different reason: everything in node_modules gets zipped, including the tools you only use on your own machine. Here's a small function that uses the S3 and DynamoDB clients and zod, measured three ways:

What's in the packageSize
npm install, with devDependencies (TypeScript, Jest, esbuild, aws-cdk-lib)247.0 MB, of which aws-cdk-lib alone is 134.6 MB
npm ci --omit=dev18.5 MB
One file bundled by esbuild, AWS SDK left to the runtime0.7 MB
One file bundled by esbuild, AWS SDK included, minified1.0 MB

The first cut is the obvious one. Install only what runs:

npm ci --omit=dev

Check that build tools such as aws-cdk-lib, typescript and test frameworks are listed under devDependencies in package.json, not dependencies; anything under dependencies gets packed.

The bigger cut is bundling: esbuild follows your imports and writes only the code you use into one file, so node_modules doesn't go in the zip at all. Install as usual with npm ci, since esbuild itself is a devDependency, then build. Every Node.js Lambda runtime already includes version 3 of the AWS SDK for JavaScript, so you can leave the @aws-sdk packages out of the bundle entirely:

npx esbuild index.mjs --bundle --platform=node --target=node22 --format=cjs --external:@aws-sdk/* --outfile=dist/index.js

Then zip the dist folder's contents and set the handler to index.handler. As with boto3, the runtime's SDK can trail the newest release; to ship your own, drop --external:@aws-sdk/* and add --minify, which still came to just 1.0 MB.

The bundling trap: "Dynamic require of "node:https" is not supported"

Notice --format=cjs in that command. If you bundle the AWS SDK into an ES module instead, with --format=esm and an .mjs output, the function fails as soon as it loads:

{"errorType":"Error","errorMessage":"Dynamic require of \"node:https\" is not supported"}

Parts of the SDK load Node's built-in modules with require(), and an ES module bundle has no require. Bundling to CommonJS, as above, avoids it, and your source files can stay ES modules. If you use the runtime's SDK with --external:@aws-sdk/*, the ESM bundle worked too, because those packages are never inside it. Our ES module guide covers the other require errors.

Still over 250 MB? Switch to a container image (10 GB)

When the libraries you need are simply big, such as machine learning frameworks, browsers for scraping, or pandas plus everything else, stop trimming. A Lambda function packaged as a container image can be 10 GB, forty times the zip limit, and you build it with the same requirements file:

FROM public.ecr.aws/lambda/python:3.13

COPY requirements.txt ${LAMBDA_TASK_ROOT}
RUN pip install --no-cache-dir -r requirements.txt --target "${LAMBDA_TASK_ROOT}"

COPY lambda_function.py ${LAMBDA_TASK_ROOT}

CMD [ "lambda_function.lambda_handler" ]

Ethan's image, with the full untrimmed pandas and pyarrow, was 874 MB, base image included: nowhere near 10 GB, with no script and no cuts. The move takes five steps:

  1. Build the image for your function's architecture.
  2. Run it on your own machine and invoke it once.
  3. Push it to a repository in Amazon ECR.
  4. Create a new function from the image.
  5. Point your trigger or schedule at the new function.

Build it, then test it on your own machine before uploading. AWS base images include a local copy of the Lambda runtime API, so a curl runs the function just as Lambda would:

docker buildx build --platform linux/amd64 --provenance=false -t repairs-report:latest .

docker run --rm -p 9000:8080 repairs-report:latest

curl -s "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'
{"rows": 3, "total_repairs": 44, "pandas": "3.0.6", "pyarrow": "26.0.0"}

Run the curl in a second terminal while the container runs. If you use Podman instead of Docker, drop --provenance=false, which Podman doesn't have, and build with podman build --platform linux/amd64 -t repairs-report:latest .; the run and curl steps are the same. With Docker, --provenance=false is required, because Lambda doesn't accept the extra metadata that Docker's builder adds by default, and Lambda doesn't accept multi-architecture images either, which is what --platform prevents. Then push the image to Amazon ECR and create the function from it:

aws ecr create-repository --repository-name repairs-report

aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 111122223333.dkr.ecr.us-east-1.amazonaws.com

docker tag repairs-report:latest 111122223333.dkr.ecr.us-east-1.amazonaws.com/repairs-report:latest
docker push 111122223333.dkr.ecr.us-east-1.amazonaws.com/repairs-report:latest

aws lambda create-function --function-name repairs-report-image \
  --package-type Image \
  --code ImageUri=111122223333.dkr.ecr.us-east-1.amazonaws.com/repairs-report:latest \
  --role arn:aws:iam::111122223333:role/repairs-report-role \
  --memory-size 1024 --timeout 60

One rule catches everyone the first time: you can't switch an existing function between zip and image. It has to be a new function, which is why the name above is different. Point your trigger or schedule at the new one and delete the old one when you're happy.

And mind the memory. Importing pandas and pyarrow and writing a three-row Parquet file peaked at 127 MB, right at Lambda's default of 128 MB, so give data functions far more; 1,024 MB is a comfortable start, and more memory also means more CPU. If you've already seen "Runtime exited with signal: killed," our memory guide walks through it.

Jake: "So why not use the image every time?"

Ethan: "It's more moving parts: a registry, a build step, pushing images. For a function that fits in a zip, the zip is simpler. For pandas, I'd pick the image."

Big models and data files: EFS or /tmp, not the package

Sometimes the big thing isn't a library but a file: a machine learning model, a dictionary, a large lookup table. Don't put those in the package at all:

  • Amazon EFS mounts a shared file system into the function at a path starting with /mnt/. The function has to be connected to the same VPC as the file system, and its security groups must allow NFS on port 2049. Files on EFS don't count toward any package limit.
  • S3 plus /tmp: download the file from S3 into /tmp at cold start and reuse it while the environment stays warm. /tmp can be set anywhere from 512 MB to 10,240 MB.
  • Amazon S3 Files is a newer option that mounts an S3 bucket as a file system, with the same VPC requirement. A function can use EFS or S3 Files, not both.

Which fix should you pick?

Your situationBest fix
Over by a little, PythonInstall in the Lambda image, then build_zip.py to leave out tests and bytecode
Over by a little, Node.jsnpm ci --omit=dev, then an esbuild bundle
pandas and pyarrow, small code of your ownThe AWS SDK for pandas layer, or the trimmed zip through S3
Over by a lot, or big libraries keep growingA container image (10 GB)
A large model or data fileEFS, or download from S3 into /tmp
Zip over 50 MB but under 250 MB unzippedUpload through S3

Leave some room either way. Libraries grow with every release, and a function that fits with 2 MB to spare today is next month's emergency.

Troubleshooting by symptom

The zip is far under 250 MB, but deploying fails

Lambda checks the unzipped size, and libraries often unzip to about three times their zip size. Run zipinfo -t function.zip, and add every attached layer.

It still fails after uploading through S3

S3 only fixes the 50 MB upload limit. The 250 MB unzipped limit applies wherever the zip comes from.

Moving libraries into a layer didn't help

Layers share the same 250 MB with your code. Trim the libraries, use a smaller set, or switch to a container image.

pip installed old versions of pandas or numpy

The manylinux2014 platform tag excludes the newest releases. For python3.12 and later, use --platform manylinux_2_28_x86_64, or install inside the Lambda image.

"Unable to import module" after trimming

Either something you removed is used at runtime, or the packages were built for the wrong system. Rebuild inside the Lambda image with the function's architecture and check the handler setting.

"Dynamic require of "node:https" is not supported"

You bundled the AWS SDK into an ES module. Bundle with --format=cjs, or keep the SDK external with --external:@aws-sdk/*.

RequestEntityTooLargeException on update-function-code

The zip is over the 50 MB direct upload limit. Upload it to S3 and pass --s3-bucket and --s3-key instead of --zip-file.

Lambda package size limit: frequently asked questions

What does "Unzipped size must be smaller than 262144000 bytes" mean?

Your Lambda function's code, unzipped, plus all its layers, is over 250 MB (262,144,000 bytes). The zip file's size doesn't matter for this check. Remove unused files and libraries, or deploy the function as a container image, which allows 10 GB.

What is the maximum deployment package size for AWS Lambda?

50 MB zipped for a direct upload through the console, CLI or SDK, 250 MB unzipped for the code plus all layers, and 10 GB for a container image. Zips over 50 MB can be uploaded through S3, but must still fit in 250 MB unzipped.

Can I increase the Lambda 250 MB limit?

No. The 250 MB unzipped limit can't be raised. If your function needs more, package it as a container image, which can be up to 10 GB, or keep large files on EFS or in S3.

Do Lambda layers count toward the 250 MB limit?

Yes. The function's unzipped code and all its layers together must stay under 250 MB, and a function can have at most five layers. Moving libraries into a layer doesn't create more room.

What is the Lambda layer size limit?

A layer follows the same rules as function code: 50 MB zipped for a direct upload, larger through S3, and the function plus all its layers must fit in 250 MB unzipped.

Does uploading the zip to S3 avoid the 250 MB limit?

No. S3 avoids the 50 MB direct upload limit only. Lambda still unzips the package and checks the 250 MB limit, wherever the zip came from.

How do I check the unzipped size of a Lambda zip?

Run zipinfo -t function.zip on Linux or macOS and read the bytes uncompressed. On Windows, sum the file_size of every entry with Python's zipfile module. Add the unzipped size of every attached layer.

Why is pandas too big for Lambda?

pandas, numpy and especially pyarrow ship large compiled libraries plus their own test suites. Together they take about 294 MB for Python 3.13, over the 250 MB limit before your own code.

How do I make pandas fit in a Lambda zip?

Install it inside the Lambda Python image, leave out the tests and __pycache__ folders, and drop pyarrow if you don't need Parquet. Or attach the AWS SDK for pandas layer, or use a container image.

Is boto3 already included in AWS Lambda?

Yes. Every Lambda Python runtime includes boto3 and botocore. Packaging your own gives you control of the version; leaving it out saves about 21 MB, but your function then uses the runtime's copy, which Lambda updates over time.

Is the AWS SDK included in the Lambda Node.js runtime?

Yes. All supported Node.js runtimes include version 3 of the AWS SDK for JavaScript. Mark @aws-sdk packages as external when bundling to leave them out of your package.

How do I reduce node_modules size for Lambda?

Install with npm ci --omit=dev so devDependencies stay out, and bundle the function with esbuild so only the code you import is packaged. A function that was 247 MB with devDependencies bundled to under 1 MB.

How do I install Python packages for AWS Lambda?

Install them into a folder with pip, inside the public.ecr.aws/lambda/python image for your runtime, or with pip's --platform, --python-version and --only-binary=:all: options. Then zip that folder with your handler at the top level.

Which manylinux platform should I use for Lambda?

manylinux_2_28 for python3.12 and later, which run on Amazon Linux 2023. manylinux2014 for python3.11 and python3.10, which run on Amazon Linux 2. The 2014 tag on newer runtimes can install old releases.

What is the container image size limit for Lambda?

10 GB, uncompressed, including all the image's layers. Images live in Amazon ECR, and you create the function with --package-type Image.

Can I convert a zip Lambda function to a container image?

No. You can't change an existing function's package type. Create a new function from the image, then move your triggers to it.

What does RequestEntityTooLargeException mean when deploying Lambda?

Usually the zip you uploaded directly is over the 50 MB limit. Upload it to S3 and deploy with --s3-bucket and --s3-key. The same exception can come from environment variables over 4 KB.

How big can /tmp be in Lambda?

Between 512 MB and 10,240 MB, set in the function's ephemeral storage. It's scratch space for files while the function runs and doesn't count toward the package size limit.

πŸ“š ALSO READ

Where to go next, from import errors after trimming to the other Lambda limits that catch people:

📌 Bookmark this; the size tables and the two scripts apply to every Python and Node.js function.

Ethan shipped the nightly report as a zip in the end: pandas and pyarrow installed inside the Lambda image, packed with build_zip.py at 230.4 MB, uploaded through S3, with the memory set to 1,024 MB. The first report reached Jake's inbox at 6:05 the next morning. He also wrote the size check into the deploy script, so the build stops on his laptop, with a list of the biggest folders, long before Lambda has a chance to say 262,144,000 again.

📌 If you keep one line from this page

Lambda's 250 MB counts everything unzipped, your code plus every layer; measure it first, leave out tests and bytecode, and when the libraries are simply too big, stop trimming and ship a container image.

50 MB = zipped upload (use S3) · 250 MB = code plus layers, unzipped · 10 GB = container image.

Revision note. Written October 13, 2026, for every deploy stopped at 250 MB. "Small drops make a flood," says a Tamil proverb; in a Lambda package, the drops are test folders and bytecode nobody runs.

Related