Skip to content

Express on AWS with SST

Create and deploy an Express app to AWS with SST.

You can use SST to deploy an Express app in a container to AWS. It uses Fargate and ECS.

We’ll build a simple app below.


Examples

We also have a few other Express examples that you can refer to.


We are going to build a hit counter using Express and Redis. We’ll the deploy it to AWS in a container.

Before you get started, make sure to configure your AWS credentials.


1. Create a project

Let’s start by creating our Express app.

Terminal window
mkdir aws-express && cd aws-express
npm init -y
npm install express

Init Express

Create your app by adding an index.mjs to the root.

index.mjs
import express from "express";
const PORT = 80;
const app = express();
app.get("/", (req, res) => {
res.send("Hello World!")
});
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});

Init SST

Now let’s initialize SST in our app.

Terminal window
npx sst@latest init
npm install

This’ll create a sst.config.ts file in your project root.


2. Add a Service

To deploy our Express app, let’s add an AWS Fargate container with Amazon ECS. Update your sst.config.ts.

sst.config.ts
async run() {
const vpc = new sst.aws.Vpc("MyVpc");
const cluster = new sst.aws.Cluster("MyCluster", { vpc });
cluster.addService("MyService", {
loadBalancer: {
ports: [{ listen: "80/http" }],
},
dev: {
command: "node --watch index.mjs",
},
});
}

This creates a VPC with an ECS Cluster, and adds a Fargate service to it.

The dev.command tells SST to instead run our Express app locally in dev mode.


Start dev mode

Run the following to start dev mode. This’ll start SST and your Express app.

Terminal window
npx sst dev

Once complete, click on MyService in the sidebar and open your Express app in your browser.


3. Add an S3 Bucket

Let’s add an S3 Bucket for file uploads. Add this to your sst.config.ts below the Vpc component.

sst.config.ts
const bucket = new sst.aws.Bucket("MyBucket");

Now, link the bucket to the container.

sst.config.ts
cluster.addService("MyService", {
// ...
link: [bucket],
});

This will allow us to reference the bucket in our Express app.


4. Upload a file

We want a POST request made to the / route to upload a file to our S3 bucket. Let’s add this below our Hello World route in our index.mjs.

index.mjs
app.post("/", upload.single("file"), async (req, res) => {
const file = req.file;
const params = {
Bucket: Resource.MyBucket.name,
ContentType: file.mimetype,
Key: file.originalname,
Body: file.buffer,
};
const upload = new Upload({
params,
client: s3,
});
await upload.done();
res.status(200).send("File uploaded successfully.");
});

Add the imports. We’ll use the extra ones below.

index.mjs
import multer from "multer";
import { Resource } from "sst";
import { Upload } from "@aws-sdk/lib-storage";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import {
S3Client,
GetObjectCommand,
ListObjectsV2Command,
} from "@aws-sdk/client-s3";
const s3 = new S3Client({});
const upload = multer({ storage: multer.memoryStorage() });

And install the npm packages.

Terminal window
npm install multer @aws-sdk/client-s3 @aws-sdk/lib-storage @aws-sdk/s3-request-presigner

5. Download the file

We’ll add a /latest route that’ll download the latest file in our S3 bucket. Let’s add this below our upload route in index.mjs.

index.mjs
app.get("/latest", async (req, res) => {
const objects = await s3.send(
new ListObjectsV2Command({
Bucket: Resource.MyBucket.name,
}),
);
const latestFile = objects.Contents.sort(
(a, b) => b.LastModified - a.LastModified,
)[0];
const command = new GetObjectCommand({
Key: latestFile.Key,
Bucket: Resource.MyBucket.name,
});
const url = await getSignedUrl(s3, command);
res.redirect(url);
});

Test your app

To upload a file run the following from your project root.

Terminal window
curl -F file=@package.json http://localhost:80/

This should upload the package.json. Now head over to http://localhost:80/latest in your browser and it’ll show you what you just uploaded.


5. Deploy your app

To deploy our app we’ll first add a Dockerfile.

Dockerfile
FROM node:lts-alpine
WORKDIR /app/
COPY package.json /app
RUN npm install
COPY index.mjs /app
ENTRYPOINT ["node", "index.mjs"]

This just builds our Express app in a Docker image.

Let’s also add a .dockerignore file in the root.

.dockerignore
node_modules

Now to build our Docker image and deploy we run:

Terminal window
npx sst deploy --stage production

You can use any stage name here but it’s good to create a new stage for production. This’ll give the URL of your Express app deployed as a Fargate service.

Terminal window
Complete
MyService: http://jayair-MyServiceLoadBala-592628062.us-east-1.elb.amazonaws.com

Connect the console

As a next step, you can setup the SST Console to git push to deploy your app and monitor it for any issues.

SST Console Autodeploy

You can create a free account and connect it to your AWS account.