Skip to main content

Performance Optimization

Optimize Borg UI for large repositories, fast archive browsing, and efficient backups.

Redis Cache Configuration

Redis caching provides 600x faster archive browsing for large repositories (60-90 seconds → 100ms).

Quick Performance Comparison

How Caching Works

Architecture (from app/services/cache_service.py):
  • Primary backend: Redis (persistent, distributed)
  • Fallback backend: In-memory LRU cache (automatic if Redis unavailable)
  • Compression: Automatic for archives 100KB (70-80% size reduction)
  • Cache key format: archive:{repo_id}:{archive_name}
Cache flow:
  1. First browse: Run borg list, serialize JSON, compress if 100KB, store in Redis
  2. Subsequent browses: Retrieve from Redis, decompress, deserialize → instant results
  3. Expiration: Entries auto-expire after TTL (default: 2 hours)
  4. Eviction: LRU eviction when cache size limit reached

Local Redis Setup (Included)

The recommended installation includes Redis with no configuration needed. docker-compose.yml (already configured):
Configuration:
  • maxmemory 2gb: Limit Redis memory usage
  • allkeys-lru: Evict least-recently-used keys when memory full
  • save "": Disable RDB snapshots (cache-only, not persistent)
  • appendonly no: Disable AOF (faster, cache can be rebuilt)
Redis is already configured in the recommended installation. No setup needed unless you need more than 2GB cache.

External Redis for Large Repositories

Use cases:
  • Repositories with 1M+ files
  • Multiple large archives
  • Need more than 2GB cache
  • Shared cache across multiple Borg UI instances
Setup on dedicated server (NAS/workstation):
Configure in Borg UI:
  1. Go to Settings → Cache
  2. Enter Redis URL: redis://192.168.1.100:6379/0
  3. Increase Max Cache Size to 20480 MB
  4. Click Save Settings
Verify connection:

Cache Statistics

View in UI:
  • Go to Settings → Cache
  • Shows: backend type, hit rate, memory usage, entry count, connection info
Implementation (app/services/cache_service.py:270-310):
Monitor via Redis CLI:

Operation Timeouts

Configure timeouts for Borg operations to handle large repositories and slow networks.

Default Timeouts

From app/config.py:90-98 and migration 053_add_operation_timeouts.py:

When to Increase Timeouts

Large repositories (100,000 files):
  • info_timeout: Increase to 1800s (30 min) for repositories with very large cache
  • list_timeout: Increase to 1800s if listing archives takes 10 minutes
Slow networks (remote SSH repositories):
  • mount_timeout: Increase to 300s (5 min)
  • info_timeout: Increase to 1800s (30 min)
  • list_timeout: Increase to 1800s (30 min)
Very large source directories:
  • source_size_timeout: Increase to 7200s (2 hours) for 100TB+ sources

Configure Timeouts

Via Web Interface (Recommended):
  1. Go to Settings → System
  2. Expand Operation Timeouts section
  3. Adjust timeout values
  4. Click Save Settings
Via Environment Variables:
UI settings in database take precedence over environment variables (from app/services/backup_service.py:32-72).
Timeout resolution order:
  1. Database settings (set via UI)
  2. Environment variables
  3. Config defaults

Memory Optimization

Redis Memory Management

LRU Eviction Policy: Redis uses allkeys-lru to automatically evict least-recently-used entries when maxmemory limit is reached. Memory calculation:
Set maxmemory based on usage:

In-Memory Cache Fallback

Configuration (app/services/cache_service.py:340-477):
  • Default size: 2GB (configurable via CACHE_MAX_SIZE_MB)
  • Automatic eviction: LRU (oldest entries removed when full)
  • No persistence: Lost on restart
When fallback activates:
  • Redis unavailable (connection refused, timeout)
  • Redis health check fails 3+ times consecutively
  • Redis URL set to disabled
Monitor fallback:

Browse Memory Limits

For very large archives (10M+ files): Browsing archives with millions of files can consume significant memory during JSON parsing. Monitor memory usage:
Mitigation strategies:
  1. Use Redis cache (parses once, serves from cache)
  2. Increase container memory limit
  3. Browse subdirectories instead of root
  4. Use Borg CLI for very large listings

Backup Performance

Parallel Backups

Maximum concurrent backups:
Increase for powerful servers:
Too many concurrent backups can saturate I/O and network. Monitor system resources before increasing.

Source Size Calculation

Purpose: Calculate total source size before backup for accurate progress percentage and ETA. Implementation (app/services/backup_service.py:433-567):
Performance impact:
  • Local directories: Fast (1 second for small, ~10 seconds for 1TB)
  • Remote SSH: Depends on network latency and remote disk speed
  • Very large sources (100TB+): Can take 30+ minutes
Optimization:
  • Runs in background (doesn’t block backup start)
  • Uses configurable timeout (source_size_timeout)
  • Skips if timeout exceeded (backup continues without ETA)
Disable size calculation:

Compression and Deduplication

Borg compression algorithms (set during repository creation): Recommendation:
Custom flags in UI: Go to Repository → Settings → Advanced → Custom Borg Flags:

Network Performance

SSH Multiplexing

Enable SSH connection sharing to speed up remote operations:
Apply configuration:
Benefits:
  • Reuses SSH connections (no re-authentication overhead)
  • Faster for repositories with many small operations
  • Reduces network latency

Bandwidth Limiting

Limit backup bandwidth for slow or metered connections:
Or via Borg environment:

Database Performance

SQLite Optimization

Borg UI uses SQLite for metadata storage. Current settings:
  • WAL mode: Enabled (concurrent reads during writes)
  • Journal mode: WAL (Write-Ahead Logging)
  • Synchronous: NORMAL (good balance of safety and speed)
Check database size:
Vacuum database (reclaim space):
Analyze for query optimization:

Migration Performance

Database migrations run on startup (from app/database/migrations/__init__.py:12-55):
Large databases may slow startup:
  • 72 migrations execute sequentially
  • Each migration checks for existing columns (idempotent)
  • First startup: 5-10 seconds
  • Subsequent startups: 1 second (migrations already applied)

Monitoring and Profiling

Performance Metrics

Cache hit rate:
Backup speed:
Repository statistics:

Log Analysis

Find slow operations:
Enable debug logging:
Debug logging is verbose and may impact performance. Use only for troubleshooting.

Performance Tuning Checklist

Cache:
  • External Redis with 8-20GB memory
  • Cache size: 8192-20480 MB
  • Cache TTL: 1440 minutes (24 hours)
  • Monitor hit rate 80%
Timeouts:
  • info_timeout: 1800s (30 min)
  • list_timeout: 1800s (30 min)
  • mount_timeout: 300s (5 min)
  • source_size_timeout: 7200s (2 hours)
Borg:
  • Compression: zstd,3 or lz4
  • Encryption: repokey-blake2 (faster than SHA256)
  • Regular borg compact to reclaim space
SSH:
  • SSH multiplexing enabled (ControlMaster auto)
  • Compression enabled in SSH config
  • SSH key authentication (no password delays)
  • Dedicated backup user (no shell overhead)
Network:
  • Bandwidth limiting if needed (--remote-ratelimit)
  • Consider using local mount for very large datasets
Timeouts:
  • Increase all timeouts by 2-3x for remote operations
  • Monitor for timeout errors in logs
Memory:
  • Borg UI: 2-4GB for large archive browsing
  • Redis: Match cache size + 500MB overhead
CPU:
  • No limit for backup operations (compression benefits from all cores)
  • Consider limiting for background jobs only
Example:

Cache Configuration

Detailed Redis setup and troubleshooting

Troubleshooting

Performance issues and solutions

Maintenance

Database optimization and cleanup

Configuration

Environment variables and system settings