Skip to content

Performance & Scaling ​

Resource Recommendations ​

DeploymentCPUMemoryDiskReplicas
Development2 cores4 GB50 GB1
Production (Small)4 cores8 GB100 GB2
Production (Medium)8 cores16 GB200 GB3-4
Production (Large)16+ cores32 GB+500 GB+5+

Horizontal Scaling ​

Alga scales horizontally when Valkey and RabbitMQ are configured:

  1. Deploy multiple backend replicas behind a load balancer
  2. Share PostgreSQL, Valkey, and RabbitMQ across replicas
  3. Configure SCHEDULER_LEADER_TTL (default: 15s) for leader election
  4. SSE fan-out works across replicas via Valkey pub/sub

Coordination Mechanisms ​

MechanismPurposeStorage
Leader electionSingle scheduler tick runnerValkey lease
Agent presenceTrack online agents across replicasValkey hash
SSE fan-outCross-replica event distributionValkey pub/sub
Atomic claimsPrevent double-dispatchPostgreSQL row lock
Disconnect graceHandle agent reconnectsValkey SET NX

Database Optimization ​

Connection Pooling ​

Use PgBouncer for connection management:

ini
[databases]
alga = host=postgres port=5432 dbname=alga

[pgbouncer]
pool_mode = transaction
max_client_conn = 200
default_pool_size = 25

Indexing ​

Key indexes (auto-created by Ent):

  • alerts.fingerprint — partial unique index (WHERE status != 'resolved')
  • alerts.status, alerts.severity — query filters
  • investigations.status, investigations.agent_id — scheduler lookups
  • incidents.service_id, incidents.status — service incident queries

Read Replicas ​

For read-heavy workloads:

  1. Set up PostgreSQL streaming replication
  2. Route read queries to replicas via PgBouncer
  3. Write queries go to primary

Valkey Optimization ​

Memory Management ​

  • Sessions: Short TTL (SESSION_EXPIRY_HOURS * 3600)
  • Agent presence: 90s TTL, renewed on heartbeat
  • SLA sorted sets: Entries removed on incident close
  • Correlation windows: TTL matches CORRELATION_WINDOW
  • On-call cache: 5-minute TTL

Persistence ​

For production:

  • Enable RDB snapshots for point-in-time recovery
  • Consider AOF for durability
  • Use Valkey Sentinel for HA

RabbitMQ Tuning ​

Queue Configuration ​

QueuePurposePrefetch
alga.alert.processAlert processing10
alga.investigate.processInvestigation dispatchMAX_CONCURRENT_INVESTIGATIONS (default 5)
alga.triage.processTriage decisions5
alga.incident.processIncident management1
alga.escalation.processEscalation processing5
alga.sla.sweepSLA breach detection1
alga.email.sendEmail delivery10
alga.notification-dispatch.processNotification dispatching10
alga.notification.sendNotification sending10
alga.audit.logAudit logging10

Retry Topology ​

Every domain (alert, investigate, triage, incident, escalation, notification-dispatch) shares a single authoritative retry schedule: four retry queues with exponential backoff, after which the message is dead-lettered to the terminal DLQ.

Stageretry.1retry.2retry.3retry.4Then
Backoff1min5min15min1hDead-letter

Each backoff has ±20% jitter applied so correlated failures do not re-deliver in lockstep. Tune retry behavior by adjusting the shared RetrySchedule in the RabbitMQ topology.

Consumer Scaling ​

Increase consumers per queue by deploying more backend replicas. Each replica runs its own consumer pool.

Backend Tuning ​

Argon2id ​

Password hashing is CPU-intensive. Tune for your hardware:

sh
ARGON2_MEMORY_KIB=65536   # 64 MiB per hash
ARGON2_TIME=3              # Iterations
ARGON2_PARALLELISM=2       # Parallel threads
MAX_CONCURRENT_PASSWORD_HASHES=4  # Default: 2 * NumCPU

Higher values = more secure but slower logins. MAX_CONCURRENT_PASSWORD_HASHES caps memory usage: value * ARGON2_MEMORY_KIB.

Scheduler ​

sh
SCHEDULER_LEADER_TTL=15s   # Leader lease
AGENT_PRESENCE_TTL=90s     # Agent presence
AGENT_DISCONNECT_GRACE=45s # Grace period
STALE_ALERT_THRESHOLD=15m  # Stale alert age
STALE_ALERT_SWEEP_INTERVAL=5m  # Sweep frequency

Frontend Optimization ​

The frontend is served by nginx with:

  • Gzip compression
  • Static asset caching (immutable, 1 year)
  • SPA routing via try_files

Vite Build ​

sh
pnpm --filter frontend build

Output is minified and tree-shaken. No additional optimization needed.

See Also ​

Released under the MIT License.