Serverless Offline: handle multiple API gateways

You can easily debug your serverless application with the Serverless Framework and the Serverless Offline Plugin when you only have one, but how do you handle the case when you have multiple API Gateways/services?

Should I run serverless offline for every service, with a different port configured in each .yml?
and hardcode that port in the environment variables so I can access that port if process.env.offline is true?


Solution 1:

If you want to run two or more Serverless API Gateways at the same time locally you can easily do it with --port parameter.

Basically, open two command line windows and in the first window, go to your first service directory and run:

sls offline start --port 3001

in the other window, go to your second service and run:

sls offline start --port 3002

This way you you will have two services listening on two ports (in this examples http://localhost:3001 and http://localhost:3002).

There is one catch (at the moment) if you also use serverless-dynamodb-local plugin:

If you don't use DynamoDB plugin then you are okay and can stop reading now :)

DynamoDB plugin is using the same --port parameter and that causes java.net.BindException: Address already in use

See this issue: https://github.com/99xt/serverless-dynamodb-local/issues/135

The workaround for this is to keep serverless-offline-local plugin enabled in only one service (if you have two or more).

Example, In my-service-1 you keep all dynamodb config in serverless.yaml file and start this service with default port: sls offline start --migrate true. In the next service, let's call it my-service-2 you remove serverless-dynamodb-local from plugins in serverless.yaml (there is no need for any other changes) and then you can start the service with: sls offline start --port 3001.

First service will start DynamoDB and the second one will be able to use it.

Solution 2:

Update for the Accepted answer in 2022

according to the documentation, --port is no longer available use --httpPort instead, like below code

sls offline --httpPort 3001

or Any of the CLI options can be added to your serverless.yml. For example:

custom:
  serverless-offline:
    httpsProtocol: "dev-certs"
    httpPort: 4000
    stageVariables:
      foo: "bar"

from official documentation

Solution 3:

What I do is create another service that has all the functions of other services. Below is my folder structure.

main/
├── service1/
│   ├── ...
│   └── serverless.yml 
├── service2/
│   ├── ...
│   └── serverless.yml
├── serverless.yml # offline service with serverless-offline plugin
├── node_modules # 1 node_modules for every services
└── ...

You can remove serverless-offline plugin on the service1 and service2.

Update!

I've develop a script for generating offline serverless.yml. Check out the example here: https://github.com/Necromancerx/serverless-offline-template