Skip to main content
Suga’s local development environment (suga dev) lets you build and test cloud applications entirely on your local machine without cloud access, accounts, or costs. This page explains how local development works, what’s emulated, and best practices for productive local workflows.

The Development Server

The suga dev command starts a local development server that:
  • Emulates cloud resources - Buckets, entrypoints, databases, schedules
  • Runs your services - Using the dev.script from your suga.yaml
  • Hot reloads code - Automatically restarts services when files change
  • Provides local URLs - Access your application at localhost ports
Start local development
suga dev
Example output
 Suga v0.0.1
   - App: my-app
   - Addr: :50051

Services

 Starting [api]

Entrypoints

 Starting [web] http://localhost:3000

Use Ctrl-C to exit

What Gets Emulated

Services

Your application services run locally using their dev.script:
suga.yaml
services:
  api:
    dev:
      script: npm run dev
  worker:
    dev:
      script: python main.py
Each service:
  • Runs as a separate process
  • Gets automatically restarted on code changes
  • Receives environment variables from suga.yaml
  • Can communicate with emulated resources

Buckets (Object Storage)

Buckets are emulated using the local filesystem:
project-root/
└── .suga/
    └── buckets/
        └── uploads/        # Bucket named "uploads"
            ├── file1.txt
            └── file2.jpg
Features:
  • Read/write/delete operations work like cloud storage
  • Files persist between suga dev sessions
  • Pre-seed buckets by placing files in .suga/buckets/{bucket-name}/
  • View files directly in the file explorer
SDK Operations: Use the generated Suga client to interact with buckets:
Works locally and in production
// Write file
await suga.uploads.write('file.txt', Buffer.from('Hello!'));

// Read file
const data = await suga.uploads.read('file.txt');

// Delete file
await suga.uploads.delete('file.txt');
Local behavior:
  • write() creates files in .suga/buckets/uploads/
  • read() reads from .suga/buckets/uploads/
  • delete() removes files from .suga/buckets/uploads/

Suga Client Libraries

Learn about generated client libraries for cloud-agnostic resource access

Entrypoints (HTTP Routing)

Entrypoints provide local HTTP servers with routing:
suga.yaml
services:
  api: ...
buckets:
  frontend: ...
entrypoints:
  web:
    routes:
      /api/: 
        name: api
      /: 
        name: frontend
Running suga dev will result in:
http://localhost:3000/api/    →  Routes to 'api' service
http://localhost:3000/        →  Routes to 'frontend' service
Features:
  • Path-based routing like production CDN
  • Request/response logging
  • CORS handling

Databases

PostgreSQL databases are automatically run locally:
suga.yaml
databases:
  main:
    access:
      api: [query]
    env_var_key: DATABASE_URL
Features:
  • Automatic PostgreSQL instance created per database
  • Connection strings injected into services via environment variables
  • Data persists between suga dev sessions
  • Full PostgreSQL compatibility for development
How it works: During suga dev, Suga:
  1. Starts a local PostgreSQL instance for each database using Docker
  2. Injects connection strings into services with access
  3. Makes databases available on local ports
Services receive the connection string exactly as they would in production:
Works locally and in production
import { Pool } from 'pg';

const pool = new Pool({
  connectionString: process.env.DATABASE_URL
});

await pool.query('CREATE TABLE IF NOT EXISTS users (id SERIAL PRIMARY KEY, name TEXT)');
await pool.query('INSERT INTO users (name) VALUES ($1)', ['Alice']);
const result = await pool.query('SELECT * FROM users');
console.log(result.rows);

The .suga Directory

Suga creates a .suga directory in your project for local state:
.suga/
├── buckets/           # Bucket contents
│   └── uploads/
├── logs/              # Service logs
│   ├── api.log
│   └── worker.log
└── dev.json          # Development server state
Add .suga/ to your .gitignore - this directory contains local development state and should not be committed.

Development Workflow

Starting Development

# Start all services and resources
suga dev

Making Code Changes

  1. Edit your service code - Changes are detected automatically
  2. Service restarts - Using a watcher in your dev script
  3. Test immediately - New code is running

Debugging Services

Standard debugging tools work normally:
  • Node.js
  • Python
  • Go
package.json
{
  "scripts": {
    "dev": "node --inspect src/index.js"
  }
}
Then connect Chrome DevTools or VS Code debugger to localhost:9229.

Viewing Logs

Service logs are written to .suga/logs/:
# Tail service logs
tail -f .suga/logs/api.log

# Or use your preferred log viewer
cat .suga/logs/api.log | grep ERROR

Seeding Local Data

Pre-populate buckets for testing:
# Create test files
mkdir -p .suga/buckets/uploads
echo "Test content" > .suga/buckets/uploads/test.txt

# Start dev server - files are available immediately
suga dev
Read pre-seeded data
const data = await suga.uploads.read('test.txt');
console.log(data); // "Test content"

Environment Variables

Services receive environment variables defined in suga.yaml:
suga.yaml
services:
  api:
    env:
      EXTERNAL_API_KEY: dev-key-12345
      DEBUG: "true"
    dev:
      script: npm run dev

databases:
  main:
    access:
      api: [query]
    env_var_key: DATABASE_URL  # Automatically injected during dev and production
During suga dev:
  • Service receives environment variables from env config
  • Database connection strings automatically injected based on env_var_key
  • Same variables are available in production (after Terraform deployment)
  • Use for configuration, feature flags, etc.
Use different values for local vs production by adding platform-specific overrides or using Terraform variables.

Service Communication

Direct service-to-service communication is coming soon. For now, services can communicate through shared databases, buckets or entrypoint URLs.

Limitations

Local emulation provides high fidelity but has some limitations:

Not Emulated

  • Cloud-specific features - Lambda layers, CloudFront behaviors, CDN caching
  • Scaling - Auto-scaling, load balancing across multiple instances
  • Managed services - Cloud-specific features like S3 lifecycle policies
  • Networking - VPCs, security groups, actual cloud networking

Performance Differences

  • Cold starts - Service cold starts don’t occur locally
  • Latency - No network latency between services
  • Resource limits - Local resources not limited like a deployed service (memory, timeout)

Workarounds

For features that can’t be emulated:
  1. Preview in cloud - Deploy to dev environment for testing
  2. Mock externals - Use mocks for cloud-specific APIs
  3. Integration tests - Test cloud features in CI/CD pipelines

Deployment Guide

Learn how to deploy to cloud environments for testing

Learn More