The question of whether to install dependencies for an SLS (Serverless) package is a frequent point of discussion and sometimes confusion for developers venturing into serverless architectures. Understanding this fundamental aspect is crucial for efficient deployment, scalable applications, and robust performance. This article delves into the intricacies of dependency management within the Serverless Framework, examining why and when dependencies are necessary, how they are handled, and the implications of different approaches.
Understanding Serverless Packages and Dependencies
At its core, a Serverless Framework deployment package is essentially a collection of code, configuration, and any other resources required for your function or service to run within a serverless environment. When you write code for a serverless function, such as a Node.js Lambda function, it’s highly probable that you’ll be leveraging external libraries or modules to simplify development, add functionality, or adhere to best practices. These external pieces of code are known as dependencies.

For instance, if you’re building a web API using Node.js, you might use the express framework for routing and request handling. You might also use libraries like aws-sdk to interact with other AWS services, lodash for utility functions, or axios for making HTTP requests. All of these are dependencies of your application.
The Serverless Framework, when packaging your service for deployment, needs to ensure that all these dependencies are present in the deployment artifact. Without them, your code would fail to execute because it wouldn’t be able to find and load the required modules. The question, therefore, isn’t whether dependencies are needed conceptually, but rather how they are managed and included in the final package.
What Constitutes a Dependency?
Dependencies can be broadly categorized:
- Runtime Dependencies: These are libraries and modules that your application code directly calls at runtime. Examples include frameworks (Express, Flask), SDKs (AWS SDK, Google Cloud Client Libraries), utility libraries (Lodash, Moment.js), and data manipulation tools (Pandas, NumPy).
- Development Dependencies: These are libraries and tools used during the development and build process but are not required for the application to run in production. Examples include testing frameworks (Jest, Pytest), linters (ESLint, Pylint), and bundlers (Webpack, Parcel). The Serverless Framework, by default, aims to exclude development dependencies from the final deployment package to minimize its size.
The Serverless Framework’s packaging mechanism intelligently handles these by default, aiming to include only what is necessary for execution in the cloud environment.
The Role of the Serverless Framework in Dependency Management
The Serverless Framework provides a sophisticated yet user-friendly system for managing dependencies. When you define your service in the serverless.yml file, you specify your function code, its runtime, and often, the way your dependencies should be bundled. The framework then orchestrates the process of gathering these dependencies and packaging them with your code.
Automatic Packaging
For many common runtimes, like Node.js and Python, the Serverless Framework has built-in support for automatically packaging dependencies.
Node.js Example: serverless.yml Configuration
In a Node.js project, you would typically manage your dependencies using npm or yarn. After installing them (npm install or yarn install), these dependencies reside in the node_modules directory. When you deploy using the Serverless Framework, it inspects your project, identifies the node_modules directory, and includes its contents in the deployment package.
service: my-node-service
provider:
name: aws
runtime: nodejs18.x
functions:
hello:
handler: handler.hello
# No explicit dependency declaration needed here for automatic bundling
In this scenario, if your handler.js file imports a module from node_modules, the Serverless Framework will automatically zip the necessary files from node_modules into your deployment artifact. This automatic inclusion is a convenience that significantly streamlines the development workflow.
Python Example: serverless.yml Configuration
For Python, the Serverless Framework can work with a requirements.txt file.
service: my-python-service
provider:
name: aws
runtime: python3.9
functions:
process:
handler: handler.process
package:
# This tells the framework to look for dependencies in requirements.txt
individually: true # Often used for finer-grained control
# Or simply let the framework discover from node_modules/vendor/
When you run pip install -r requirements.txt, the packages are installed. The Serverless Framework, particularly when configured with certain plugins or through its default behavior for Python, will then package these installed libraries, often into a vendor directory, alongside your function code.
Manual Inclusion and Advanced Scenarios
While automatic packaging is convenient, there are scenarios where more control is desired or necessary. This might include:
- Optimizing Package Size: For functions with many dependencies, the
node_modulesor Python site-packages can become quite large, increasing deployment time and potentially hitting size limits. Techniques like pruning unused dependencies or using bundlers become important. - Custom Build Steps: Some dependencies require compilation or specific build processes that the default packaging might not handle correctly.
- Cross-Platform Dependencies: Dealing with dependencies that have native extensions can be tricky, as they need to be compiled for the target deployment environment (e.g., Amazon Linux for AWS Lambda).
In these cases, developers might employ specific plugins or configure the packaging process more granularly.

Plugins for Enhanced Packaging
The Serverless Framework ecosystem is rich with plugins that extend its functionality. For dependency management, plugins like serverless-webpack for Node.js or serverless-python-requirements for Python offer advanced features:
serverless-webpack: This plugin integrates Webpack into the Serverless Framework build process. Webpack is a module bundler that can perform tree-shaking (removing unused code), code splitting, and transpilation, all of which contribute to smaller and more optimized deployment packages. It effectively bundles all your code and dependencies into a single, or a few, JavaScript files.serverless-python-requirements: This plugin automates the process of installing Python dependencies fromrequirements.txtand packaging them. It can also handle dependencies with native extensions by building them against the target Lambda environment’s architecture and operating system, avoiding common compatibility issues.
When using such plugins, the serverless.yml configuration would change to reflect their usage:
# Example with serverless-webpack
plugins:
- serverless-webpack
- serverless-dotenv-plugin # Example of another plugin
custom:
webpack:
webpackConfig: webpack.config.js # Path to your Webpack configuration
includeModules: true # Ensure node_modules are included/processed
functions:
hello:
handler: handler.hello
# Example with serverless-python-requirements
plugins:
- serverless-python-requirements
custom:
pythonRequirements:
dockerizePip: true # Crucial for handling dependencies with native extensions
layer: true # Option to package dependencies as a Lambda Layer
In these configurations, the plugins take over the responsibility of inspecting your package.json (or requirements.txt), resolving dependencies, and performing the necessary bundling or packaging steps before the Serverless Framework creates the final deployment artifact.
Lambda Layers: A Key Dependency Management Strategy
One of the most significant advancements in serverless dependency management is the introduction of Lambda Layers. Lambda Layers allow you to decouple libraries and dependencies from your function code. This offers several advantages:
- Reduced Deployment Package Size: By placing common dependencies into a Lambda Layer, your individual function deployment packages become much smaller, leading to faster deployments.
- Code Reusability: Multiple functions can share the same Lambda Layer, promoting consistency and reducing redundant packaging.
- Simplified Updates: Updating a shared library only requires updating the Lambda Layer, and all functions that use it will automatically benefit from the update without needing to be redeployed themselves.
The Serverless Framework supports Lambda Layers directly in its configuration.
Configuring Lambda Layers
To use a Lambda Layer for dependencies, you would typically:
- Install your dependencies locally.
- Configure a plugin (like
serverless-python-requirementswithlayer: true) or manually structure your dependencies into a format compatible with Lambda Layers. - Define the Lambda Layer in your
serverless.yml. - Attach the Lambda Layer to your functions.
# Example of packaging dependencies into a layer with serverless-python-requirements
plugins:
- serverless-python-requirements
custom:
pythonRequirements:
dockerizePip: true
layer: true # This tells the plugin to create a Lambda Layer
functions:
process:
handler: handler.process
layers:
- ${cf:my-layers-stack-name.MyPythonLayerArn} # Referencing a layer from another stack
# Or if the layer is defined within the same service:
# - !Ref PythonDependenciesLambdaLayer
# Defining the layer within the same service (if not managed by a separate stack)
resources:
Resources:
PythonDependenciesLambdaLayer:
Type: AWS::Lambda::LayerVersion
Properties:
LayerName: python-dependencies
Content:
ZipFile: |
# Zip file content or S3 location for the layer
CompatibleRuntimes:
- python3.9
This approach is particularly beneficial for larger projects with many functions that share common external libraries, such as SDKs or data processing libraries. It significantly streamlines maintenance and improves deployment efficiency.
When Dependencies ARE Installed for SLS Package
To reiterate and clarify, dependencies are almost always a part of the final deployed artifact for your serverless function, unless specific advanced techniques are employed to exclude them or manage them separately (like Lambda Layers). The “installation” happens in the context of preparing the package for deployment.
- During Development: You install dependencies locally using package managers (
npm,yarn,pip) to make your code runnable and testable on your development machine. - During Packaging: The Serverless Framework or its associated plugins scan your project, locate these installed dependencies, and bundle them. This bundling can take various forms:
- Copying the
node_modulesdirectory (Node.js default). - Copying Python packages from a
site-packagesorvendordirectory. - Bundling everything into one or a few files using tools like Webpack.
- Creating a Lambda Layer archive.
- Copying the
The key is that the contents of your dependencies must be present in the zip file uploaded to the serverless platform (e.g., AWS Lambda) for your function to execute correctly.

Best Practices for Dependency Management
To ensure smooth deployments and maintainable serverless applications, consider these best practices:
- Minimize Dependencies: Only include libraries that are strictly necessary. Every dependency adds to the package size and potential attack surface.
- Use Version Pinning: In your
package.jsonorrequirements.txt, pin dependency versions (e.g.,express: "^4.17.1"orrequests==2.28.1) to ensure reproducible builds and prevent unexpected behavior from automatic updates. - Leverage Lambda Layers: For common dependencies shared across multiple functions, Lambda Layers are highly recommended to optimize package size and simplify updates.
- Use Bundlers for Node.js: Employ tools like Webpack with the
serverless-webpackplugin to create highly optimized, smaller bundles for Node.js functions. - Dockerize Python Requirements: If using Python, always use
dockerizePip: truewithserverless-python-requirementsto ensure dependencies with native extensions are built correctly for the Lambda environment. - Regularly Audit Dependencies: Periodically review your dependencies for security vulnerabilities and outdated versions. Tools like
npm auditorsnykcan be integrated into your CI/CD pipeline. - Understand the Packaging Process: Familiarize yourself with how the Serverless Framework and any used plugins package your code and dependencies. This understanding is crucial for troubleshooting deployment issues.
By adhering to these practices, you can effectively manage dependencies, leading to more efficient, secure, and scalable serverless applications. The Serverless Framework, with its flexible plugin architecture, provides the tools to achieve this, transforming the complexity of dependency management into a manageable and integral part of your serverless development lifecycle.
