BETA: This repository contains a beta version of a new Serverless Framework feature.
Deploy and orchestrate multiple Serverless Framework services in monorepositories.
- Deploy multiple services in parallel
- Deploy dependent services in a specific order
- Share outputs from one service to another
- Run commands across multiple services
name: myapp
services:
subscriptions:
path: subscriptions
users:
path: users
...
You can also check out and deploy the example.
Beta version
This repository contains a beta version of Serverless Framework Compose: a new feature providing multi-service deployments.
While in beta, this feature is in a separate repository and NPM package. Eventually, it will be merged in the main serverless
CLI and project.
We use GitHub issues to discuss ideas and features. We encourage you to:
- watch the GitHub repository to be notified of releases and discussions
- get involved in GitHub issues
Installation
While in beta, the feature ships as a separate package and CLI. Install it via NPM:
npm -g i @serverless/compose-beta
The CLI can now be used via the following command:
serverless-compose
or for short:
slsc
Note: while in beta, the feature is available via the serverless-compose
command, not the main serverless
CLI.
Usage
The multi-service deployment feature is designed for monorepositories.
Assuming you have an application containing multiple Serverless Framework services, for example:
my-app/
service-a/
src/
...
serverless.yml
service-b/
src/
...
serverless.yml
You can now create a serverless-compose.yml
configuration file at the root of your monorepository.
In that new file, you can reference existing Serverless Framework projects by their relative paths:
# Name of the application
name: myapp
services:
service-a:
# Relative path to the Serverless Framework service
path: service-a
service-b:
# Relative path to the Serverless Framework service
path: service-b
# If the file is not named "serverless.yml" it is possible to configure that:
# config: serverless.api.yml
To deploy all services, instead of running serverless deploy
in each service, you can now deploy all services at once via:
$ serverless-compose deploy
Deploying myapp to stage dev
✔ service-a › deployed › 15s
✔ service-b › deployed › 31s
serverless deploy
in each service directory. If Serverless Framework is installed locally (in node_modules/
) in some services, you need to make sure Serverless Framework v3.3.0 or greater is installed.
Service dependencies and variables
Service variables let us:
- order deployments
- inject outputs from one service into another
This is possible via the ${service.output}
syntax. For example:
services:
service-a:
path: service-a
service-b:
path: service-b
params:
queueUrl: ${service-a.queueUrl}
Let's break down the example above into 3 steps:
-
${service-a.queueUrl}
will resolve to thequeueUrl
output of theservice-a
service.The outputs of a Serverless Framework service are resolved from its CloudFormation outputs. Here is how we can expose the
queueUrl
output in theservice-a/serverless.yml
config:# service-a/serverless.yml # ... resources: Resources: MyQueue: Type: AWS::SQS::Queue # ... Outputs: queueUrl: Value: !Ref MyQueue
-
Because of the dependency introduced by the variable,
serverless-compose deploy
will automatically deployservice-a
first, and thenservice-b
. -
The value will be passed to
service-b
as a parameter namedqueueUrl
. Parameters can be referenced in Serverless Framework configuration via the${param:xxx}
syntax:# service-b/serverless.yml provider: ... environment: # Here we inject the queue URL as a Lambda environment variable SERVICE_A_QUEUE_URL: ${param:queueUrl}
Cross-services variables are a great way to share API URLs, queue URLs, database table names, and more, without having to hardcode resource names or use SSM.
Alternatively, you can also specify explicit dependencies without passing any variables between services by setting dependsOn
to a name of service in configuration. For example:
services:
service-a:
path: service-a
service-b:
path: service-b
dependsOn: service-a
service-c:
path: service-c
service-d:
path: service-d
dependsOn:
- service-a
- service-c
As seen in the above example, it is possible to configure more than one dependency by providing dependsOn
as a list.
Global commands
On top of serverless-compose deploy
, the following commands can be run globally across all services:
-
serverless-compose info
to view all services outputs -
serverless-compose remove
to remove all services -
serverless-compose refresh-outputs
to refresh outputs of all services -
serverless-compose logs
to fetch logs from all functions across all services -
serverless-compose outputs
to view all services outputs
For example, it is possible to tail logs for all functions at once:
$ serverless-compose logs --tail
service-a › users › START
service-a › users › 2021-12-31 16:54:14 INFO New user created
service-a › users › END Duration: 13 ms ...
service-b › subscriptions › START
service-b › subscriptions › 2021-12-31 16:54:14 INFO New subscription enabled
service-b › subscriptions › END Duration: 7 ms ...
⠴ service-a › logs › 2s
⠦ service-a › logs › 2s
Service-specific commands
It is possible to run commands for a specific service only. For example to deploy only a specific service:
serverless-compose deploy --service=service-a
# Shortcut alternative
serverless-compose service-a:deploy
Or tail logs of a single function:
serverless-compose logs --service=service-a --function=index
# Shortcut alternative
serverless-compose service-a:logs --function=index
All Serverless Framework commands are supported via service-specific commands, including custom commands from plugins.
Service-specific commands when using parameters
The serverless-compose service-a:deploy
command is the equivalent of running serverless deploy
in service-a's directory. Both approaches can be used.
However, if "service-a" uses ${param:xxx}
to reference serverless-compose.yml
parameters, then serverless deploy
will not work. Indeed, ${param:xxx}
cannot be resolved outside of Serverless Framework compose.
In these cases, you must run all commands from the root: serverless-compose service-a:deploy
.
serverless.yml
Differences with Unless documented here, expect any serverless.yml
feature to not be supported in serverless-compose.yml
. For example, it is not possible to include plugins or use serverless.yml
variables (like ${env:
, ${opt:
, etc.) inside serverless-compose.yml
.
Feel free to open an issue if you need a feature that isn't supported at the moment.
Refreshing outputs of already deployed services
If you need to refresh outputs of services that you already deployed previously, e.g. from different development machine, you can do it with the following command:
serverless-compose refresh-outputs
Removing services
To delete the whole project (and all its services), run serverless-compose remove
. This will run serverless remove
in each service.
To delete only one service:
- run
serverless-compose <component>:remove
- then remove the service from
serverless-compose.yml
If you remove the service from serverless-compose.yml
without doing step 1 first the service will still be deployed in your AWS account.
Remember to do this for every stage you may have previously deployed.