Skip to main content

Scaling & Performance

Ever Works is designed to scale from single-instance development to multi-replica production deployments. This document covers the key scaling strategies and performance optimizations.

Compute Scaling

Kubernetes Horizontal Scaling

The API and Web deployments on DigitalOcean Kubernetes can be scaled independently:

kubectl scale deployment/ever-works-api --replicas=3
kubectl scale deployment/ever-works-web --replicas=3

The stateless architecture of both applications enables horizontal scaling without code changes. The API stores all persistent state in the database, and Git operations use per-request temporary works.

Trigger.dev Worker Scaling

Background generation tasks run on Trigger.dev workers, which scale independently from the API:

  • Machine sizes: micro, small-1x, small-2x, medium-1x, medium-2x, large-1x, large-2x
  • Configured via the TRIGGER_MACHINE environment variable.
  • Tasks can run for up to 5 hours (maxDuration: 3600 * 5).
  • Multiple tasks can execute in parallel on separate workers.

This offloads heavy AI pipeline processing from the API servers entirely.

Database Scaling

Multi-Database Support

Ever Works supports three database backends with different scaling characteristics:

DriverBest ForScaling Path
better-sqlite3Development, CLI, single-instanceVertical only (single writer)
postgresProductionConnection pooling, read replicas
mysql / mariadbProduction (alternative)Connection pooling, read replicas

PostgreSQL Connection Management

For PostgreSQL deployments, connection pooling is handled at the driver level through TypeORM's built-in pool:

// Connection via URL (supports connection parameters)
{
type: 'postgres',
url: 'postgresql://user:pass@host:5432/ever_works?sslmode=require',
}

// Direct host configuration
{
type: 'postgres',
host: 'localhost',
port: 5432,
username: 'postgres',
password: '',
database: 'ever_works',
}

DigitalOcean Managed PostgreSQL provides built-in connection pooling via PgBouncer, configurable through the DO dashboard.

Database SSL/TLS

Production PostgreSQL connections use SSL with a CA certificate:

if (config.database.sslMode()) {
baseConfig.ssl = getTlsOptions(true, config.database.databaseCaCert());
}

The CA certificate is provided as a base64-encoded environment variable (DATABASE_CA_CERT).

Caching Strategy

Database Cache

The CacheEntry entity provides a simple key-value cache with TTL support:

@Entity({ name: 'cache_entries' })
export class CacheEntry {
@PrimaryColumn('varchar')
key: string;

@Column('text')
value: string;

@Column({ type: 'bigint', nullable: true })
@Index()
expiresAt: number | null;
}

This is used for caching API responses, computed results, and configuration data. The expiresAt index enables efficient cleanup of expired entries.

Git Repository Caching

Cloned repositories are cached on the local filesystem to avoid re-cloning on every operation:

  • API Docker volume: /tmp/ever-works-repos -- persists across container restarts.
  • Clone-or-pull strategy: The Git facade first attempts a pull on an existing clone, falling back to a fresh clone if the work does not exist.

This significantly reduces I/O for frequent operations on the same work's repositories.

Concurrency Controls

Generation Pipeline

Item writing uses controlled concurrency to prevent filesystem and database overload:

const PARALLEL_WRITE_CONCURRENCY = 10;
await pMap(items, (item) => dataRepo.writeItem(item), {
concurrency: PARALLEL_WRITE_CONCURRENCY
});

Branch Synchronization

Website template branch syncing runs sequentially (concurrency = 1) because the clone-or-pull mechanism uses a deterministic work path based on owner+repo:

private readonly MAX_CONCURRENT_SYNCS = 1;

Parallel syncs to the same template repository would corrupt the local working work.

Rate Limiting

The API uses three-tier rate limiting via @nestjs/throttler:

TierWindowLimitPurpose
short1 second50 requestsBurst protection
medium10 seconds300 requestsSustained load protection
long60 seconds1000 requestsPer-minute cap

All three tiers are applied simultaneously. A request must pass all three checks to proceed.

Build Performance

Turborepo Caching

Turborepo orchestrates monorepo builds with dependency-aware caching:

pnpm build # Turborepo handles ^build dependency ordering

Unchanged packages are skipped based on content hash comparison, significantly reducing CI build times.

Docker Layer Caching

Docker builds use registry-based layer caching:

cache-from: type=registry,ref=ghcr.io/ever-works/ever-works-api:latest
cache-to: type=inline

Layers that have not changed (base image, dependency install) are reused from the previous build.

CI Runner Optimization

CI workflows run on ubicloud-standard-8 runners (8 cores), providing faster builds than standard GitHub-hosted runners.

Performance Monitoring

Sentry Performance

Sentry captures transaction traces with configurable sample rates:

  • Production: 10% of transactions and profiles.
  • Development: 100% (full visibility).

PostHog API Tracking

The PostHog interceptor tracks every API request with:

  • Response time (duration in milliseconds).
  • Endpoint pattern (normalized for grouping).
  • Status code distribution.

This data is available in PostHog dashboards for performance analysis.

Scaling Considerations

Git Operations

Git clone and push operations are I/O intensive and can be bottlenecks at scale:

  • Each generation run clones up to 3 repositories (data, markdown, website template).
  • The /tmp/ever-works-repos volume caches clones to reduce re-cloning.
  • For high-volume deployments, consider network-attached storage with high IOPS.

AI API Rate Limits

Generation tasks call external AI APIs (OpenAI, Anthropic, etc.) which have their own rate limits:

  • The pipeline system handles retries and backoff internally.
  • The circuit breaker pattern in the pipeline can degrade gracefully when providers are unavailable.
  • Consider multiple AI provider accounts for high-throughput generation.

Database Indexes

Key indexes are defined on entities to optimize common queries:

EntityIndexQuery Pattern
WorkGenerationHistory[workId, status]History by work and status
WorkSchedule[status, nextRunAt]Finding due schedules
UserSubscription[userId, status]Active subscription lookup
Notification[userId, isRead]Unread notification count
UsageLedgerEntry[userId, status]Billing aggregation