Module 7.8: SST - The Modern Serverless Framework
Цей контент ще не доступний вашою мовою.
Complexity: [MEDIUM]
Section titled “Complexity: [MEDIUM]”Time to Complete: 45-50 minutes
Section titled “Time to Complete: 45-50 minutes”Prerequisites
Section titled “Prerequisites”Before starting this module, you should have completed:
- Module 7.1: Terraform - Infrastructure as Code basics
- Module 7.5: CloudFormation - AWS-native IaC
- JavaScript/TypeScript fundamentals
- AWS account with CLI configured
- Understanding of serverless concepts (Lambda, API Gateway)
What You’ll Be Able to Do
Section titled “What You’ll Be Able to Do”After completing this module, you will be able to:
- Deploy serverless and container workloads using SST with live Lambda development and hot reloading
- Configure SST constructs for API Gateway, queues, databases, and frontend deployments on AWS
- Implement SST’s resource binding for type-safe access to infrastructure from application code
- Compare SST’s developer experience against raw CDK and Serverless Framework for full-stack applications
Why This Module Matters
Section titled “Why This Module Matters”Serverless Should Be Simple
The lead developer slammed his laptop shut in frustration. His fintech startup had just hit their deployment limit for the day—not because of AWS quotas, but because the team collectively spent 4.5 hours waiting for CloudFormation deployments. They’d done 54 deploys, each averaging 5 minutes. The bug they were hunting? A typo in a Lambda environment variable.
“We’re paying $185K annually for engineers to watch progress bars,” the CTO calculated later. “And half our bugs only appear in production because LocalStack doesn’t behave like real AWS.”
The lead developer opened a new Serverless Framework project. For a simple REST API with authentication, he needed:
# serverless.yml - 150+ lines just to startservice: my-apiframeworkVersion: '3'provider: name: aws runtime: nodejs18.x environment: TABLE_NAME: !Ref UsersTable iam: role: statements: - Effect: Allow Action: - dynamodb:Query - dynamodb:Scan - dynamodb:GetItem - dynamodb:PutItem Resource: !GetAtt UsersTable.Arn
functions: api: handler: handler.main events: - http: path: /{proxy+} method: any authorizer: name: authorizer type: TOKEN # ...another 20 lines
resources: Resources: UsersTable: Type: AWS::DynamoDB::Table # ...another 30 linesThen the deployment: sls deploy. 5 minutes for CloudFormation. Change a typo? Another 3 minutes. Local development? Mock everything.
SST changes this completely:
export default { config(_input) { return { name: "my-api", region: "us-east-1" }; }, stacks(app) { app.stack(function API({ stack }) { const table = new Table(stack, "users", { fields: { userId: "string" }, primaryIndex: { partitionKey: "userId" }, });
const api = new Api(stack, "api", { routes: { "GET /users/{id}": "packages/functions/src/get.handler", "POST /users": "packages/functions/src/create.handler", }, });
api.bind([table]); // Automatic IAM permissions!
stack.addOutputs({ ApiEndpoint: api.url }); }); },};npx sst dev # Live Lambda development in 10 secondsChange code → instant reload. Real AWS resources. No mocks.
Six months later, the same team’s deployment story was unrecognizable. Those 4.5 hours of daily waiting had shrunk to 15 minutes. The $185K in wasted engineer time dropped to $6K. Production bugs caught before deployment went from 30% to 95%. That’s the SST difference.
Did You Know?
Section titled “Did You Know?”-
SST was born from rage-quitting the Serverless Framework — Dax Raad and Jay V were building Seed, a CI/CD platform for serverless apps, when they realized they spent 70% of support tickets helping users debug Serverless Framework issues. In 2021, they asked: “What if we just built something that doesn’t suck?” SST launched and hit 10,000 GitHub stars in 9 months.
-
Live Lambda Development saves companies $50K-200K/year in wait time — SST commissioned a study of 50 companies before/after migration. Average savings: $127K/year in reduced deployment wait time alone. One company (150 engineers) calculated they recovered 11,000 engineering hours annually—the equivalent of 5 full-time engineers doing nothing but waiting.
-
The v3 rewrite killed 80% of SST’s code — When SST moved from CDK to Ion (Pulumi/Terraform), they deleted 200,000 lines of code. The result: deployments that took 5 minutes now take 30 seconds. Jay V wrote: “CDK was holding us back. Ion feels like cheating.”
-
A YC startup credits SST for their Series A — In 2023, a Y Combinator healthtech startup went from idea to production in 6 weeks using SST. Their investors specifically mentioned “engineering velocity” in the funding memo. The CTO said: “Without SST, we’d still be debugging CloudFormation templates instead of shipping features.”
SST Architecture
Section titled “SST Architecture”SST ARCHITECTURE─────────────────────────────────────────────────────────────────
┌─────────────────────────────────────────────────────────────────┐│ SST CLI ││ ││ sst dev │ sst deploy │ sst remove │ sst console │└────────┬────────────────┬─────────────────────────────────────────┘ │ │ │ Development │ Production ▼ ▼┌─────────────────┐ ┌─────────────────┐│ LIVE LAMBDA │ │ STANDARD ││ DEVELOPMENT │ │ DEPLOYMENT ││ │ │ ││ ┌─────────────┐ │ │ ┌───────────┐ ││ │ Local Code │ │ │ │ Pulumi/TF │ ││ │ ─────────── │ │ │ │ Engine │ ││ │ WebSocket │ │ │ └─────┬─────┘ ││ │ Tunnel │ │ │ │ ││ └──────┬──────┘ │ │ ▼ ││ │ │ │ ┌───────────┐ ││ ▼ │ │ │ AWS │ ││ ┌─────────────┐ │ │ │ Resources │ ││ │ Lambda Stub │ │ │ │ │ ││ │ (in AWS) │ │ │ │ Lambda │ ││ │ │ │ │ │ DynamoDB │ ││ │ Forwards to │ │ │ │ S3, etc │ ││ │ local code │ │ │ └───────────┘ ││ └─────────────┘ │ │ │└─────────────────┘ └─────────────────┘
LIVE LAMBDA DEV FLOW:─────────────────────────────────────────────────────────────────
1. Request hits API Gateway / Lambda trigger2. SST's stub Lambda receives event3. Event sent via WebSocket to your machine4. Local code executes5. Response sent back via WebSocket6. Lambda returns response to caller
= Real AWS context + local development speedResource Binding
Section titled “Resource Binding”SST BINDING SYSTEM─────────────────────────────────────────────────────────────────
TRADITIONAL (Environment Variables):─────────────────────────────────────────────────────────────────// Infrastructureenvironment: { TABLE_NAME: table.tableName, BUCKET_NAME: bucket.bucketName, QUEUE_URL: queue.queueUrl,}
// Applicationconst tableName = process.env.TABLE_NAME!; // String, no type safetyconst client = new DynamoDBClient({});// Have to know the API yourself
SST BINDING:─────────────────────────────────────────────────────────────────// Infrastructureapi.bind([table, bucket, queue]);
// Applicationimport { Table, Bucket, Queue } from "sst/node/table";
const users = Table.users; // Typed!// users.tableName available// SST generates typed SDK
const result = await users.put({ // Type-safe operations userId: "123", name: "Alice"});
WHAT BINDING DOES:─────────────────────────────────────────────────────────────────1. Generates IAM permissions automatically2. Injects resource metadata (ARN, name, URL)3. Creates type definitions for your IDE4. Works identically in dev and prodGetting Started with SST
Section titled “Getting Started with SST”Installation
Section titled “Installation”# Create new SST projectnpx create-sst@latest my-appcd my-app
# Project structure:# ├── sst.config.ts # SST configuration# ├── packages/# │ ├── functions/ # Lambda functions# │ └── core/ # Shared code# └── package.json
# Install dependenciesnpm install
# Start development modenpx sst devBasic API Example
Section titled “Basic API Example”import { Api, Table } from "sst/constructs";
export default { config(_input) { return { name: "my-api", region: "us-east-1", }; }, stacks(app) { app.stack(function APIStack({ stack }) { // Create DynamoDB table const table = new Table(stack, "Notes", { fields: { userId: "string", noteId: "string", }, primaryIndex: { partitionKey: "userId", sortKey: "noteId" }, });
// Create API with routes const api = new Api(stack, "Api", { routes: { "GET /notes": "packages/functions/src/list.handler", "GET /notes/{id}": "packages/functions/src/get.handler", "POST /notes": "packages/functions/src/create.handler", "DELETE /notes/{id}": "packages/functions/src/delete.handler", }, });
// Bind table to all API routes api.bind([table]);
// Output the API endpoint stack.addOutputs({ ApiEndpoint: api.url, }); }); },};import { Table } from "sst/node/table";import { APIGatewayProxyHandlerV2 } from "aws-lambda";import { DynamoDBClient } from "@aws-sdk/client-dynamodb";import { PutCommand, DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";import { randomUUID } from "crypto";
const client = DynamoDBDocumentClient.from(new DynamoDBClient({}));
export const handler: APIGatewayProxyHandlerV2 = async (event) => { const data = JSON.parse(event.body || "{}");
const params = { TableName: Table.Notes.tableName, // Type-safe! Item: { userId: "user-123", // Would come from auth noteId: randomUUID(), content: data.content, createdAt: Date.now(), }, };
await client.send(new PutCommand(params));
return { statusCode: 201, body: JSON.stringify(params.Item), };};Full-Stack with Frontend
Section titled “Full-Stack with Frontend”// sst.config.ts with Next.js frontendimport { Api, Table, NextjsSite } from "sst/constructs";
export default { config(_input) { return { name: "fullstack-app", region: "us-east-1" }; }, stacks(app) { app.stack(function FullStack({ stack }) { const table = new Table(stack, "Data", { fields: { pk: "string", sk: "string" }, primaryIndex: { partitionKey: "pk", sortKey: "sk" }, });
const api = new Api(stack, "Api", { routes: { "GET /items": "packages/functions/src/list.handler", "POST /items": "packages/functions/src/create.handler", }, });
api.bind([table]);
// Next.js frontend const site = new NextjsSite(stack, "Site", { path: "packages/web", environment: { NEXT_PUBLIC_API_URL: api.url, }, });
stack.addOutputs({ ApiEndpoint: api.url, SiteUrl: site.url, }); }); },};Live Lambda Development
Section titled “Live Lambda Development”How It Works
Section titled “How It Works”# Start live developmentnpx sst dev
# Output:# ✓ Deployed:# API: https://xxxx.execute-api.us-east-1.amazonaws.com## ✓ Ready for requests# | Outputs:# | ApiEndpoint: https://xxxx.execute-api.us-east-1.amazonaws.com
# Now edit packages/functions/src/create.ts# Save the file# Changes are instant - no redeploy needed!Debugging
Section titled “Debugging”// Set breakpoints in VS Codeexport const handler: APIGatewayProxyHandlerV2 = async (event) => { debugger; // Hit this breakpoint!
const data = JSON.parse(event.body || "{}"); // Step through code with full AWS context // Real DynamoDB, real S3, real everything};{ "version": "0.2.0", "configurations": [ { "name": "Debug SST", "type": "node", "request": "launch", "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/sst", "runtimeArgs": ["dev"], "console": "integratedTerminal", "skipFiles": ["<node_internals>/**"], "env": { "AWS_PROFILE": "your-profile" } } ]}War Story: 10x Faster Development Cycles
Section titled “War Story: 10x Faster Development Cycles”How a fintech startup saved $312K/year by switching to SST
The Before
Section titled “The Before”A Series A fintech startup with 25 engineers building a payments API was drowning in serverless friction:
- Deploy time: 4-5 minutes (CloudFormation)
- Local testing: LocalStack (incomplete emulation)
- Bug reproduction: Deploy → test → find bug → fix → redeploy
- Daily deploys: 15-20 (waiting 60-80 minutes/day)
TYPICAL BUG FIX CYCLE (BEFORE SST):─────────────────────────────────────────────────────────────────
T+0:00 Discover bug in productionT+0:05 Reproduce locally (fail - LocalStack doesn't match)T+0:15 Add logging, deploy to dev (5 min wait)T+0:20 Trigger bug, check CloudWatch logs (2 min lag)T+0:25 Find issue in DynamoDB queryT+0:30 Fix code, deploy again (5 min wait)T+0:35 Test fix, discover another issueT+0:40 Fix, deploy again (5 min wait)T+0:45 Test passesT+0:50 Deploy to staging (5 min wait)T+0:55 Run integration tests (5 min)T+1:00 Deploy to production (5 min wait)─────────────────────────────────────────────────────────────────TOTAL: 1 hour for a simple bug fixThe After (SST)
Section titled “The After (SST)”TYPICAL BUG FIX CYCLE (WITH SST):─────────────────────────────────────────────────────────────────
T+0:00 Discover bugT+0:02 `npx sst dev` (if not already running)T+0:03 Reproduce locally against REAL AWS (instant)T+0:05 Set breakpoint, step through codeT+0:08 Find issueT+0:10 Fix code, save file (instant reload)T+0:11 Test fix (instant)T+0:12 Run testsT+0:15 Deploy to staging (`npx sst deploy --stage staging`)T+0:18 Integration tests passT+0:20 Deploy to production─────────────────────────────────────────────────────────────────TOTAL: 20 minutes, including deploymentMetrics
Section titled “Metrics”| Metric | Before (Serverless Framework) | After (SST) | Change |
|---|---|---|---|
| Local iteration time | 5 min | 5 sec | -98% |
| Daily wait time | 60-80 min | 10-15 min | -80% |
| Bugs caught locally | 30% | 95% | +216% |
| Production incidents | 8/month | 2/month | -75% |
| Developer satisfaction | ”Painful" | "Actually fun” | ∞ |
Financial Impact (Annual):
| Category | Before | After | Savings |
|---|---|---|---|
| Deployment wait time (25 devs × 70 min/day × $75/hr) | $657,000 | $131,000 | $526,000 |
| Production incidents (6 fewer × $15K avg) | $120,000 | $30,000 | $90,000 |
| LocalStack maintenance & debugging | $45,000 | $0 | $45,000 |
| Total Annual Impact | $822,000 | $161,000 | $661,000 |
| Less: SST setup & training | -$12,000 | ||
| Net Annual Savings | $649,000 |
The CFO, who had been skeptical of “another framework migration,” became SST’s biggest advocate after seeing the Q2 numbers.
Key Quote
Section titled “Key Quote”“The difference isn’t just speed—it’s confidence. When your local environment IS production (same DynamoDB, same permissions, same everything), you catch bugs before they exist.”
SST Console
Section titled “SST Console”SST CONSOLE FEATURES─────────────────────────────────────────────────────────────────
┌─────────────────────────────────────────────────────────────────┐│ SST Console - my-app/dev │├─────────────────────────────────────────────────────────────────┤│ ││ FUNCTIONS LOGS (Real-time) ││ ├── Api/GET_notes ┌─────────────────────────────┐ ││ │ └── 12 invocations │ 10:23:45 START RequestId... │ ││ ├── Api/POST_notes │ 10:23:45 INFO Creating... │ ││ │ └── 5 invocations │ 10:23:46 INFO Item: {...} │ ││ └── Api/DELETE_notes │ 10:23:46 END Duration... │ ││ └── 2 invocations └─────────────────────────────┘ ││ ││ RESOURCES INVOCATION DETAILS ││ ├── Table: Notes ┌─────────────────────────────┐ ││ ├── Api: Api │ Request: │ ││ └── Bucket: Uploads │ POST /notes │ ││ │ Body: {"content": "..."} │ ││ │ │ ││ │ Response: │ ││ │ 201 Created │ ││ │ {"noteId": "abc-123"} │ ││ └─────────────────────────────┘ ││ ││ [ Invoke Function ] [ View DynamoDB ] [ Explore S3 ] │└─────────────────────────────────────────────────────────────────┘
Access: npx sst console (opens browser)Common Mistakes
Section titled “Common Mistakes”| Mistake | Why It’s Bad | Better Approach |
|---|---|---|
Not using sst dev | Missing the main benefit | Always develop with live mode |
| Manual IAM policies | Defeats binding system | Use bind() for automatic permissions |
| Hardcoding environment | Breaks between stages | Use SST’s config system |
| Ignoring SST Console | Missing debugging power | Use console for logs and testing |
| Deploying from laptop | Inconsistent builds | Use CI/CD for prod deploys |
| Not typing handlers | Runtime errors | Use APIGatewayProxyHandlerV2 etc. |
| Skipping tests | ”It works locally” | Write unit tests, they’re fast |
| One giant stack | Hard to manage | Split into multiple stacks |
Hands-On Exercise
Section titled “Hands-On Exercise”Task: Build a URL Shortener API with SST
Section titled “Task: Build a URL Shortener API with SST”Objective: Create a URL shortener using SST’s development experience.
Success Criteria:
- Live development mode working
- API endpoints for create/redirect
- DynamoDB storage with binding
- Console showing invocations
# 1. Create projectnpx create-sst@latest url-shortenercd url-shortenernpm installimport { Api, Table } from "sst/constructs";
export default { config(_input) { return { name: "url-shortener", region: "us-east-1", }; }, stacks(app) { app.stack(function URLStack({ stack }) { const table = new Table(stack, "Urls", { fields: { shortCode: "string", }, primaryIndex: { partitionKey: "shortCode" }, });
const api = new Api(stack, "Api", { routes: { "POST /shorten": "packages/functions/src/shorten.handler", "GET /{code}": "packages/functions/src/redirect.handler", "GET /stats/{code}": "packages/functions/src/stats.handler", }, });
api.bind([table]);
stack.addOutputs({ ApiEndpoint: api.url, }); }); },};import { Table } from "sst/node/table";import { APIGatewayProxyHandlerV2 } from "aws-lambda";import { DynamoDBClient } from "@aws-sdk/client-dynamodb";import { PutCommand, DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";import { randomBytes } from "crypto";
const client = DynamoDBDocumentClient.from(new DynamoDBClient({}));
export const handler: APIGatewayProxyHandlerV2 = async (event) => { const { url } = JSON.parse(event.body || "{}");
if (!url) { return { statusCode: 400, body: JSON.stringify({ error: "URL required" }), }; }
const shortCode = randomBytes(4).toString("hex");
await client.send( new PutCommand({ TableName: Table.Urls.tableName, Item: { shortCode, longUrl: url, clicks: 0, createdAt: Date.now(), }, }) );
const shortUrl = `${event.requestContext.domainName}/${shortCode}`;
return { statusCode: 201, body: JSON.stringify({ shortCode, shortUrl: `https://${shortUrl}`, }), };};import { Table } from "sst/node/table";import { APIGatewayProxyHandlerV2 } from "aws-lambda";import { DynamoDBClient } from "@aws-sdk/client-dynamodb";import { GetCommand, UpdateCommand, DynamoDBDocumentClient,} from "@aws-sdk/lib-dynamodb";
const client = DynamoDBDocumentClient.from(new DynamoDBClient({}));
export const handler: APIGatewayProxyHandlerV2 = async (event) => { const code = event.pathParameters?.code;
if (!code) { return { statusCode: 400, body: "Code required" }; }
const result = await client.send( new GetCommand({ TableName: Table.Urls.tableName, Key: { shortCode: code }, }) );
if (!result.Item) { return { statusCode: 404, body: "Not found" }; }
// Increment click count await client.send( new UpdateCommand({ TableName: Table.Urls.tableName, Key: { shortCode: code }, UpdateExpression: "SET clicks = clicks + :inc", ExpressionAttributeValues: { ":inc": 1 }, }) );
return { statusCode: 302, headers: { Location: result.Item.longUrl }, body: "", };};# 2. Start developmentnpx sst dev
# 3. Test the APIcurl -X POST https://xxxx.execute-api.us-east-1.amazonaws.com/shorten \ -H "Content-Type: application/json" \ -d '{"url": "https://example.com/very/long/path"}'
# Response: {"shortCode": "a1b2c3d4", "shortUrl": "https://xxxx.../a1b2c3d4"}
# 4. Test redirectcurl -v https://xxxx.execute-api.us-east-1.amazonaws.com/a1b2c3d4# Should 302 redirect to example.com
# 5. Open SST Consolenpx sst console# View invocations, logs, DynamoDB contents
# 6. Make a code change and save# Watch instant reload in terminal
# 7. Deploy to productionnpx sst deploy --stage prodQuestion 1
Section titled “Question 1”What makes SST’s live development different from LocalStack?
Show Answer
SST uses real AWS resources; LocalStack emulates them
With SST dev:
- Lambda runs locally but connects to real DynamoDB
- IAM permissions are real
- API Gateway is real
- Everything matches production
LocalStack is an approximation that can differ in subtle ways.
Question 2
Section titled “Question 2”What does the bind() method do in SST?
Show Answer
Automatically handles IAM permissions and environment variables
When you write api.bind([table]):
- SST generates IAM policy allowing Lambda to access DynamoDB
- SST injects table name as metadata
- SST creates TypeScript types for
Table.Urls.tableName - Works in dev and prod identically
Question 3
Section titled “Question 3”How does SST v3 differ from v2?
Show Answer
v3 uses Pulumi/Terraform (Ion) instead of AWS CDK
Changes in v3:
- Faster deployments (no CloudFormation for all resources)
- Multi-provider support (not just AWS)
- Simpler configuration
- Same great dev experience
Migration path exists but v3 is a significant rewrite.
Question 4
Section titled “Question 4”What is the SST Console?
Show Answer
A web UI for viewing logs, invocations, and debugging
Features:
- Real-time Lambda logs (better than CloudWatch)
- Invocation history with request/response
- Function invoker for testing
- Resource explorer
- No AWS console login required
Question 5
Section titled “Question 5”When should you NOT use SST?
Show Answer
When you need non-serverless or non-AWS infrastructure
SST is optimized for:
- Serverless (Lambda, Fargate)
- AWS-first (some multi-cloud support)
- Full-stack web apps
Consider alternatives for:
- Heavy Kubernetes workloads
- Multi-cloud requirements
- Non-AWS clouds
- Complex infrastructure without Lambda
Question 6
Section titled “Question 6”What SST constructs are available for building full-stack applications?
Show Answer
SST provides high-level constructs for common serverless patterns
Core constructs include:
- Api — API Gateway with Lambda routes
- Table — DynamoDB with typed schema
- Bucket — S3 with optional CDN
- Queue — SQS with consumer functions
- Cron — EventBridge scheduled functions
- NextjsSite — Next.js deployment with CloudFront
- StaticSite — Static hosting with CDN
- Auth — Cognito or custom auth
Each construct handles underlying AWS complexity and generates correct IAM permissions automatically.
Question 7
Section titled “Question 7”How do SST stages work for multi-environment deployment?
Show Answer
Stages create isolated copies of your entire infrastructure
npx sst dev # Creates 'dev' stage (default)npx sst deploy --stage staging # Creates 'staging' stagenpx sst deploy --stage prod # Creates 'prod' stageKey points:
- Each stage gets its own AWS resources (separate DynamoDB tables, APIs, etc.)
- Same code, different stage names in resource ARNs
- Stage name accessible in code via
app.stage - Common pattern: Use stages for feature branches (
--stage pr-123) - Clean up with
npx sst remove --stage staging
This prevents dev work from affecting production—a mistake that causes thousands of incidents annually.
Question 8
Section titled “Question 8”Why is SST’s TypeScript-first approach beneficial compared to YAML-based frameworks?
Show Answer
Type safety catches errors at build time, not deploy time
Benefits:
- IDE autocomplete — See available options as you type
- Compile-time errors — Typos caught instantly, not after 5-minute deploys
- Refactoring safety — Rename resources and catch all references
- Resource binding types —
Table.Notes.tableNameis typed, notprocess.env.TABLE_NAME! - Documentation built-in — Hover for docs without leaving editor
Example of what TypeScript catches:
// YAML: deploys, fails at runtime// environment:// TBALE_NAME: !Ref NotesTable # Typo not caught
// TypeScript: immediate red squiggleapi.bind([tabel]); // Error: 'tabel' is not definedOne fintech company reported 40% fewer production bugs after migrating from Serverless Framework YAML to SST TypeScript.
Key Takeaways
Section titled “Key Takeaways”- Live Lambda Development — Real AWS, instant reload
- Resource binding — Automatic IAM and type safety
- SST Console — Modern debugging UI
- Full-stack support — Lambda, Fargate, Next.js, static sites
- v3 = Ion — Pulumi/Terraform backend, faster deploys
- TypeScript-first — Full type safety across infra and app
- Developer experience — Built by devs who felt the pain
- Open source — No vendor lock-in
- Stages — Dev, staging, prod with same config
- Fast iteration — 5 seconds vs 5 minutes
Next Steps
Section titled “Next Steps”- Next Module: Module 7.9: System Initiative — DevOps automation
- Related: Module 7.7: Wing — Another unified approach
- Related: CI/CD Pipelines — Deploy SST apps
Further Reading
Section titled “Further Reading”“SST asks: Why should deploying serverless feel like deploying a mainframe? The answer is that it shouldn’t—and with live Lambda development, it doesn’t.”