Skip to content

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:

  1. Stack Definition: Each logical component is defined as a separate stack
  2. Dependency Management: Stacks can reference outputs from other stacks
  3. 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

  1. AWS account with appropriate permissions
  2. AWS CLI configured locally
  3. Node.js and npm/yarn installed
  4. 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:

  1. Use Lambda provisioned concurrency for critical functions
  2. Implement proper TTL settings for DynamoDB tables
  3. Configure appropriate auto-scaling for RDS instances
  4. Use CloudFront caching to reduce Lambda invocations
  5. 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