Serverless Framework、AWS CDK 與 SST 比較及作者在 2026 年的選擇
Serverless Framework vs CDK vs SST: my pick for 2026
作者以同一個 Lambda API 實作比較 Serverless Framework、AWS CDK 和 SST,並提出按項目需求選擇工具的 2026 年建議。
Serverless Framework vs CDK: I get asked this almost every week, and for a few years now SST has been the third candidate in the room. I started out with the Serverless Framework, wrote CDK for many years and keep coming back to SST to try it out. That is why I know the honest answer is not “tool X is the best”. It depends on what you build, who will still maintain it in three years and how much infrastructure grows around your Lambda functions.
In this article I build the same small API three times: once with the Serverless Framework, once with AWS CDK and once with SST. After that I compare the three tools where it really matters in day-to-day work. At the end you get my clear recommendation on which tool I pick in 2026, and why the Serverless Framework vs CDK question is often settled before the first line of code.
In short
All three tools get a Lambda API into AWS within minutes, but they differ in engine, licence and target audience. I use the Serverless Framework for Lambda-heavy backends, CDK for platforms with a lot of infrastructure and SST for full-stack apps in TypeScript teams. The biggest pitfall is switching tools halfway through a project, because the state of your infrastructure does not simply move with you.
What you will learn in this article
- Deploy the same Lambda API with Serverless Framework, CDK and SST
- How engine, state and local development differ between the three tools
- What the Serverless Framework v4 licence means for companies
- Which questions help you choose a tool
Three tools, one goal
All three tools describe infrastructure as code (IaC): you write down in a file which Lambda functions, APIs and tables should exist, and the tool makes sure AWS looks exactly like that. The differences lie in how you describe it and what happens under the hood.
Serverless Framework: YAML focused on functions
The Serverless Framework is the oldest of the three. You describe your service in a serverless.yml, with functions and the events that trigger them at the centre. From that, the framework generates a CloudFormation template and deploys it. Since version 4 it builds TypeScript handlers itself with its built-in esbuild, so you no longer need a build plugin. Version 3 is open source, but according to the vendor it has not been maintained since 31 December 2024.
AWS CDK: a real programming language, CloudFormation underneath
The AWS Cloud Development Kit (CDK) is the official tool from AWS. You write infrastructure in TypeScript, Python, Java, C#/.NET or Go. Reusable building blocks are called constructs: a NodejsFunction construct, for example, bundles your TypeScript code and creates the Lambda function including its IAM role. CDK also produces a CloudFormation template in the end. The project is licensed under Apache 2.0, and the CLI is now released from its own repository with its own version number.
SST: TypeScript configuration with the Pulumi engine
SST describes the whole app in a single sst.config.ts. The key difference: SST does not use CloudFormation. According to its docs it uses Pulumi as the deployment engine and talks to the AWS APIs directly. SST keeps its state in an S3 bucket in your account. SST is open source under the MIT licence and has been at version 4 since February 2026. The main change from v3 is the jump of the Pulumi AWS provider from v6 to v7. If you only use SST components, your code stays as it is, but the state has to be migrated once with sst refresh.
Serverless Framework vs CDK vs SST in practice
For the comparison I build a fictional mini API for a bike rental: GET /bikes returns all available bikes, optionally filtered by station. Behind it sits a single Lambda function in TypeScript behind an API Gateway HTTP API. Small enough to show everything, big enough to make the differences visible.
Prerequisites
- An AWS account and local credentials (for example via
aws configure sso), ideally in a test account. - Node.js 22 or newer and npm.
- For Serverless Framework v4, a free account with the vendor, because the CLI requires you to sign in.
- For CDK, run
cdk bootstraponce per account and region.
Step 1: The shared Lambda handler
The handler is identical in all three variants. It lives in src/bikes.ts and uses the types from @types/aws-lambda:
// src/bikes.ts
import type { APIGatewayProxyHandlerV2 } from "aws-lambda";
type Bike = {
id: string;
model: string;
station: string;
available: boolean;
};
// Demo data – in a real app this would come from DynamoDB
const bikes: Bike[] = [
{ id: "b-101", model: "City Classic", station: "hauptbahnhof", available: true },
{ id: "b-102", model: "Trekking Pro", station: "hauptbahnhof", available: false },
{ id: "b-103", model: "E-Bike Flow", station: "altstadt", available: true },
{ id: "b-104", model: "Lastenrad Max", station: "altstadt", available: true },
];
export const handler: APIGatewayProxyHandlerV2 = async (event) => {
const station = event.queryStringParameters?.station;
const result = bikes.filter(
(bike) => bike.available && (!station || bike.station === station),
);
return {
statusCode: 200,
headers: { "content-type": "application/json" },
body: JSON.stringify({ count: result.length, bikes: result }),
};
};
So that TypeScript knows the types, install the dev dependencies once:
npm init -y
npm install --save-dev typescript @types/aws-lambda @types/node
Step 2: Deploy with the Serverless Framework
The complete infrastructure fits into this serverless.yml. You point the handler straight at the TypeScript file, and the built-in esbuild bundles it during deployment:
# serverless.yml
service: fahrradverleih-api
frameworkVersion: "4"
provider:
name: aws
runtime: nodejs22.x
architecture: arm64
region: eu-central-1
memorySize: 256
timeout: 5
functions:
listBikes:
handler: src/bikes.handler
events:
- httpApi:
path: /bikes
method: get
Then install the CLI, sign in once and deploy:
npm install -g serverless
serverless login
serverless deploy --stage dev
At the end, the framework prints the API URL under endpoint. A curl "<endpoint>/bikes?station=altstadt" then returns {"count":2,"bikes":[...]}. Clean up with serverless remove --stage dev.
Step 3: Deploy with AWS CDK
With CDK you write the infrastructure as a TypeScript class. First the dependencies:
npm install aws-cdk-lib constructs
npm install --save-dev aws-cdk esbuild tsx
The stack creates the function, the HTTP API and the route. NodejsFunction bundles the handler with esbuild, which is why esbuild is in the dev dependencies above:
// lib/bike-api-stack.ts
import { CfnOutput, Duration, Stack, type StackProps } from "aws-cdk-lib";
import { HttpApi, HttpMethod } from "aws-cdk-lib/aws-apigatewayv2";
import { HttpLambdaIntegration } from "aws-cdk-lib/aws-apigatewayv2-integrations";
import { Architecture, Runtime } from "aws-cdk-lib/aws-lambda";
import { NodejsFunction } from "aws-cdk-lib/aws-lambda-nodejs";
import type { Construct } from "constructs";
export class BikeApiStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
const listBikes = new NodejsFunction(this, "ListBikes", {
entry: "src/bikes.ts",
handler: "handler",
runtime: Runtime.NODEJS_22_X,
architecture: Architecture.ARM_64,
memorySize: 256,
timeout: Duration.seconds(5),
});
const api = new HttpApi(this, "BikeApi");
api.addRoutes({
path: "/bikes",
methods: [HttpMethod.GET],
integration: new HttpLambdaIntegration("ListBikesIntegration", listBikes),
});
new CfnOutput(this, "ApiUrl", { value: api.apiEndpoint });
}
}
Add the entry point of the app and a small cdk.json that tells CDK how to start the app:
// bin/app.ts
import { App } from "aws-cdk-lib";
import { BikeApiStack } from "../lib/bike-api-stack";
const app = new App();
new BikeApiStack(app, "FahrradverleihApi", {
env: { region: "eu-central-1" },
});
{ "app": "npx tsx bin/app.ts" }
Now bootstrap once per account and region, then deploy:
npx cdk bootstrap
npx cdk deploy
In the output you will find the value FahrradverleihApi.ApiUrl under Outputs. Append /bikes and you get the same response as with the Serverless Framework. Remove everything with npx cdk destroy. If you want to learn CDK from scratch, my article “Deploy a Lambda function with CDK and TypeScript” walks through every step in detail.
Step 4: Deploy with SST
You set up SST with one command in the project folder. It creates an sst.config.ts and installs the sst package:
npx sst@latest init
Then replace the contents of the configuration with this variant. The line with /// <reference …> loads the types that SST generates under .sst/ on first run:
// sst.config.ts
/// <reference path="./.sst/platform/config.d.ts" />
export default $config({
app(input) {
return {
name: "fahrradverleih",
home: "aws",
removal: input?.stage === "production" ? "retain" : "remove",
protect: input?.stage === "production",
providers: { aws: { region: "eu-central-1" } },
};
},
async run() {
const api = new sst.aws.ApiGatewayV2("BikeApi");
api.route("GET /bikes", {
handler: "src/bikes.handler",
architecture: "arm64",
memory: "256 MB",
});
return { url: api.url };
},
});
removal and protect are set on purpose here: in the production stage, resources are kept on removal and sst remove refuses to run. In every other stage, SST cleans up completely. Deploying and removing works like this:
npx sst deploy --stage dev
npx sst remove --stage dev
At the end, SST prints the URL that you return from run(). SST stores the state and a passphrase in an S3 bucket named sst-state-… and in SSM Parameter Store, both in your account.
🎬 From code to AWS: three paths – this animated diagram only runs on my site: watch it on sascha-ms.de
The differences that matter day to day
All three variants deliver the same API. Still, they feel very different once the project grows. I have summarised the key points of Serverless Framework vs CDK vs SST in a table:
| Serverless Framework v4 | AWS CDK v2 | SST v4 | |
|---|---|---|---|
| Configuration | YAML (or a JS/TS file) | TypeScript, Python, Java, C#, Go | TypeScript |
| Engine | CloudFormation | CloudFormation | Pulumi (Terraform providers via bridge) |
| State | in the CloudFormation stack | in the CloudFormation stack | S3 bucket plus SSM parameter in your own account |
| Licence | free up to USD 2 million annual revenue, subscription above that; sign-in required | Apache 2.0 | MIT |
| Local development |
serverless dev routes real invocations to your machine |
cdk watch with hotswap |
sst dev with live functions |
| Strength | Lambda-centric services, little code | any AWS infrastructure, your own constructs | full-stack apps with a frontend |
Engine and state: CloudFormation or Pulumi
On the engine, Serverless Framework vs CDK is almost a draw: both end up in CloudFormation. Deployments can take a bit of patience, but there is a big upside: AWS manages the state, rollbacks happen automatically, and any team with AWS experience can read a stack in the console. You can also mix both worlds without trouble, because ordinary stacks come out at the end.
SST takes a different route with Pulumi. You skip the detour through CloudFormation stacks, and besides AWS you can use providers such as Cloudflare. In return, the state is your responsibility, even though SST keeps it in your account. You notice this at the latest with a major version jump: moving to v4 meant migrating every stage once with sst refresh, and SST explicitly calls this migration one-way.
Local development: how fast is the feedback?
All three have caught up here. serverless dev attaches the functions of an already deployed stage to your machine, so real invocations in AWS run against your local code. The mode refuses production stages named prod and production. sst dev works in a similar way and also starts a watcher for infrastructure changes and your frontend. With CDK I use cdk watch, which pushes code changes straight into the Lambda function via hotswap without redeploying the whole stack. Keep hotswap to development stacks, though, because it deliberately bypasses CloudFormation.
Licence and cost: the Serverless Framework is no longer free
This point is often underestimated. Since v4, the Serverless Framework CLI requires you to sign in. It stays free for individuals and organisations with at most USD 2 million in annual revenue; larger companies need a subscription. Billing works in credits per “service instance”, meaning per service, stage and region that exists for more than ten days in a month. In CI pipelines you use an access key or, with a subscription, the licence key in the SERVERLESS_LICENSE_KEY variable. I walk through moving an existing v3 project in Migrate to Serverless Framework v4.
For a start-up this hardly matters. In a large enterprise with many services and stages, however, it becomes a real budget item and often a procurement question too. CDK and SST cost nothing as tools; you only pay for the AWS resources.
Learning curve and team fit
Almost everyone can read YAML. That is why a serverless.yml is the most approachable option for beginners and for people from operations or the business side. CDK requires your team to understand a programming language and the construct model. In return you get loops, type checking, tests and your own libraries. SST sits in between: TypeScript, but with a small set of very well chosen components. If you already build with Next.js or Astro, you will feel at home right away.
Serverless Framework vs CDK and SST: how I decide today
My thesis: the tool matters less than the question of who maintains the code in three years. Switching halfway through a project is expensive, because you cannot simply move resources holding data from one stack to the next. So it pays to make this decision deliberately. This is the decision guide I use myself:
My decision guide: three questions, three recommendations
Serverless Framework: when Lambda is at the centre
For backends that consist mainly of functions and events, the Serverless Framework is still the most pleasant tool for me. A serverless.yml shows at a glance which function reacts to which event. That is exactly what I love about it. Additional resources such as a DynamoDB table go into the resources section as CloudFormation. That stays readable as long as it is manageable. Do clarify the licence question with your procurement team before you start, though.
AWS CDK: when the infrastructure grows
As soon as a lot of infrastructure grows next to the functions, such as networks, databases, permissions across several accounts or shared building blocks for many teams, I pick CDK. Your own constructs are a strong tool for enforcing standards: one team builds, for example, a MonitoredFunction construct with alarms and logs, and everyone else uses it. On top of that, CDK has no licence fee and comes straight from AWS. In large organisations, that is a strong argument for me.
SST: when a frontend is part of it
SST shines when backend and frontend live together in one repository and the team writes TypeScript throughout. Components for Next.js, Astro and friends, linking resources via link, and sst dev make daily work very pleasant there. I am less keen on SST in environments where CloudFormation is mandatory, for example because approval processes or compliance checks are built around stacks.
And what if I want to mix them?
Mixing works as long as you do it deliberately. A pattern that has proven itself: a platform team builds shared infrastructure such as the network, the event bus or central tables with CDK. It writes the values other services need as parameters into SSM Parameter Store, and the services themselves run on the Serverless Framework. In the serverless.yml you then read the values with ${ssm:/fahrradverleih/event-bus-arn}. What I would avoid: letting two tools manage the same resource.
Common mistakes when comparing tools
- Only comparing hello world. All three are fast in the example. Things get interesting with permissions, multiple stages and the tenth resource.
-
Forgetting the CDK bootstrap. Without
cdk bootstrap, the first deployment fails with a message about missing bootstrap resources. Run it once per account and region, including every additional region. - Checking the licence too late. With Serverless Framework v4, the question of the revenue threshold and subscription belongs before the first production deployment, not after it.
- Ignoring the SST state. The state bucket and the passphrase are part of your infrastructure. If you delete them or clean up the account without thinking of them, you lose track of the deployed resources.
-
Hotswap in production.
cdk deploy --hotswapandcdk watchare meant for development stacks. In production they create drift between the stack and reality.
By the way, you can look up which AWS service fits your API part in the AWS service finder. And if you want to see what the Serverless Framework looks like in a larger example, have a look at my async job pattern with 202 and SQS.
FAQ
Is the Serverless Framework still free?
For individuals and organisations with at most USD 2 million in annual revenue, yes. Larger companies need a subscription for v4. The CLI requires you to sign in either way. Version 3 is free but has not been maintained since the end of 2024.
Can I combine CDK and the Serverless Framework?
Yes. Both produce ordinary CloudFormation stacks. The cleanest way is to exchange values via SSM Parameter Store or CloudFormation exports and let exactly one tool manage each resource.
Does SST use CloudFormation?
No. Since v3, SST has used Pulumi as its deployment engine and can use Terraform providers through it as well. SST stores the state in an S3 bucket in your AWS account.
Which tool is best for beginners?
For pure Lambda projects, the Serverless Framework is the quickest to understand, because one YAML file is enough. If you write TypeScript anyway and plan a lot of AWS infrastructure in the long run, CDK is a good choice.
Do I need to change code when moving from SST v3 to v4?
Usually not. If you only use SST components without transforms or direct access to @pulumi/aws, the update plus sst refresh per stage is enough. With transforms, follow the migration guide for the Pulumi AWS provider v7.
Your next step
Take an hour and deploy the bike rental example with two of the three tools into a test account. Pay less attention to speed and more to one question: would my team still enjoy reading this code a year from now? And I am curious about your experience: which tool does your team use today, and would you make the same choice again?
Sources
- Serverless Framework: pricing and licence (v4)
- Serverless Framework: Upgrading to v4
- Serverless Framework: Building (built-in esbuild)
- Serverless Framework: Dev Mode
- Serverless Framework: License Keys
- AWS CDK v2 Developer Guide
- AWS CDK: Bootstrapping
- SST: documentation
- SST: ApiGatewayV2 component
- SST: State
- SST: Migrate from v3
- Tested on 26 Oct 2026 with Node.js 22.23, TypeScript 5.9.3, aws-cdk-lib 2.274.0 and esbuild 0.28.2: handler compiled and run locally, CDK stack synthesized (nodejs22.x, arm64, route
GET /bikes).serverless.ymlandsst.config.tswere checked for syntax but not deployed (Serverless Framework 4.45.0 and SST 4.17.2 are the current versions on npm). Deploy and curl outputs are examples.
This post was created with AI assistance.
👉 Next step: Working with AWS CDK? Grab my printable AWS CDK cheat sheet with commands, concepts and a stack skeleton.
Originally published on sascha-ms.de. More articles on serverless, AI in everyday development and leading tech teams: sascha-ms.de/en
來源:DEV Community · dev.to
