What is SST
SST is a framework that makes it easy to build modern full-stack applications on AWS.
Deploy a serverless Next.js, Remix, Astro, or Solid site to your AWS account and add any backend feature to it.
Frontend
Start by defining, in code, the frontend you are using. SST supports the following.
Next.js
new NextjsSite(stack, "site", {
path: "web",
customDomain: "my-next-app.com",
});
Behind the scenes, NextjsSite
will create the infrastructure to host your serverless Next.js app on AWS. Including Lambda functions for SSR, edge functions for Middleware, a CDN, and an S3 bucket for static assets.
Remix
Similarly there's RemixSite
for Remix.
new RemixSite(stack, "site", {
path: "web",
customDomain: "my-remix-app.com",
});
Astro
new AstroSite(stack, "site", {
path: "web",
customDomain: "my-astro-app.com",
});
Solid
And the SolidStartSite
for Solid.
new SolidStartSite(stack, "site", {
path: "web",
customDomain: "my-solid-app.com",
});
Static sites
There's also the StaticSite
for any static site builder.
new StaticSite(stack, "site", {
path: "web",
buildOutput: "dist",
buildCommand: "npm run build",
customDomain: "my-static-site.com",
});
Just specify the build command and point to where the output is generated.
Infrastructure
The above snippets are a way of defining the features of your application in code. You can define any feature of your application, not just the frontend.
You can add backend features like APIs, databases, cron jobs, and more. All without ever using the AWS Console.
Let's look at it in detail.
Constructs
These snippets are called Constructs. They are TypeScript or JavaScript classes, where each class corresponds to a feature that can be configured through its props.
const site = new NextjsSite(stack, "site", {
/** props **/
});
We recommend using TypeScript because it allows for full type safety while configuring your application.
Stacks
Constructs are grouped into stacks. They allow you to organize the infrastructure in your application.
export function Web({ stack }: StackContext) {
const site = new NextjsSite(stack, "site");
}
Each stack is just a function that creates a set of constructs.
App
Finally, you add all your stacks to your app in the sst.config.ts
.
export default {
config(input) {
return {
name: "my-sst-app",
region: "us-east-1",
}
},
stacks(app) {
app.stack(Database).stack(Api).stack(Web);
},
} satisfies SSTConfig;
Here we are also specifying a name for our app and the AWS region it'll be deployed to.
Now let's look at how you can add the backend for your app with these constructs.
Backend
SST has constructs for most backend features. And you can even use any AWS service in your app.
APIs
For example, with the Api
construct you can define an API in a few lines.
new Api(stack, "API", {
routes: {
"GET /notes": "services/list.main",
"POST /notes": "services/create.main",
},
});
Behind the scenes, this creates a serverless API using Amazon API Gateway, where each route points to a Lambda function.
Functions
So when a user hits the /notes
route in your API.
"GET /notes": "services/list.main"
The main
function in services/list.ts
gets executed. The API then responds with what's returned.
export async function main() {
return {
statusCode: 200,
body: JSON.stringify([
/** list of notes **/
]),
};
}
Your functions can be in TypeScript, JavaScript, Python, Golang, Java, or C#.
Databases
You can add a serverless database to your app. Here the RDS
construct configures a new Amazon RDS serverless PostgreSQL cluster.
new RDS(stack, "notesDb", {
engine: "postgresql11.13",
defaultDatabaseName: "main",
migrations: "services/migrations",
});
In addition to SQL databases, SST also supports Amazon DynamoDB, a NoSQL serverless database.
Cron jobs
You can add cron jobs to your application with a few lines. Here's a cron job that calls a function every minute.
new Cron(stack, "cron", {
schedule: "rate(1 minute)",
job: "services/cronjob.main",
});
SST also has constructs for Auth, Queues, Pub/Sub, Data Streams, and more.
All AWS services
Aside from the features that SST's constructs support, you can add any AWS service to your app. This is because SST is built on top of AWS CDK and you can use any CDK construct in SST.
Here we are defining an Amazon ECS cluster with an AWS CDK construct.
import * as ecs from "aws-cdk-lib/aws-ecs";
const cluster = new ecs.Cluster(stack, "Cluster", {
vpc,
});
This ensures that as your app grows, you'll be able to add any feature you need.
Connecting everything
Once you've added a couple of features, SST can help you connect them together. This is great because you won't need to hardcode anything in your app.
In the frontend
For example, you can grab the endpoint of your API and pass it to Next.js as an environment variable.
const api = new Api(/* ... */);
new NextjsSite(stack, "site", {
// ...
environment: {
API_URL: api.url,
},
});
You can then connect to your API in Next.js without hardcoding the URL.
export async function getStaticProps() {
const notes = await fetch(process.env.API_URL);
// ...
}
In the backend
Similarly, you can allow your backend functions to securely connect to your infrastructure, through a concept we call Resource Binding. For example, you can bind the PostgreSQL database to the API.
const rds = new RDS(stack, "notesDb" /* ... */);
const api = new Api(/* ... */);
api.bind([rds]);
Now the functions in your API will have type safe access to your database.
import { RDS } from "sst/node/rds";
export async function main() {
new ExecuteStatementCommand({
sql: "select * from notes",
secretArn: RDS.notesDb.secretArn,
resourceArn: RDS.notesDb.clusterArn,
database: RDS.notesDb.defaultDatabaseName,
});
}
Behind the scenes SST also adds the required permissions, so only your API has access to the database.
Project structure
We've looked at a couple of different types of files. Let's take a step back and see what an SST app looks like in practice.
SST applications are monorepo by default.
my-sst-app
├─ sst.config.ts
├─ package.json
├─ packages
│ ├─ frontend
│ └─ functions
├─ stacks
Where the packages/frontend/
directory is your frontend, packages/functions/
is the backend, and stacks/
has your infrastructure definitions.
For the frontend of your application, SST lets you deploy Next.js and Remix apps. Or any static website.
Here for example, we are defining a Vite static site using the StaticSite
construct.
new StaticSite(this, "site", {
path: "packages/frontend",
buildCommand: "npm run build",
buildOutput: "dist",
customDomain: "my-sst-app.com",
environment: {
VITE_API_URL: api.url,
},
});
Behind the scenes, this creates a static website powered by Amazon S3 and serves it through Amazon CloudFront, a CDN.
Connect to the API
SST makes it easy to connect your frontend to your API by letting you share config between constructs.
For example, you can grab the API endpoint from the API construct and pass it to our frontend as an environment variable.
const api = new Api(/* ... */);
new StaticSite(this, "site", {
// ...
environment: {
VITE_API_URL: api.url,
},
});
With SST, we don't need to hardcode our backend config in the frontend.
SST CLI
To help with building and deploying your app, SST comes with a CLI.
Local dev
The sst dev
command starts a local development environment called Live Lambda, that connects directly to AWS. Letting you set breakpoints and test your functions locally.
npx sst dev
Now you can start your frontend with the sst env
command. It'll connect your frontend to the backend by loading all the environment variables.
cd web
sst env "next dev"
With this you can make changes to your backend on AWS, and see them directly in your frontend!
SST Console
The sst dev
CLI also powers a web based dashboard called the SST Console.
With the Console you can view and interact with your application in real-time. You can manually invoke functions, view logs, replay invocations, and do things like query your database and run migrations.
Deployment
To deploy your application to AWS, you use the sst deploy
command. It uses your local IAM credentials and deploys to your AWS account.
npx sst deploy
Since everything in your app is connected, this single command is all you need. Once complete, it'll print out your app's URL!
Outputs:
ApiEndpoint: https://ck198mfop1.execute-api.us-east-1.amazonaws.com
SiteUrl: https://my-next-app.com
Behind the scenes, it compiles the constructs to AWS CloudFormation, packages your frontend assets and functions, uploads it to AWS, and creates your app's infrastructure.
Environments
The sst deploy
command can also deploy your app to a specific stage or environment. This lets you create separate environments for development, production, pull-requests, or branches.
# Deploy to dev
npx sst deploy --stage dev
# Deploy to production
npx sst deploy --stage prod
You can use this in your GitHub Actions workflow to generate pull-request based environments.
Or, you can get automatic preview environments with SEED, a service built by the SST team.
Starters
To create your first SST app you can use one of our starters with the create-sst
CLI.
npm create sst@latest
This will set you up with a full-stack TypeScript app with a React frontend, GraphQL API, and a PostgreSQL database.
However, if you are a more advanced user, you can pick one of our minimal templates and use our constructs to build the type of app you need.
To get started with SST, check out our tutorial.