Serverless Deployment with SST
This document outlines the strategy and configuration for using SST.dev to implement fragmented deployment of the AI Agent Orchestration Platform.
Overview
SST (Serverless Stack) is an open-source framework that makes it easy to build serverless applications on AWS. It provides a unified way to define and deploy infrastructure as code, allowing for fragmented deployment where different components of the application can be deployed independently or together using a single configuration.
Key Benefits
- Infrastructure as Code: Define all infrastructure components in TypeScript/JavaScript
- Unified Deployment: Deploy frontend, backend, and infrastructure with a single command
- Local Development: Test serverless functions locally with hot reloading
- Selective Deployment: Deploy only specific components of the application
- Environment Management: Easily manage multiple environments (dev, staging, prod)
- AWS Integration: Seamless integration with AWS services
Architecture Components
SST allows defining and deploying the following components of the platform:
Frontend (Web Stack)
- Static site hosting with CloudFront and S3
- Next.js, React, or other frontend frameworks
- Environment variables injection
- Custom domains and SSL certificates
Backend API (API Stack)
- API Gateway and Lambda functions
- GraphQL APIs with AppSync
- WebSocket APIs
- Custom domains for APIs
Database (Database Stack)
- RDS for PostgreSQL
- DynamoDB tables
- Aurora Serverless
- ElastiCache
Storage (Storage Stack)
- S3 buckets for file storage
- CloudFront distributions for content delivery
- Lambda@Edge for edge computing
Authentication (Auth Stack)
- Cognito User Pools
- JWT authentication
- OAuth integrations
- Custom authentication flows
Monitoring (Monitoring Stack)
- CloudWatch Logs and Metrics
- X-Ray tracing
- Custom dashboards
- Alarms and notifications
Fragmented Deployment
SST enables fragmented deployment through its stack-based architecture:
- Stack Definition: Each logical component is defined as a separate stack
- Dependency Management: Stacks can reference outputs from other stacks
- Selective Deployment: Deploy specific stacks based on environment variables or flags
Implementation
Project Structure
meta-agent-platform/
├── sst.config.ts # Main SST configuration
├── stacks/ # Stack definitions
│ ├── API.ts # API stack
│ ├── Web.ts # Web frontend stack
│ ├── Database.ts # Database stack
│ ├── Storage.ts # Storage stack
│ ├── Auth.ts # Authentication stack
│ └── Monitoring.ts # Monitoring stack
├── packages/ # Application code
│ ├── functions/ # Lambda functions
│ ├── core/ # Shared business logic
│ └── web/ # Frontend application
└── scripts/ # Deployment scripts
└── fragmented-deploy.sh # Script for selective deployment
Stack Definitions
API Stack Example
// stacks/API.ts
import { StackContext, Api, use } from "sst/constructs";
import { Database } from "./Database";
export function API({ stack }: StackContext) {
const { table } = use(Database);
// Create API
const api = new Api(stack, "Api", {
defaults: {
function: {
bind: [table],
},
},
routes: {
"GET /agents": "packages/functions/src/agents/list.handler",
"POST /agents": "packages/functions/src/agents/create.handler",
"GET /workflows": "packages/functions/src/workflows/list.handler",
"POST /workflows": "packages/functions/src/workflows/create.handler",
"POST /workflows/{id}/execute": "packages/functions/src/workflows/execute.handler",
},
});
// Output API URL
stack.addOutputs({
ApiEndpoint: api.url,
});
return {
api,
};
}
Web Stack Example
// stacks/Web.ts
import { StackContext, NextjsSite, use } from "sst/constructs";
import { API } from "./API";
export function Web({ stack }: StackContext) {
const { api } = use(API);
// Create Next.js site
const site = new NextjsSite(stack, "Web", {
path: "packages/web",
environment: {
NEXT_PUBLIC_API_URL: api.url,
},
});
// Output website URL
stack.addOutputs({
SiteUrl: site.url,
});
return {
site,
};
}
SST Configuration
// sst.config.ts
import { SSTConfig } from "sst";
import { API } from "./stacks/API";
import { Web } from "./stacks/Web";
import { Database } from "./stacks/Database";
import { Storage } from "./stacks/Storage";
import { Auth } from "./stacks/Auth";
import { Monitoring } from "./stacks/Monitoring";
export default {
config(_input) {
return {
name: "meta-agent-platform",
region: "us-east-1",
};
},
stacks(app) {
// Deploy specific stacks based on environment variables
if (process.env.DEPLOY_DB === "true") {
app.stack(Database);
}
if (process.env.DEPLOY_API === "true" || !process.env.DEPLOY_API) {
app.stack(API);
}
if (process.env.DEPLOY_WEB === "true" || !process.env.DEPLOY_WEB) {
app.stack(Web);
}
if (process.env.DEPLOY_STORAGE === "true") {
app.stack(Storage);
}
if (process.env.DEPLOY_AUTH === "true") {
app.stack(Auth);
}
if (process.env.DEPLOY_MONITORING === "true") {
app.stack(Monitoring);
}
},
} satisfies SSTConfig;
Deployment Process
Prerequisites
- AWS account with appropriate permissions
- AWS CLI configured locally
- Node.js and npm/yarn installed
- SST CLI installed (
npm install -g sst)
Deployment Scripts
Full Deployment
#!/bin/bash
# deploy.sh - Deploy all components
ENV=$1
if [ -z "$ENV" ]; then
echo "Usage: ./deploy.sh [environment]"
echo "Example: ./deploy.sh dev"
exit 1
fi
echo "Deploying all components to $ENV environment..."
# Deploy using SST
npx sst deploy --stage $ENV
echo "Deployment complete!"
Fragmented Deployment
#!/bin/bash
# fragmented-deploy.sh - Deploy specific components
ENV=$1
COMPONENTS=$2
if [ -z "$ENV" ] || [ -z "$COMPONENTS" ]; then
echo "Usage: ./fragmented-deploy.sh [environment] [components]"
echo "Example: ./fragmented-deploy.sh dev 'api,web'"
exit 1
fi
echo "Deploying components $COMPONENTS to $ENV environment..."
# Set environment variables based on components
if [[ $COMPONENTS == *"api"* ]]; then
export DEPLOY_API=true
fi
if [[ $COMPONENTS == *"web"* ]]; then
export DEPLOY_WEB=true
fi
if [[ $COMPONENTS == *"db"* ]]; then
export DEPLOY_DB=true
fi
if [[ $COMPONENTS == *"storage"* ]]; then
export DEPLOY_STORAGE=true
fi
if [[ $COMPONENTS == *"auth"* ]]; then
export DEPLOY_AUTH=true
fi
if [[ $COMPONENTS == *"monitoring"* ]]; then
export DEPLOY_MONITORING=true
fi
# Deploy using SST
npx sst deploy --stage $ENV
echo "Fragmented deployment complete!"
CI/CD Integration
For automated deployments, integrate with GitHub Actions:
name: Deploy with SST
on:
push:
branches: [main]
workflow_dispatch:
inputs:
environment:
description: 'Environment to deploy to'
required: true
default: 'dev'
type: choice
options:
- dev
- staging
- prod
components:
description: 'Components to deploy (comma-separated)'
required: false
default: ''
type: string
jobs:
deploy:
runs-on: ubuntu-latest
name: Deploy
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm ci
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Deploy with SST
run: |
if [ -n "${{ github.event.inputs.components }}" ]; then
# Fragmented deployment
./scripts/fragmented-deploy.sh ${{ github.event.inputs.environment || 'dev' }} "${{ github.event.inputs.components }}"
else
# Full deployment
npx sst deploy --stage ${{ github.event.inputs.environment || 'dev' }}
fi
Local Development
SST provides a local development environment that simulates AWS services:
# Start local development environment
npx sst dev
# In another terminal, start the frontend
cd packages/web
npm run dev
Cost Optimization
To optimize costs when using SST with AWS:
- Use Lambda provisioned concurrency for critical functions
- Implement proper TTL settings for DynamoDB tables
- Configure appropriate auto-scaling for RDS instances
- Use CloudFront caching to reduce Lambda invocations
- Implement proper IAM policies to restrict access
Limitations and Considerations
- AWS Lock-in: SST primarily targets AWS services
- Cold Starts: Lambda functions have cold start times
- Execution Limits: Lambda has execution time limits (15 minutes)
- State Management: Serverless applications require special consideration for state
- Debugging: Debugging serverless applications can be more complex
References
Last updated: 2025-04-18