zip for AWS Lambda Deployment Packages
An AWS Lambda deployment package is a zip whose handler file and dependencies sit at the archive root with correct file permissions.
Lambda has specific layout and permission expectations for the zip you upload. Getting the structure or the exec bits wrong is a common cause of "handler not found" and permission errors.
What it does
Lambda unpacks the deployment zip into the function root and looks for the handler at the path you configured (for example index.handler expects index.js or index.py at the top level). Files must be readable, and any executables or binaries must keep their execute permission. The handler and dependencies live at the archive root, not inside a wrapping folder.
Common usage
# build from inside the package dir so paths are at the root
cd package
zip -r ../function.zip . -x '*.git*'
cd -
# verify the handler is at the top level
unzip -l function.zip | grep -E '^.*index\.(js|py)$'Layout requirements
| Requirement | Why it matters |
|---|---|
| Handler at archive root | Lambda resolves index.handler against the root |
| Dependencies included | node_modules or site-packages must be in the zip |
| Execute bit on binaries | Native executables need exec permission preserved |
| Readable files (chmod) | Lambda must be able to read every file |
| No wrapping top-level folder | Do not zip the parent dir, zip its contents |
In CI
Build the zip from inside the package directory (cd package && zip -r ../function.zip .) so the handler ends up at the root rather than nested under package/. The Info-ZIP zip on Linux preserves Unix permission bits, so an executable stays executable; building the zip on a system that drops permissions can cause runtime permission errors. Set permissions with chmod before zipping if needed.
Common errors in CI
A function that fails with "Unable to import module" or handler-not-found usually has the handler nested one folder too deep because the parent directory was zipped instead of its contents. "permission denied" at runtime means a binary lost its execute bit, often because the zip was built on a system that does not store Unix permissions (such as some Windows tools). Use -j by accident and you flatten away the required layout, so avoid it for Lambda packages.