📑 Daftar Isi
- Backup First, Then Tune
- Basic Structure of httpd_config.xml
- Root Settings: Server Identity and Process
- Tuning Section: The Heart of Tweaking
- keepAliveTimeout
- keepAliveMax
- maxConnections
- maxSSLConnections
- connTimeout
- maxReqPerConn
- socketIdleTimeout
- staticReqPerSec
- dynReqPerSec
- bandwidthPerSec
- maxMemoryUsage
- privilege
- memTransferBufSize
- compressibleContentTypes & enableBr
- Logging Settings: Access Log and Error Log
- Example Optimized Config for a Mid-Range VPS
- Troubleshooting: When Tweaking Goes Wrong
- Pro Tips from the Field
- How to Apply Changes Without Downtime
- Monitoring After Tweaking
- Conclusion
I still remember the first time I had to tune a LiteSpeed server for a client who was complaining about slow website performance — and the VPS specs looked perfectly fine on paper. 4 cores, 8GB RAM, NVMe SSD. Everything seemed solid, but the time-to-first-byte was over 3 seconds. After digging through configs, the root cause wasn’t in PHP, wasn’t in MySQL — it was in LiteSpeed’s main configuration file which was still running all default values. One file: httpd_config.xml.
Think of httpd_config.xml as the dashboard of a high-performance car. Every critical component is configured here — how many connections it can handle, how long idle connections stay alive, memory limits, compression settings, and more. If you installed LiteSpeed and never touched this file, that’s like buying a sports car and never adjusting the suspension or throttle response. It’ll run, but you’re leaving serious performance on the table.
Many NOC engineers — even experienced ones — often overlook how powerful this file truly is. They focus on PHP-level tuning (OPcache, pm.max_children) or kernel-level tweaks (sysctl.conf), while LiteSpeed’s own configuration remains entirely at defaults. In this article, we’re going to dissect every parameter in /usr/local/lsws/conf/httpd_config.xml, explain what each one does, when you should change it, and what realistic values look like for different server environments.
Backup First, Then Tune
Before we start poking around, here’s rule number one: always backup first. Seriously, I’ve seen engineers edit configs without backup, mistype a value, and crash LiteSpeed entirely. The client’s server was down for 20 minutes all because they didn’t want to spend 10 seconds on a backup.
cp /usr/local/lsws/conf/httpd_config.xml /usr/local/lsws/conf/httpd_config.xml.bak-$(date +%Y%m%d)
After editing, if LiteSpeed refuses to start, just restore:
cp /usr/local/lsws/conf/httpd_config.xml.bak-20260727 /usr/local/lsws/conf/httpd_config.xml
/usr/local/lsws/bin/lswsctrl restart
Simple, right? This backup habit is what separates engineers whose servers rarely go down from those who get emergency calls at 3 AM.
Basic Structure of httpd_config.xml
Generally, the httpd_config.xml file has several main sections:
- Root settings — serverName, user, group, priority, CPUAffinity
- tuning — the heart of it all, where most tweaking happens
- accessLog & errorLog — logging configuration
- indexFiles & autoindex — index file handling
- mimeTypes — content type mapping
We’ll cover each section in depth, but the primary focus is the tuning section since that’s where tweaking has the most direct impact on server performance.
Root Settings: Server Identity and Process
serverName
This parameter sets the server identity name displayed in the HTTP response header. The default is usually LiteSpeed. From a security standpoint, it’s good practice to change this to something that doesn’t immediately identify LiteSpeed — attackers can fingerprint your server from this header.
<serverName>web-prod-01</serverName>
user & group
Determines which user and group the LiteSpeed worker process runs under. Make sure this user has sufficient permissions to access website document roots, but never use root. If you’re on cPanel, this is typically set to nobody:nobody or lsadm:lsadm. If you’re running CloudLinux, ensure CageFS is compatible with this user.
priority
Sets the Nice value for the LiteSpeed process. The range is -20 (highest priority) to 19 (lowest priority). Default is usually 0. In shared hosting environments, you might want to set this to a positive value (like 5 or 10) so LiteSpeed doesn’t starve other critical services. But on a dedicated server where LiteSpeed is the primary service, 0 or even a negative value can help.
CPUAffinity
Determines which CPU cores the main LiteSpeed process can use. A value of 0 means no affinity restriction — the process can run on any core. If your server has many cores and you want to reserve some for other services (like MySQL), you can set this. But for most cases, leave it at 0 and let the OS scheduler handle it.
Tuning Section: The Heart of Tweaking
This is the critical section. Every parameter here directly affects how LiteSpeed handles connections, memory, and throughput. Let’s break them down one by one.
keepAliveTimeout
This parameter determines how many seconds a TCP connection stays alive after the last request completes. The default is usually 5 seconds.
The concept is straightforward: if a browser is loading a page with many resources (images, CSS, JS), keep-alive allows all those resources to be loaded over a single TCP connection without repeatedly opening and closing connections. This saves TLS handshake overhead on HTTPS.
This is where many engineers make mistakes. If keepAliveTimeout is too high (say 60 seconds), idle connections still consume resources — file descriptors, some memory, and connection slots. If too low (say 1 second), the browser must frequently re-handshake, which adds latency especially on HTTPS.
| Scenario | Recommended Value | Reason |
|---|---|---|
| Shared hosting / high traffic | 3-5 | Saves file descriptors and memory per idle connection |
| VPS with moderate traffic | 5-10 | Balance between performance and resource usage |
| Dedicated, low traffic | 10-15 | More persistent connections, less overhead |
| API / WebSocket heavy | 30-60 | Connections need to stay alive longer for long-polling |
<keepAliveTimeout>5</keepAliveTimeout>
keepAliveMax
Determines the maximum number of requests allowed over one keep-alive connection before it’s closed. Default is usually 100.
This acts as a safety net — preventing a single TCP connection from monopolizing a worker thread for too long. In most scenarios, 100 is fine. But if you’re experiencing issues where one client consumes too many requests (like a crawling bot), lowering this to 50 can help distribute worker threads more evenly.
Don’t set it too low (like 5) because modern browsers typically fetch many resources simultaneously — a single WordPress page can easily generate 30-50 HTTP requests. If keepAliveMax is too low, connections will drop frequently and the browser must open new ones, adding latency especially on HTTPS.
maxConnections
This is one of the most critical parameters. It determines the maximum number of simultaneous TCP connections LiteSpeed can accept. Default is usually 5000.
Important: this isn’t the number of users, but the number of TCP connections. A single browser user can open 6-8 simultaneous connections (due to HTTP/2 and parallel loading). So maxConnections must be large enough to handle your peak concurrent users, multiplied by a factor of 6-8.
Use this simple formula to calculate the right value:
maxConnections = (peak_concurrent_users × 6) + 20%
safety_margin
Example:
- Peak concurrent users: 200
- Need: 200 × 6 = 1200
- With 20% safety margin: 1200 × 1.2 = 1440
- Round up to 1500
But remember — maxConnections also depends on the OS file descriptor limit. If you set maxConnections = 5000 but ulimit -n is only 1024, LiteSpeed still can’t accept more than 1024 connections. Make sure you also set the appropriate file descriptor limit in /etc/security/limits.conf.
maxSSLConnections
Same concept as maxConnections, but specifically for SSL/TLS connections. Default is usually 2000. SSL connections are heavier on resources because they require additional memory for SSL session buffers. In today’s HTTPS-mandatory world, most of your traffic is going through SSL.
Rule of thumb: set maxSSLConnections to at least 80% of maxConnections. If all your traffic is HTTPS (which is standard now), set both to the same value. If there’s also plain HTTP traffic, maxSSLConnections can be slightly lower.
Watch out for memory footprint. Each SSL connection consumes roughly 15-30KB of RAM for TLS buffers. So if maxSSLConnections is 5000, be prepared to allocate at least 150MB of RAM just for SSL buffers — and that’s before content serving memory.
connTimeout
Determines how many seconds LiteSpeed will wait before closing a connection that hasn’t sent any request. Default is usually 300 seconds (5 minutes).
This differs from keepAliveTimeout. KeepAliveTimeout starts counting after the last request completes. ConnTimeout starts from when the TCP connection is first established — including time before the first request is sent. This is crucial for preventing slowloris attacks, where an attacker opens many connections but never completes an HTTP request.
For high-traffic servers, 300 seconds may be too long. Consider lowering to 60–120 seconds. But don’t go too low (like 10 seconds) because slow clients on poor networks may need more time to send their first request.
maxReqPerConn
Determines the maximum number of requests allowed per TCP connection. Default is usually 10000. This differs from keepAliveMax — maxReqPerConn is a hard limit at the TCP level, while keepAliveMax is a soft limit at the HTTP keep-alive level.
In practice, you almost never need to change this. The default 10000 is very generous. This parameter is more relevant as a safety limit against abusive clients performing aggressive request pipelining.
socketIdleTimeout
Determines how many seconds an established socket that hasn’t started HTTP communication will be closed. Default is usually 300 seconds. This differs from connTimeout because it focuses on idle time after TCP handshake but before the first HTTP request.
In production, this value typically doesn’t need changing from default. But if you’re experiencing SYN floods or connection exhaustion, lowering it to 30–60 seconds can help reduce zombie connections consuming resources.
staticReqPerSec
Determines the maximum requests per second allowed for static resources (images, CSS, JS, fonts) per connection. Default 0 means unlimited.
This parameter is very useful for preventing a single client from monopolizing server bandwidth for static file downloads. In shared hosting, this can be a lifesaver — without this limit, one user could consume all server bandwidth just repeatedly downloading large ZIP files.
However, if you implement this limit, make sure the value is still high enough for normal users. A single modern web page can request 20-30 static resources in seconds, so setting it too low will worsen page load times. Values of 50–100 are generally safe for most cases. Set 0 if you don’t have abuse issues.
dynReqPerSec
Same concept as staticReqPerSec, but for dynamic requests (PHP, Python, CGI). Default 0 (unlimited). This is more sensitive because dynamic requests consume worker threads and CPU time. In shared hosting with CloudLinux, this parameter is extremely helpful for preventing one account from draining the entire LiteSpeed worker pool.
Common values: 20–50 per connection. But if you’re running LiteSpeed with CloudLinux, you might already have per-user limits via LVE. In that case, leave it at 0 and let CloudLinux handle it.
bandwidthPerSec
Limits total bandwidth allowed per second. Default 0 means unlimited. This can be set globally (httpd_config.xml) or per virtual host.
For shared hosting, you might want to set per-virtual-host limits instead of global. But if you’re hit with sudden abuse and need quick throttling, a global setting can serve as a temporary fix.
<bandwidthPerSec>0</bandwidthPerSec> <!-- unlimited -->
maxMemoryUsage
Determines the maximum percentage of memory LiteSpeed is allowed to use. Default 0 means no limit. If you set this to say 80, LiteSpeed will start rejecting new requests when memory usage exceeds 80% of total server RAM.
This parameter is absolutely critical for preventing OOM (Out of Memory) situations. I once handled a case where LiteSpeed consumed 95% of RAM because a WordPress site had heavy plugins and high concurrent visitors. The server OOMed and everything went down — LiteSpeed, MySQL, even SSH. If maxMemoryUsage had been set to 80, LiteSpeed would have rejected new requests before running out of memory, and at minimum the other services would have stayed up.
privilege
Determines whether LiteSpeed drops privileges after binding to ports. Default 1 means privilege dropping is active — LiteSpeed binds to port 80/443 as root, then drops to the configured user (nobody or whoever is set). This is important for security. Never set to 0 unless you fully understand the consequences.
memTransferBufSize
Determines the buffer size (in bytes) for transferring data from worker to client. Default is usually 4096 (4KB). Larger values can improve throughput for large file transfers, but also increase memory usage per connection.
For most cases, the default 4096 is sufficient. If your server handles lots of large file downloads (like file sharing), you could increase to 8192 or 16384. But for regular websites with small content, this change won’t be noticeably impactful.
compressibleContentTypes & enableBr
Determines which content types can be compressed by LiteSpeed. The default typically includes text/html, text/css, text/javascript, application/javascript, application/json, and more. Make sure you don’t include already-compressed content types (like image/jpeg, image/png, video/mp4) because compressing already-compressed files just wastes CPU with zero benefit.
enableBr determines whether Brotli compression is active. Default 1 (active). Brotli generally provides better compression ratios than gzip, especially for HTML, CSS, and JavaScript. Keep it enabled unless there’s a specific reason not to (like compatibility with very old clients).
<compressibleContentTypes>text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json,application/xml</compressibleContentTypes>
<enableBr>1</enableBr>
Logging Settings: Access Log and Error Log
accessLog
Configures the location and format of the access log. Good logging is the key to troubleshooting. Never disable access logs in production — it’s an investment in your future debugging sanity.
<accessLog>
<logs>/var/log/lsws/accesslog</logs>
<compactLog>0</compactLog>
</accessLog>
compactLog = 1 reduces log size by dropping some less important fields. On production servers with high traffic, this can save significant disk space. But during troubleshooting, compact logs sometimes lack detail.
errorLog
Error logs are your best friend during problems. Set logLevel to NOTICE for production, or DEBUG temporarily while troubleshooting.
<errorLog>
<logs>/var/log/lsws/errorlog</logs>
<logLevel>NOTICE</logLevel>
<debugLevel>0</debugLevel>
<rolloverSize>10M</rolloverSize>
<keepDays>30</keepDays>
</errorLog>
rolloverSize determines when the log file gets rotated (default 10MB). keepDays determines how many days old logs are kept before deletion. For certain compliance requirements, you might need 90 days or more. Make sure your disk space is sufficient.
Often overlooked: make sure log rotation is also configured in crontab or logrotate, not just within LiteSpeed. If you only rely on LiteSpeed’s rolloverSize, log files can sometimes grow large before rotation kicks in.
Example Optimized Config for a Mid-Range VPS
Here’s a tweaked configuration for a VPS with 4 cores, 8GB RAM, targeting 100 concurrent users, and mixed traffic (static + PHP):
<?xml version="1.0" encoding="UTF-8"?>
<httpdConfig>
<serverName>web-prod-01</serverName>
<user>nobody</user>
<group>nogroup</group>
<priority>0</priority>
<CPUAffinity>0</CPUAffinity>
<autoStart>0</autoStart>
<tuning>
<keepAliveTimeout>5</keepAliveTimeout>
<keepAliveMax>100</keepAliveMax>
<maxConnections>1500</maxConnections>
<maxSSLConnections>1500</maxSSLConnections>
<connTimeout>120</connTimeout>
<maxReqPerConn>10000</maxReqPerConn>
<socketIdleTimeout>120</socketIdleTimeout>
<staticReqPerSec>0</staticReqPerSec>
<dynReqPerSec>0</dynReqPerSec>
<bandwidthPerSec>0</bandwidthPerSec>
<maxMemoryUsage>80</maxMemoryUsage>
<privilege>1</privilege>
<memTransferBufSize>4096</memTransferBufSize>
<compressibleContentTypes>text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json,application/xml</compressibleContentTypes>
<enableBr>1</enableBr>
</tuning>
<accessLog>
<logs>/var/log/lsws/accesslog</logs>
<compactLog>0</compactLog>
</accessLog>
<errorLog>
<logs>/var/log/lsws/errorlog</logs>
<logLevel>NOTICE</logLevel>
<debugLevel>0</debugLevel>
<rolloverSize>10M</rolloverSize>
<keepDays>30</keepDays>
</errorLog>
</httpdConfig>
Troubleshooting: When Tweaking Goes Wrong
Sometimes after tweaking, performance actually degrades or new errors appear. Here are common issues I’ve encountered and their solutions:
| Problem | Likely Cause | Solution |
|---|---|---|
| LiteSpeed won’t start after config edit | XML syntax error or invalid value | Run xmllint --noout /usr/local/lsws/conf/httpd_config.xml to validate syntax. Restore backup if needed. |
| “Too many open files” error | maxConnections exceeds ulimit -n | Increase ulimit in /etc/security/limits.conf and restart server. Or lower maxConnections. |
| Server using too much RAM | maxSSLConnections too high or maxMemoryUsage not set | Set maxMemoryUsage to 80. Reduce maxSSLConnections. Monitor with free -m. |
| Website feels slower after tweaking | keepAliveTimeout too low or maxConnections too low | Increase keepAliveTimeout to 5-10. Gradually increase maxConnections. Monitor response time. |
| 503 Service Temporarily Unavailable | maxConnections or maxSSLConnections exhausted | Increase limits. Check who’s consuming connections with netstat -an | grep :443 | wc -l |
| Worker process keeps crashing | privilege set to 0 or permission issues | Ensure privilege = 1. Check error log at /var/log/lsws/errorlog for crash details. |
Pro Tips from the Field
Some things that aren’t written in LiteSpeed documentation but are critical from handling hundreds of servers:
- Tune gradually. Don’t change all parameters at once. Change one or two, monitor the impact for 24-48 hours, then move to the next. If you change 10 parameters simultaneously and performance drops, you’ll never know which one caused it.
- Benchmark before and after. Record baseline performance metrics (response time, TTFB, concurrent connections) before tweaking. Without a baseline, you’ll never know if your tweaks actually helped.
- Don’t forget file descriptor limits. I’ve seen engineers set maxConnections high but forget to raise ulimit. Result? LiteSpeed is still limited by the OS.
- Check the admin config too. Besides httpd_config.xml, there’s also the admin listener config that can affect performance. Make sure the admin port doesn’t conflict with production config.
- Use LiteSpeed Load Tester. LiteSpeed provides a free load testing tool. Use it to benchmark before and after tweaking instead of just relying on gut feeling.
Important addition: if you’re running LiteSpeed with cPanel, make sure you also check per-virtual-host configurations. Settings in httpd_config.xml are global defaults, but can be overridden per virtual host in each vhconf.xml file. For a complete guide on installing LiteSpeed with cPanel, check out the LiteSpeed cPanel installation guide.
And if you want to optimize LiteSpeed’s cache for WordPress, don’t miss the LiteSpeed Cache for WordPress guide — there’s a direct relationship between httpd_config.xml tuning and how LiteSpeed Cache interacts with worker threads.
How to Apply Changes Without Downtime
After editing httpd_config.xml, you need to restart or reload LiteSpeed. There are two options:
# Graceful restart (recommended) - won't disconnect active connections
/usr/local/lsws/bin/lswsctrl graceful
# Full restart - disconnects all connections
/usr/local/lsws/bin/lswsctrl restart
Use graceful in production because it won’t interrupt active user connections. Full restart is only needed for fundamental changes (like changing user/group or chroot settings).
Alternative: you can also reload from the LSWS WebAdmin Console on port 7080. Log in to https://server-ip:7080, click “Graceful Restart” in the menu. But I prefer the command line — it’s faster and can be automated with scripts.
Monitoring After Tweaking
After tweaking, don’t just walk away. Monitor for at least 1-2 hours to ensure there are no anomalies. Watch for:
- Response time — should be stable or better than before
- Error rate — should not increase significantly
- Memory usage — make sure it’s not approaching limits
- Open connections —
netstat -an | grep ESTABLISHED | wc -l - Error log — check for any new errors appearing
For more serious monitoring, consider tools like Netdata, Grafana + Prometheus, or even a simple setup with sar and dstat. What matters is having a baseline and being able to spot trend changes.
If you’re managing VPS infrastructure for clients, also check out the broader VPS web server optimization guide for tuning strategies that go beyond just LiteSpeed.
Conclusion
The httpd_config.xml file is where you can truly make LiteSpeed perform at its best for your specific server needs. Of all the parameters, the main focus should be on maxConnections, maxSSLConnections, keepAliveTimeout, connTimeout, and maxMemoryUsage — these five alone can deliver significant improvement when configured correctly.
Remember, there’s no one-size-fits-all value. Every server has its own characteristics — concurrent user count, content type, hardware specs. What works for Server A may not work for Server B. That’s why benchmarking and monitoring are the keys to successful tuning.
Now you have complete knowledge of what happens under the hood of LiteSpeed’s configuration. Use it wisely, and never forget to backup before tweaking. If you have questions or your own experiences with LiteSpeed tweaking, share them in the comments — you might help another engineer facing similar issues.
Q: Do I need to restart LiteSpeed every time I edit httpd_config.xml?
Yes, every change in httpd_config.xml requires a restart or reload to take effect. Use /usr/local/lsws/bin/lswsctrl graceful for a graceful restart that doesn’t disconnect active connections. Some parameters can be changed from the WebAdmin Console without manual restart, but for significant tuning changes, a restart is still recommended.
Q: What’s the difference between maxConnections and keepAliveMax?
maxConnections is the maximum number of simultaneous TCP connections LiteSpeed accepts overall. keepAliveMax is the limit on how many HTTP requests can be sent over one keep-alive connection before it closes. maxConnections controls overall server capacity, while keepAliveMax controls how long a single connection persists.
Q: I’m on shared hosting with cPanel — can I edit httpd_config.xml?
Usually not. In shared hosting, access to httpd_config.xml is restricted by the server administrator. What you can tweak is PHP configuration and .htaccess. If you’re a server admin or VPS owner, then you have full access to this file. For a complete guide on LiteSpeed installation with cPanel, read the LiteSpeed cPanel installation article.
Q: After tweaking, my website became slower. Why?
Several possibilities: (1) maxConnections is too low so requests are being rejected, (2) keepAliveTimeout is too low so connections drop frequently and must re-handshake, (3) maxMemoryUsage is too low so LiteSpeed starts rejecting requests prematurely. Check the LiteSpeed error log at /var/log/lsws/errorlog for clues. Restore your backup if needed, then tweak gradually with tighter monitoring.