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