DEV Community

Alex Spinov
Alex Spinov

Posted on

SST Has a Free API: Deploy Full-Stack Apps to AWS With TypeScript, Not CloudFormation

SST (Serverless Stack) lets you define and deploy full-stack apps on AWS using TypeScript. It abstracts CloudFormation into simple, composable constructs and provides a live development environment.

Why SST?

  • TypeScript infra — define AWS resources in TypeScript, not YAML
  • Live Lambda — live reload for Lambda functions during dev
  • Full-stack — frontend + API + database + auth in one framework
  • Components — high-level constructs for common patterns
  • Free — open source, you pay only for AWS

Quick Start

npx create-sst@latest my-app
cd my-app
npx sst dev  # Live development
npx sst deploy --stage prod  # Production deploy
Enter fullscreen mode Exit fullscreen mode

Define Infrastructure (TypeScript)

// sst.config.ts
export default $config({
  app(input) {
    return {
      name: 'my-app',
      removal: input.stage === 'prod' ? 'retain' : 'remove',
    };
  },
  async run() {
    // Database
    const table = new sst.aws.Dynamo('Users', {
      fields: { userId: 'string', email: 'string' },
      primaryIndex: { hashKey: 'userId' },
      globalIndexes: { emailIndex: { hashKey: 'email' } },
    });

    // API
    const api = new sst.aws.ApiGatewayV2('Api');
    api.route('GET /users', 'packages/functions/src/users.list');
    api.route('GET /users/{id}', 'packages/functions/src/users.get');
    api.route('POST /users', 'packages/functions/src/users.create');

    // Link resources
    new sst.aws.Function('CreateUser', {
      handler: 'packages/functions/src/users.create',
      link: [table],
    });

    // Frontend
    const site = new sst.aws.Nextjs('Web', {
      link: [api],
    });

    return { url: site.url, api: api.url };
  },
});
Enter fullscreen mode Exit fullscreen mode

Lambda Functions

// packages/functions/src/users.ts
import { Resource } from 'sst';
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { DynamoDBDocumentClient, PutCommand, GetCommand, ScanCommand } from '@aws-sdk/lib-dynamodb';

const ddb = DynamoDBDocumentClient.from(new DynamoDBClient({}));

export async function list() {
  const result = await ddb.send(new ScanCommand({
    TableName: Resource.Users.name,
  }));
  return { statusCode: 200, body: JSON.stringify(result.Items) };
}

export async function get(event: any) {
  const result = await ddb.send(new GetCommand({
    TableName: Resource.Users.name,
    Key: { userId: event.pathParameters.id },
  }));
  return { statusCode: 200, body: JSON.stringify(result.Item) };
}

export async function create(event: any) {
  const body = JSON.parse(event.body);
  await ddb.send(new PutCommand({
    TableName: Resource.Users.name,
    Item: { userId: crypto.randomUUID(), ...body },
  }));
  return { statusCode: 201, body: JSON.stringify({ success: true }) };
}
Enter fullscreen mode Exit fullscreen mode

Components

// Cron job
new sst.aws.Cron('DailyReport', {
  schedule: 'rate(1 day)',
  job: 'packages/functions/src/report.handler',
});

// Queue
const queue = new sst.aws.Queue('EmailQueue');
queue.subscribe('packages/functions/src/email.handler');

// Bucket
const bucket = new sst.aws.Bucket('Uploads');
bucket.subscribe('packages/functions/src/process.handler', {
  events: ['object_created'],
});

// Auth
const auth = new sst.aws.Auth('Auth', {
  authenticator: 'packages/functions/src/auth.handler',
});
Enter fullscreen mode Exit fullscreen mode

Key Features

Feature Details
Language TypeScript
Cloud AWS
Live dev Live Lambda for instant feedback
Components API, Database, Queue, Cron, Auth, etc.
Frameworks Next.js, Remix, Astro, SvelteKit
Deploys ~30 seconds (incremental)

Resources


Building on AWS? Check my Apify actors or email spinov001@gmail.com.

Top comments (0)