Performance Tuning
OpenLiteSpeed is fast by default. These settings push it further — from baseline to production-optimized.
Performance Baseline — Before You Tune
# Establish baseline response time
curl -w "TTFB: %{time_starttransfer}s | Total: %{time_total}s\n" \
-o /dev/null -s https://example.com/
# Check cache headers on a request
curl -I https://example.com/ | grep -iE "cache-control|etag|last-modified|x-cache"
# Check compression
curl -H "Accept-Encoding: gzip,br" -I https://example.com/ | grep -i "content-encoding"
# Check HTTP version
curl -I --http2 https://example.com/ 2>&1 | grep "HTTP/"
# Count requests per second (ab benchmark)
ab -n 1000 -c 10 https://example.com/ | grep "Requests per second"
HTTP/2 and HTTP/3 / QUIC
Enable HTTP/2 (httpd_config.conf — HTTPS listener)
listener HTTPS {
address *:443
secure 1
...
# Enable HTTP/2 via ALPN
alpn h2,http/1.1
}
Enable HTTP/3 / QUIC
listener HTTPS {
address *:443
secure 1
...
alpn h3,h2,http/1.1
# QUIC uses UDP — ensure UDP 443 is open in firewall
quic 1
quicShmDir /dev/shm
}
# Check firewall allows UDP 443 for QUIC
sudo ufw allow 443/udp
# Verify HTTP/2 is negotiated
curl -I --http2 https://example.com/ | head -1
# Expected: HTTP/2 200
# Verify HTTP/3 (needs curl with h3 support)
curl -I --http3 https://example.com/ | head -1
Compression
vhconf.conf — compression settings
# Enable gzip (broad compatibility)
enableGzip 1
# Enable Brotli (better ratio, modern browsers)
enableBr 1
# In httpd_config.conf — compression config block
compress {
# Minimum file size to compress
compressMinSize 1024
# Compress these MIME types
compressibleTypes text/html, text/css, text/javascript,
application/javascript, application/json,
application/xml, text/xml, image/svg+xml,
text/plain, application/xhtml+xml
# Cache compressed output
enableCache 1
}
Verify Compression
# Test gzip
curl -H "Accept-Encoding: gzip" -I https://example.com/ | grep "content-encoding"
# Test Brotli
curl -H "Accept-Encoding: br" -I https://example.com/ | grep "content-encoding"
# Check actual compressed size vs. uncompressed
curl -H "Accept-Encoding: gzip" -s https://example.com/ | wc -c
curl -s https://example.com/ | wc -c
LiteSpeed Cache (LSCache)
LSCache is OLS's built-in full-page cache. It works with the LSCache plugins for WordPress, Joomla, etc.
vhconf.conf — enable LSCache
# Enable the cache engine for this vhost
lsCache {
lscacheOn 1
privateCacheTimeout 60
publicCacheTimeout 86400
dynamicCacheTimeout 0
}
# Check LSCache is responding
curl -I https://example.com/ | grep -i "x-litespeed-cache"
# Expected header: X-LiteSpeed-Cache: hit
# Purge LSCache for a domain (if LSCache plugin installed)
# Usually done via WP admin or curl with purge request
curl -X PURGE https://example.com/
Cache Headers from .htaccess
.htaccess — browser caching
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType text/javascript "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
ExpiresByType application/x-font-woff "access plus 1 year"
ExpiresByType font/woff2 "access plus 1 year"
ExpiresDefault "access plus 1 week"
</IfModule>
# Cache-Control headers
<FilesMatch "\.(css|js|png|jpg|jpeg|gif|ico|webp|svg|woff|woff2)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
Connection Optimization (httpd_config.conf)
# ============================================================
# KEEP-ALIVE
# ============================================================
tuning {
maxKeepAliveReq 1000 # max requests per keep-alive
keepAliveTimeout 5 # seconds to wait for next request
sndBufSize 0 # 0 = OS default (auto)
rcvBufSize 0 # 0 = OS default (auto)
maxReqURLLen 32768 # max URL length
maxReqHeaderSize 65536 # max header size
maxReqBodySize 2G # max upload body
maxDynRespHeaderSize 32768
maxDynRespSize 2G
}
# ============================================================
# CONNECTION LIMITS
# ============================================================
connLimit {
maxConnections 20000 # total server-wide
maxSSLConnections 20000
connHardLimit 10000 # per IP hard limit
connSoftLimit 2000 # per IP soft limit (then throttle)
gracePeriod 15 # seconds before hard limit kicks in
banPeriod 300 # seconds to ban after hard limit
}
Static File Optimization
httpd_config.conf
# File descriptor cache (reduces open() syscalls)
fileCacheStat {
maxCacheEntries 4096
maxCacheFileSize 1M
maxSmallFileSize 4K
smallFileDefaultAge 10
largeFileDefaultAge 30
fileStatRefreshInterval 60
}
vhconf.conf — static file context
# Serve uploads directly as static
context /wp-content/uploads {
location /var/www/example.com/public/wp-content/uploads
allowBrowse 0
accessControl {
allow *
}
}
Reverse Proxy Caching (for Node.js / backend)
vhconf.conf — cache proxy responses
extprocessor node_app {
type proxy
address 127.0.0.1:3000
maxConns 100
persistConn 1
pcKeepAliveTimeout 60
}
context / {
type proxy
handler node_app
addDefaultCharset 0
}
Quick Wins Checklist
| Optimization | Impact | How |
|---|---|---|
| Enable Brotli | Medium | enableBr 1 in vhconf |
| Enable HTTP/2 | High | alpn h2,http/1.1 in listener |
| Enable OPcache | Very High | php.ini opcache.enable=1 |
| Enable LSCache | Very High | lscacheOn 1 in vhconf |
| Set browser cache headers | High | .htaccess Expires rules |
| Tune PHP worker count | Medium | PHP_LSAPI_CHILDREN in extprocessor |
Enable LSAPI_AVOID_FORK | Medium | Add to extprocessor env |
| Disable unused PHP extensions | Low | Remove from php.ini / conf.d |
| Enable file stat cache | Medium | fileCacheStat block |
Benchmarking
# ab (Apache Bench) — simple concurrency test
ab -n 5000 -c 50 https://example.com/
# wrk — modern HTTP benchmarking
wrk -t4 -c100 -d30s https://example.com/
# siege — stress test with multiple URLs
siege -c 25 -r 100 https://example.com/
# hey — simple Go-based load tester
hey -n 10000 -c 100 https://example.com/
# Check memory and CPU during load test
watch -n1 'ps aux | grep lshttpd | grep -v grep | head -5'
watch -n1 'free -m'