Serverless Stack Toolkit (SST) is an extension of AWS CDK that:
- Includes a complete local development environment for Lambda
- Supports remotely invoking local functions
- Zero-config ES and TypeScript support using esbuild
- Allows you to use CDK with Serverless Framework
Getting help: Slack / Twitter / Forums
Create your first SST app.
$ npx create-serverless-stack@latest my-sst-app
$ cd my-sst-app
$ npx sst start- Background
- Usage
- Example Project
- Migrating From CDK
- Known Issues
- Future Roadmap
- Contributing
- Running Locally
- References
- Community
Developing Lambdas locally is painful, you either:
- Locally mock all the AWS services you are using
- Or, constantly deploy your changes to test them
Both these approaches don't work well in practice. Locally mocking all the AWS services can be hard to do and most setups are really flaky. While, constantly deploying your Lambda functions or infrastructure can be simply too slow.
The sst start command starts up a local development environment that opens a WebSocket connection to your deployed app and proxies any Lambda requests to your local machine. This allows you to:
- Work on your Lambda functions locally
- While, interacting with your entire deployed AWS infrastructure
- Supports all Lambda triggers, so there's no need to mock API Gateway, SQS, SNS, etc.
- Supports real Lambda environment variables and Lambda IAM permissions
- So if a Lambda fails on AWS due to lack of IAM permissions, it would fail locally as well
- And it's fast. There's nothing to deploy when you make a change!
You can read more about the sst start command here and try out a demo here.
Serverless Framework is great but deploying any other AWS resources requires you to write CloudFormation templates in YAML. CloudFormation templates are incredibly verbose and even creating simple resources can take hundreds of lines of YAML. AWS CDK solves this by allowing you to generate CloudFormation templates using modern programming languages. Making it truly, infrastructure as code.
However, to use AWS CDK alongside your Serverless Framework services, requires you to follow certain conventions.
-
Deploying all the stacks to the same region and AWS account
Serverless Framework apps are deployed to multiple environments using the
--regionandAWS_PROFILE=profileoptions. CDK apps on the other hand, contain CloudFormation stacks that are deployed to multiple regions and AWS accounts simultaneously. -
Prefixing stage and resource names
Since the same app is deployed to multiple environments, Serverless Framework adopts the practice of prefixing the stack names with the stage name. On the other hand, to deploy a CDK app to multiple stages, you'd need to manually ensure that the stack names and resource names don't thrash.
SST provides the above out-of-the-box. So you can deploy your Serverless services using:
$ AWS_PROFILE=production serverless deploy --stage prod --region us-east-1And use CDK for the rest of your AWS infrastructure:
$ AWS_PROFILE=production npx sst deploy --stage prod --region us-east-1You can read more about this here.
As a bonus, SST also supports deploying your CloudFormation stacks asynchronously. So you don't have to waste CI build minutes waiting for CloudFormation to complete. Seed natively supports concurrent asynchronous deployments for your SST apps. Making it 5x faster than other CI services. And SST deployments on Seed are free!
SST also comes with a few other niceties:
- Zero-config support for ES and TypeScript using esbuild
- Automatically lints your code using ESLint
- Runs your unit tests using Jest
Behind the scenes, SST uses a lightweight fork of AWS CDK to programmatically invoke the various CDK commands.
Create a new project using.
$ npx create-serverless-stack@latest my-sst-appOr alternatively, with a newer version of npm or Yarn.
# With npm 6+
$ npm init serverless-stack@latest my-sst-app
# Or with Yarn 0.25+
$ yarn create serverless-stack my-sst-appThis by default creates a JavaScript/ES project. If you instead want to use TypeScript.
$ npm init serverless-stack@latest my-sst-app --language typescriptBy default your project is using npm as the package manager, if you'd like to use Yarn.
$ npm init serverless-stack@latest my-sst-app --use-yarnYou can read more about the create-serverless-stack CLI here.
Your app starts with a simple project structure.
my-sst-app
├── README.md
├── node_modules
├── .gitignore
├── package.json
├── sst.json
├── test
│ └── MyStack.test.js
├── lib
| ├── MyStack.js
| └── index.js
└── src
└── lambda.js
It includes a config file in sst.json.
{
"name": "my-sst-app",
"stage": "dev",
"region": "us-east-1"
}The stage and the region are defaults for your app and can be overridden using the --stage and --region options. The name is used while prefixing your stack and resource names.
The lib/index.js file is the entry point for your app. It has a default export function to add your stacks.
import MyStack from "./MyStack";
export default function main(app) {
new MyStack(app, "my-stack");
// Add more stacks
}Here you'll be able to access the stage, region, and name of your app using.
app.stage; // "dev"
app.region; // "us-east-1"
app.name; // "my-sst-app"In the sample lib/MyStack.js you can add the resources to your stack.
import * as sst from "@serverless-stack/resources";
export default class MyStack extends sst.Stack {
constructor(scope, id, props) {
super(scope, id, props);
// Define your stack
}
}Note that the stacks in SST use sst.Stack as imported from @serverless-stack/resources. As opposed to cdk.Stack. This is what allows SST to make sure that your stack names are prefixed with the stage names and are deployed to the region and AWS account that's specified through the CLI.
You can access the stage, region, and name of your app using.
this.node.root.stage; // "dev"
this.node.root.region; // "us-east-1"
this.node.root.name; // "my-sst-app"And if you need to prefix certain resource names so that they don't thrash when deployed to multiple stages, you can do the following in your stacks.
this.node.root.logicalPrefixedName("MyResource"); // "dev-my-sst-app-MyResource"The sample stack also comes with a Lambda function and API endpoint. The Lambda function is in the src/ directory.
new sst.Function(this, "Lambda", {
entry: "src/lambda.js",
});Notice that we are using the sst.Function instead of the cdk.lambda.NodejsFunction. This allows SST to locally invoke a deployed Lambda function.
You can read more about @serverless-stack/resources here.
Let's start the local development environment.
# With npm
$ npx sst start
# Or with Yarn
$ yarn sst startThe first time you run this, it'll deploy your app and a stack that sets up the debugger. This can take a couple of minutes.
The sample stack will deploy a Lambda function with an API endpoint. You'll see something like this in the output.
Outputs:
ApiEndpoint: https://s8gecmmzxf.execute-api.us-east-1.amazonaws.comIf you head over to the endpoint, it'll invoke the Lambda function in src/lambda.js. You can try changing this file and hitting the endpoint again. You should see your changes reflected right away!
Once you are ready to build your app and convert your CDK code to CloudFormation, run the following from your project root.
# With npm
$ npx sst build
# Or with Yarn
$ yarn sst buildThis will compile your ES (or TS) code to the .build/ directory in your app. And the synthesized CloudFormation templates are outputted to .build/cdk.out/. Note that, you shouldn't commit the .build/ directory to source control and it's ignored by default in your project's .gitignore.
You can run your tests using.
# With npm
$ npm test
# Or with Yarn
$ yarn testInternally, SST uses Jest. You'll just need to add your tests to the test/ directory.
Once your app has been built and tested successfully. You are ready to deploy it to AWS.
# With npm
$ npx sst deploy
# Or with Yarn
$ yarn sst deployThis uses your default AWS Profile. And the region and stage specified in your sst.json. You can deploy using a specific AWS profile, stage, and region by running.
$ AWS_PROFILE=my-profile npx sst deploy --stage prod --region eu-west-1Finally, you can remove all your stacks and their resources from AWS using.
# With npm
$ npx sst remove
# Or with Yarn
$ yarn sst removeNote that, this permanently removes your resources from AWS. It also removes the stack that's created as a part of the debugger.
The above commands (start, build, deploy, and remove) are also available in your package.json. So you can run them using.
# With npm
$ npm run <command>
# Or with Yarn
$ yarn run <command>Just note that for npm run, you'll need to use an extra -- for the options. For example:
$ npm run build -- --stage alphaYour code is automatically linted when building or deploying. If you'd like to customize the lint rules, add a .eslintrc.json in your project root. If you'd like to turn off linting, add * to an .eslintignore file in your project root.
If you are using TypeScript, SST also runs a separate TypeScript process to type check your code. It uses the tsconfig.json in your project root for this.
Note that, this applies to the Lambda functions in your app as well.
We use SST as a part of the Serverless Stack guide. We build a simple notes app in the guide and the backend for it is created using Serverless Framework and CDK with SST. You can check out the repo here — serverless-stack-demo-api.
It's fairly simple to move a CDK app to SST. There are a couple of small differences between the two:
-
There is no
cdk.jsonIf you have a
contextblock in yourcdk.json, you can move it to acdk.context.json. You can read more about this here. You'll also need to add asst.jsonconfig file, as talked about above. Here is a sample config for reference.{ "name": "my-sst-app", "stage": "dev", "region": "us-east-1" } -
There is no
bin/*.jsInstead there is a
lib/index.jsthat has a default export function where you can add your stacks. SST creates the App object for you. This is what allows SST to ensure that the stage, region, and AWS accounts are set uniformly across all the stacks. Here is a samplelib/index.jsfor reference.import MyStack from "./MyStack"; export default function main(app) { new MyStack(app, "my-stack"); // Add more stacks }
-
Stacks extend
sst.StackYour stack classes extend
sst.Stackinstead ofcdk.Stack. Here is what the JavaScript version looks like.import * as sst from "@serverless-stack/resources"; export default class MyStack extends sst.Stack { constructor(scope, id, props) {} }
And in TypeScript.
import * as sst from "@serverless-stack/resources"; export class MyStack extends sst.Stack { constructor(scope: sst.App, id: string, props?: sst.StackProps) {} }
-
Lambdas use
sst.FunctionUse the
sst.Functionconstruct instead to thecdk.lambda.NodejsFunction. You can read more about this over on@serverless-stack/resourcesdocs. -
Include the right packages
You don't need the
aws-cdkpackage in yourpackage.json. Instead you'll need@serverless-stack/cliand@serverless-stack/resources.
There is a known issue in AWS CDK when using mismatched versions of their NPM packages. This means that all your AWS CDK packages in your package.json should use the same exact version. And since SST uses a forked version of AWS CDK internally, this means that your app needs to use the same versions as well.
To help with this, SST will show a message to let you know if you might potentially run into this issue. And help you fix it.
Mismatched versions of AWS CDK packages. Serverless Stack currently supports 1.55.0. Fix using:
npm install @aws-cdk/[email protected] --save-exactWe also created a convenience method to help install the CDK npm packages with the right version — sst add-cdk.
So instead of:
$ npm install @aws-cdk/aws-s3 @aws-cdk/aws-iamYou can do:
$ npx sst add-cdk @aws-cdk/aws-s3 @aws-cdk/aws-iamAnd it'll install those packages using the right CDK versions.
You can learn more about these issues here and here.
Check out the public SST roadmap here.
Check out our roadmap and join our Slack to get started.
- Open a new issue if you've found a bug or have some suggestions.
- Or submit a pull request!
To run this project locally, clone the repo and initialize the project.
$ git clone https://github.com/serverless-stack/serverless-stack.git
$ cd serverless-stack
$ yarnRun all the tests.
$ yarn testFollow us on Twitter, join us on Slack, post on our forums, and subscribe to our newsletter.
This project extends AWS CDK and is based on the ideas from Create React App.
Brought to you by Anomaly Innovations; makers of Seed and the Serverless Stack Guide.
