Performance
This document covers performance optimization techniques and configuration for SLOzy.
Cache Layer
SLOzy uses a two-tier caching system implemented in internal/cache/:
- In-memory cache (
sync.Map) — Ultra-fast access for frequently queried data - PostgreSQL-backed cache (
query_cachetable viainternal/cache/repository.go) — Persistent cache with compression
Configuration
type CacheConfig struct {
DefaultTTL time.Duration // Default entry time-to-live
MaxEntries int // Maximum cache entries
CleanupInterval time.Duration // Expired entry cleanup interval
EnableMemoryCache bool // Enable in-memory caching layer
EnableCompression bool // Compress cached results
CompressionThreshold int // Minimum bytes for compression
EnableWarmup bool // Preload popular entries on startup
AnalyticsRetention time.Duration // How long to keep analytics data
}Cache Statistics
Monitor cache effectiveness via GET /api/v1/cache/statistics. Aim for a hit rate above 85%.
Connection Pooling
PostgreSQL connection pool settings (internal/config/config.go):
| Setting | Default | Description |
|---|---|---|
POSTGRES_MAX_OPEN_CONNS | 25 | Maximum concurrent connections |
POSTGRES_MAX_IDLE_CONNS | 10 | Maximum idle connections in pool |
POSTGRES_CONN_MAX_LIFETIME | 1h | Maximum connection lifetime |
POSTGRES_CONN_MAX_IDLETIME | 10m | Maximum idle time before closing |
The pool is configured in internal/db/connection.go:
config.MaxConns = int32(cfg.PostgresMaxOpenConns)
config.MinConns = int32(cfg.PostgresMaxIdleConns)
config.MaxConnLifetime = 1800 * time.Second
config.MaxConnIdleTime = 600 * time.Second
config.HealthCheckPeriod = 1 * time.MinuteTune these values based on your workload and database capacity.
Query Optimization
- All queries use parameterized statements to avoid planning overhead
- Migrations include indexes on frequently queried columns (user_id, organization_id, slo_id, timestamps)
- The RBAC system uses a
check_permission()PostgreSQL function for efficient permission lookups - SLO calculations use range queries with indexed time windows
Rate Limiting
Rate limiting uses a token bucket algorithm (internal/middleware/security.go):
type RateLimiterConfig struct {
Enabled bool
GlobalRate int // requests per minute for all users
GlobalBurst int // burst size for global limiter
PerIPRate int // requests per minute per IP
PerIPBurst int // burst size per IP
Whitelist []string
Blacklist []string
}Default limits: 1000 global requests/minute (burst 50), 100 per-IP requests/minute (burst 10).
Build Size Optimization
The frontend uses Vite with React and Ant Design.
Lazy Loaded Routes
Routes are lazy-loaded to reduce initial bundle size. The frontend (frontend/src/) uses React Router for code splitting:
- Each route loads its component on demand
- Ant Design components are tree-shaken during build
Production Build
cd frontend && npm run build
# Output in frontend/dist/The Docker build uses multi-stage builds to minimize the final image size:
FROM golang:1.25.0-alpine AS builder
# ... build stage
FROM alpine:3.19
# ... minimal runtime stage