Stages in Serverless Framework
Serverless Framework allows you to create stages for your project to deploy to. Stages are useful for creating environments for testing and development. Typically you create a staging environment that is an independent clone of your production environment. This allows you to test and ensure that the version of code that you are about to deploy is good to go.
In this chapter we will take a look at how to configure stages in serverless. Let’s first start by looking at how stages can be implemented.
How Is Staging Implemented?
There are a couple of ways to set up stages for your project:
-
Using the API Gateway built-in stages
You can create multiple stages within a single API Gateway project. Stages within the same project share the same endpoint host, but have a different path. For example, say you have a stage called
prod
with the endpoint:https://abc12345.execute-api.us-east-1.amazonaws.com/prod
If you were to add a stage called
dev
to the same API Gateway API, the new stage will have the endpoint:https://abc12345.execute-api.us-east-1.amazonaws.com/dev
The downside is that both stages are part of the same project. You don’t have the same level of flexibility to fine tune the IAM policies for stages of the same API, when compared to tuning different APIs. This leads to the next setup, each stage being its own API.
-
Separate APIs for each stage
You create an API Gateway project for each stage. Let’s take the same example, your
prod
stage has the endpoint:https://abc12345.execute-api.us-east-1.amazonaws.com/prod
To create the
dev
stage, you create a new API Gateway project and add thedev
stage to the new project. The new endpoint will look something like:https://xyz67890.execute-api.us-east-1.amazonaws.com/dev
Note that the
dev
stage carries a different endpoint host since it belongs to a different project. This is the approach Serverless Framework takes when configuring stages for your Serverless project. We will look at this in detail below. -
Separate AWS account for each stage
Just like how having each stage being separate APIs give us more flexibility to fine tune the IAM policy. We can take it a step further and create the API project in a different AWS account. Most companies don’t keep their production infrastructure in the same account as their development infrastructure. This helps reduce any cases where developers accidentally edit/delete production resources. We go in to more detail on how to deploy to multiple AWS accounts using different AWS profiles in the Configure Multiple AWS Profiles chapter.
Deploying to a Stage
Let’s look at how the Serverless Framework helps us work with stages. As mentioned above, a new stage is a new API Gateway project. To deploy to a specific stage, you can either specify the stage in the serverless.yml
.
service: service-name
provider:
name: aws
stage: dev
Or you can specify the stage by passing the --stage
option to the serverless deploy
command.
$ serverless deploy --stage dev
Stage Variables in Serverless Framework
Deploying to stages can be pretty simple but now let’s look at how to configure our environment variables so that they work with our various stages. We went over the concept of environment variables in the chapter on Serverless Environment Variables. Let’s extend that to specify variables based on the stage we are deploying to.
Let’s take a look at a sample serverless.yml
below.
service: service-name
custom:
myStage: ${opt:stage, self:provider.stage}
myEnvironment:
MESSAGE:
prod: "This is production environment"
dev: "This is development environment"
provider:
name: aws
stage: dev
environment:
MESSAGE: ${self:custom.myEnvironment.MESSAGE.${self:custom.myStage}}
There are a couple of things happening here. We first defined the custom.myStage
variable as ${opt:stage, self:provider.stage}
. This is telling Serverless Framework to use the --stage
CLI option if it exists. And if it does not, then use the default stage specified by provider.stage
. We also define the custom.myEnvironment
section. This contains the value for MESSAGE
defined for each stage. Finally, we set the environment variable MESSAGE
as ${self:custom.myEnvironment.MESSAGE.${self:custom.myStage}}
. This sets the variable to pick the value of self:custom.myEnvironment
depending on the current stage defined in custom.myStage
.
You can easily extend this format to create separate sets of environment variables for the stages you are deploying to.
And we can access the MESSAGE
in our Lambda functions via process.env
object like so.
export function main(event, context, callback) {
callback(null, { body: process.env.MESSAGE });
}
Hopefully, this chapter gives you a quick idea on how to set up stages in your Serverless project.
For help and discussion
Comments on this chapter