OTOBO / Znuny – Performance Optimization
In this in-depth guide, we cover all relevant layers for a scalable and high-performance OTOBO or Znuny installation:
- Index Modules for Ticket Queues
- Full-Text and Document Search (Internal & Elasticsearch)
- Article Storage Backends (DB vs. FS)
- Ticket Archiving
- Caching (Redis, Ramdisk)
- Database Tuning (MySQL/MariaDB)
- Hardware & Infrastructure
- Automation (Cron, Docker-Compose Scripts)
- Monitoring & Alerts
1. Ticket Index Module
1.1 RuntimeDB (Default)
- Module:
Kernel::System::Ticket::IndexAccelerator::RuntimeDB
- How it works: Dynamic queries directly on the
ticket
table - Use Case: Up to ~60k open tickets without noticeable latency
- Metric: Query-Time ∝ Number of Tickets ➔ linear increase
1.2 StaticDB (High-Scale)
Module:
Kernel::System::Ticket::IndexAccelerator::StaticDB
How it works: Pre-compiled
ticket_index
table with token columns (Subject, Status, Owner, and many more)Use Case: >80k open tickets, constant query times
Initial Indexing:
bash/opt/otobo/bin/otobo.Console.pl Maint::Ticket::QueueIndexRebuild
Cron Example: Daily rebuild at 02:30 AM
cron30 2 * * * /opt/otobo/bin/otobo.Console.pl Maint::Ticket::QueueIndexRebuild --force >> /var/log/otobo/queueindex.log 2>&1
Optimization Tips:
- Automatic partial rebuilds only for changed queues (SysConfig option)
- Monitoring the runtime: measure via the
time
command
2. Full-Text Search & Document Search
2.1 Internal Full-Text Index
Command for Rebuild:
bash/opt/otobo/bin/otobo.Console.pl Maint::Ticket::FulltextIndex --rebuild
Recommended SysConfig:
Setting Value Purpose Ticket::SearchIndex::IndexArchivedTickets 0 (off) Exclude archived tickets Ticket::SearchIndex::Attribute.WordCountMax 1000 Index the first 1000 words Ticket::SearchIndex::Filters Default Regex filter for special characters Ticket::SearchIndex::StopWords###Custom de, en Add custom stopwords Example Filter (SysConfig under Filters):
regexps#[,\&<>?"!*\|;\[\]()\+\$\^=]# #g # Remove special characters s#\b\S{1,2}\b##g # Delete words <3 characters
2.2 Elasticsearch (optional)
For large data volumes (>10M articles), Elasticsearch is recommended.
2.2.1 JVM Heap Size
# jvm.options
-Xms4g
-Xmx4g
- Set Min = Max to minimize GC pauses
- Max ≤ 50% of physical RAM
2.2.2 Disk Watermarks
cluster.routing.allocation.disk.watermark.low: "85%"
cluster.routing.allocation.disk.watermark.high: "90%"
cluster.routing.allocation.disk.watermark.flood_stage: "95%"
- low/high for shard allocation
- flood_stage sets indices to read-only
2.2.3 Mapping Optimizations
keyword
type for rarely changed fields (e.g., Ticket IDs)text
+analyzer
for free text
3. Article Storage Backends
Backend | Storage Location | Use Case |
---|---|---|
DB | MySQL/MariaDB | < 10k attachments, single-server |
FS | local FS / NFS / SAN | ≥ 10k attachments, multi-server, high IOPS |
3.1 Switching DB ↔ FS
/opt/otobo/bin/otobo.Console.pl Admin::Article::StorageSwitch --target ArticleStorageFS
- Check
/opt/otobo/var/log/article_storage.log
- Pay attention to permissions: user
otobo
(UID 1000)
4. Ticket Archiving
Reduces actively indexed datasets.
SysConfig:
Ticket::ArchiveSystem = 1
Set up a GenericAgent job:
- Limit: max. 5000 tickets per run
- Filter:
State = close
ANDChanged < now-6mon
Cron (weekly Mon 4:00 AM):
cron0 4 * * 1 /opt/otobo/bin/otobo.Console.pl Maint::Ticket::Archive --criteria State:close,Changed:-6m >> /var/log/otobo/archive.log
5. Caching
5.1 Redis Cache
Installation:
bashyum install redis systemctl enable --now redis
Perl Module:
cpan install Redis::Fast
SysConfig:
textCache::Module: Redis Cache::Redis###Server: 127.0.0.1:6379 Cache::Redis###DatabaseNumber: 0 Cache::Redis###RedisFast: 1
5.2 Ramdisk for /opt/otobo/var/tmp
mount -t tmpfs -o size=8G tmpfs /opt/otobo/var/tmp
# Add to /etc/fstab:
tmpfs /opt/otobo/var/tmp tmpfs nodev,nosuid,noexec,size=8G 0 0
6. Database Tuning (MySQL/MariaDB)
Edit /etc/my.cnf.d/otobo.cnf
:
[mysqld]
innodb_buffer_pool_size = 12G # 60% of 20G RAM
innodb_log_file_size = 1G # large transactions
innodb_flush_log_at_trx_commit = 2 # Performance/ACID compliance balance
max_connections = 500 # expected agents+API
thread_cache_size = 50 # reuse threads
query_cache_type = 0 # disabled (deprecated)
- Benchmark: TPC-C or sysbench for load tests
7. Hardware & Infrastructure
- CPU: ≥ 8 Cores for parallelism
- RAM: Sufficient for DB pool + JVM + caches
- Storage: NVMe SSDs in RAID10 (≥ 10k IOPS)
- Network: 10 GbE between frontend & DB
- Load-Balancer: HAProxy or NGINX with health checks
8. Automation & Backup Scripts
8.1 Docker-Compose Backup
Script: /usr/local/bin/otobo_backup.sh
#!/usr/bin/env bash
set -euo pipefail
DATE=$(date +"%Y%m%d_%H%M%S")
COMPOSE_FILE=/opt/otobo-docker/compose.yml
# Stop for consistency
docker compose -f "$COMPOSE_FILE" down
# Volumes & DB dump
tar -czf "/backups/volumes_$DATE.tar.gz" /var/lib/docker/volumes
mysqldump --single-transaction --quick --user=otobo --password="\$OTC_DB_PASS" otobo > "/backups/db_$DATE.sql"
# Start
docker compose -f "$COMPOSE_FILE" up -d
echo "Backup $DATE completed"
Cron (hourly):
0 * * * * /usr/local/bin/otobo_backup.sh >> /var/log/otobo/backup.log 2>&1
8.2 Cleaning Up Old Backups
#!/usr/bin/env bash
find /backups -type f -mtime +7 -delete
Cron: daily at 1:00 AM
9. Monitoring & Alerts
Prometheus Exporter:
otobo-agent
metrics (ResponseTime, QueueDepth)Grafana Dashboard:
- Query latency (95th percentile)
- Redis cache hits vs. misses
- InnoDB Buffer Pool Usage
- Elasticsearch shard status
Alert Rules:
- Slow Queries > 200 ms for > 5 min
- Disk Watermark > 90%
- Heap pauses > 100 ms
- DB Connections > 80% of
max_connections
Conclusion
With this comprehensive performance tuning plan covering the index, search, storage, cache, database, and infrastructure layers, you can achieve a stable and fast platform in OTOBO/Znuny that scales smoothly even with millions of tickets and articles.