Skip to main content

Set Linux sysctl for a Site That Gets Lots of Hits

Linux ships with small limits, and they slow your site when hits jump. Here is how to set socket queues, BBR, and file limits for 10,000 live links on a full box.

Cover image for Set Linux sysctl for a Site That Gets Lots of Hits

Default Linux settings suit a home PC. They do not suit a busy web host. Web hits jump. The queues fill fast. This happens fast on phone networks in India. A burst of guests can clog the buffers. Then Linux drops SYN packets. Web guests wait longer. Their pages load slowly. Real-time AI search bots drop slow pages. They cite quick sites instead.

You can fix this on a managed app server. You need no new hardware. You need tuned socket queues. You need TCP BBR speed control. You need the right file caps. This guide shows how to tune /etc/sysctl.conf for 10,000 or more live links.

How the TCP handshake works.

When a guest loads your site, the browser starts a TCP three-way handshake. Linux runs it through two queues.

  1. The SYN queue holds half open links. The client sends a SYN. Linux sends back SYN-ACK. It holds the link here. It waits for the last ACK from the client.
  2. The accept queue holds live links. The handshake ends. It goes to the next queue. It waits until your web host calls accept().
Incoming Client SYN
        │
        ▼
┌───────────────────────────────┐
│     SYN Backlog Queue         │ <── Controlled by net.ipv4.tcp_max_syn_backlog
│    (Half-Open Handshakes)     │
└───────────────┬───────────────┘
                │ Client returns ACK
                ▼
┌───────────────────────────────┐
│     Accept Backlog Queue      │ <── Controlled by net.core.somaxconn
│    (Established Sockets)      │
└───────────────┬───────────────┘
                │ Web server calls accept()
                ▼
┌───────────────────────────────┐
│   Nginx / Web Worker Pool     │ <── Reads HTTP request headers
└───────────────────────────────┘

If the accept queue fills, Linux drops new links. If the SYN queue fills, no new guest can link. Tune both queues. That stops lost links under load.

Socket queue tuning: fixing queue drops.

In short: Set net.core.somaxconn and net.ipv4.tcp_max_syn_backlog to 65535. Then set your web host queue to match.

The base value of net.core.somaxconn is 128 or 4096. A quick burst of hits can fill a queue of 128 links. That takes a few milliseconds. Once full, the host drops new packets.

Tune the accept queue (somaxconn).

The net.core.somaxconn rule sets the top queue depth for listen() sockets. Raise this cap. It lets you take lots of live visits.

sysctl -w net.core.somaxconn=65535

Your web host must ask for this queue size. In Nginx, change the listen rule in your host block.

server {
    listen 443 ssl default_server backlog=65535;
    listen [::]:443 ssl default_server backlog=65535;
    server_name example.com;
}

If you do not set backlog in Nginx, it uses 511. Linux picks the smaller one.

Tune the SYN queue (tcp_max_syn_backlog).

The net.ipv4.tcp_max_syn_backlog rule sets how many half open links Linux keeps in RAM. When hits surge, clients take time to send the last packet.

sysctl -w net.ipv4.tcp_max_syn_backlog=65535

Tune the network card queue (netdev_max_backlog).

Cards can take frames faster than Linux threads can read them. The frames wait in net.core.netdev_max_backlog. The base is 1000. It drops frames in a quick spike. Raise it to 16384.

sysctl -w net.core.netdev_max_backlog=16384
SettingBaseNewWhat it does.
net.core.somaxconn128 to 409665535Max sockets in the accept queue.
net.ipv4.tcp_max_syn_backlog512 to 102465535Max half open SYN links.
net.core.netdev_max_backlog100016384Packet queue for the network card.

In short: Turn on net.ipv4.tcp_tw_reuse, drop net.ipv4.tcp_fin_timeout to 15 seconds, and widen the port range.

When your web host closes a link, the socket stays in TIME_WAIT state. It waits up to 60 seconds. This wait lets old packets clear the path.

On busy reverse proxies, thousands pile up. They all sit in TIME_WAIT state. This state uses up free ports. It uses up RAM.

The net.ipv4.tcp_tw_reuse rule lets Linux reuse them for new links. It is safe for web hosts. It is safe for proxies.

sysctl -w net.ipv4.tcp_tw_reuse=1

[!WARNING] Never turn on net.ipv4.tcp_tw_recycle. Modern Linux cut it. It drops links from clients behind phone routers. It does the same for clients behind shared NAT links.

Cutting tcp_fin_timeout.

The net.ipv4.tcp_fin_timeout rule sets how long Linux holds a socket. It sits in FIN-WAIT-2 state. The base is 60 seconds. On web hosts, drop it to 15 seconds.

sysctl -w net.ipv4.tcp_fin_timeout=15

Open the port range.

When Nginx proxies calls to back-end tools, it opens a port. Tools like PHP-FPM, Node.js, or Redis are common. The base range is 32768 to 60999 (about 28,231 ports). Under load, you can run out of ports.

Open it. That allows up to 64,511 ports.

sysctl -w net.ipv4.ip_local_port_range="1024 65535"

TCP BBR vs Cubic.

In short: Turn on TCP BBR to keep speeds high and stop speed drops on phone networks.

Cubic is the norm on most Linux. Cubic thinks packet loss means the load is too high. When a packet drops, Cubic cuts link speed in half.

On phone 4G and 5G networks in India, packet loss comes from radio noise. It comes from tower hops too. It is not caused by a heavy load. Cubic slows down by mistake. This makes page loads slow. It raises Time to First Byte.

Google built BBR to fix this issue. BBR stands for Bottleneck Bandwidth and Round-trip Time. BBR checks the real pipe width and delay fast. It skips small packet loss. It keeps link speed high.

# Set default queueing discipline to Fair Queueing
sysctl -w net.core.default_qdisc=fq

# Enable BBR congestion control
sysctl -w net.ipv4.tcp_congestion_control=bbr
MetricCubic ModeBBR ModePhone User Impact.
Congestion checkPacket loss events.Bandwidth and round trip time.BBR ignores radio signal loss.
Speed after 2% lossDrops by up to 50%.Stays at full link rate.Up to 3x faster link rate.
Median response waitShifts.Low and steady.Faster TTFB and lower bounce rates.
Buffer bloat defensePoor.Strong.Smoother Core Web Vitals.

To learn how low delay boosts web speed, see our guide on server-side TTFB speed.

TCP RAM buffer caps for a VPS.

In short: Set buffer caps to boost speed without draining RAM.

Each live link claims read and write buffers in RAM. Linux tunes these on the fly. You must set safe caps.

The rules use three numbers: floor, base, and top bytes.

# TCP receive buffer: min 4KB, default 87KB, max 16MB
sysctl -w net.ipv4.tcp_rmem="4096 87380 16777216"

# TCP send buffer: min 4KB, default 65KB, max 16MB
sysctl -w net.ipv4.tcp_wmem="4096 65536 16777216"

# Maximum OS socket receive and send limits
sysctl -w net.core.rmem_max=16777216
sysctl -w net.core.wmem_max=16777216

RAM buffer caps across VPS tiers.

Do not set top buffers too high on small RAM nodes. If 10,000 sockets all grow to 16 MB at once, your host runs out of RAM.

Use these safe caps for your cloud host size.

VPS TierRAM SizeTop rmem_maxTop wmem_maxSafe Socket Count.
Starter1 GB4,194,304 (4 MB)4,194,304 (4 MB)Up to 2,500 links.
Growth2 GB8,388,608 (8 MB)8,388,608 (8 MB)Up to 5,000 links.
Pro4 GB16,777,216 (16 MB)16,777,216 (16 MB)Up to 15,000 links.
Business8 GB33,554,432 (32 MB)33,554,432 (32 MB)Up to 30,000 links.
Enterprise16 GB+67,108,864 (64 MB)67,108,864 (64 MB)50,000+ links.

To tune back-end workers, read our guide on PHP-FPM worker pool tuning. Learn how fast local storage cuts disk wait limits.

File caps and process limits.

In short: In Linux, sockets are files. Set system and user file caps to at least 65535.

Each live link takes a file descriptor. So does each log file. So does each static asset. The base user cap is often 1024. Once reached, Nginx logs the errors.

Raise system file caps.

Set the file descriptor cap in /etc/sysctl.conf.

sysctl -w fs.file-max=2097152

Raise user file caps in limits.conf.

Edit /etc/security/limits.conf and add these lines.

* soft nofile 65535
* hard nofile 65535
root soft nofile 65535
root hard nofile 65535
www-data soft nofile 65535
www-data hard nofile 65535

Set systemd service caps.

Linux now runs systemd. Add file caps to each service unit. Make a custom rule for Nginx.

mkdir -p /etc/systemd/system/nginx.service.d/
cat << 'EOF' > /etc/systemd/system/nginx.service.d/limits.conf
[Service]
LimitNOFILE=65535
EOF
systemctl daemon-reload
systemctl restart nginx

The /etc/sysctl.d/99-webhost24.conf pool file for live use.

Here is a tested setup file. Save it to /etc/sysctl.d/99-webhost24.conf on your VPS.

# /etc/sysctl.d/99-webhost24.conf
# High-concurrency web server kernel optimizations

# Socket queue backlogs
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.core.netdev_max_backlog = 16384

# TIME_WAIT socket management and port ranges
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
net.ipv4.ip_local_port_range = 1024 65535

# TCP BBR congestion control
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr

# TCP memory buffers (Safe for 2GB - 8GB VPS nodes)
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216

# Keepalive intervals (Detect dead connections in 5 minutes instead of 2 hours)
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_intvl = 15
net.ipv4.tcp_keepalive_probes = 5

# System file descriptor ceiling
fs.file-max = 2097152

# Protect against SYN flood attacks
net.ipv4.tcp_syncookies = 1

Apply them without a reboot.

sysctl --system

CLI checks for the new rules.

Once applied, check your setup with standard tools.

Step 1: Check that TCP BBR is active.

Run this command to see the method.

sysctl net.ipv4.tcp_congestion_control

It should return.

net.ipv4.tcp_congestion_control = bbr

Step 2: Check for listen queue drops.

Run netstat to check that your queues do not overflow.

netstat -s | grep -i listen

If you see zero queue drops, your host takes the load.

Check total live links and states with ss.

ss -s

Make sure that TIME_WAIT links stay low. Make sure they do not run out of ports.

Step 4: Check file descriptor use.

View used file counts.

cat /proc/sys/fs/file-nr

The output shows three counts: used files, free files, and the top cap.

Step 5: Check the kernel ring buffer for errors.

Check that no SYN flood or lost packet notes show in dmesg.

dmesg | grep -E -i "syn|drop|overflow"

For broad server defense, read our VPS hosting guide.

Frequently asked questions.

How do net.core.somaxconn and net.ipv4.tcp_max_syn_backlog differ?

In short: net.ipv4.tcp_max_syn_backlog limits half open links. net.core.somaxconn limits live links that wait for your web host to take them.

When a client sends a SYN packet, it sits in the SYN queue. It waits until the handshake ends. Then it goes into the accept queue. If the SYN queue rule is too low, new links drop in the handshake. If net.core.somaxconn is too low, links drop when your web workers are full.

Does raising somaxconn use RAM when the site is idle?

In short: No. Sockets only claim RAM when real links arrive.

Setting net.core.somaxconn to 65535 raises the top queue length. It does not take RAM for buffers. It sets a higher cap for when guests surge.

Why was tcp_tw_recycle dropped from Linux?

In short: It breaks TCP links for guests who share one IP through NAT or phone carriers.

net.ipv4.tcp_tw_recycle used time stamps to drop old packets. When lots of phones share one mobile IP, their time stamps do not match. Linux thought the packets were out of order. It cut valid links. The option was cut in Linux kernel 4.12.

How does sysctl help AI search bots?

In short: It stops lost links and cuts Time to First Byte during bot crawler visits.

Real-time AI search bots fetch pages on tight clocks. Bots like OAI-SearchBot and PerplexityBot work this way. When a bot hits the host in a spike, lost packets cause wait timeouts. If your host fails to reply fast, the search bot drops your page. It cites a rival site instead.

Final: building a strong web node.

Tune the kernel. Your web stack then handles traffic spikes. It does not drop guests. It does not stall search crawlers.

Before you push your host live, read this checklist of six points.

  1. Set socket queues. Raise net.core.somaxconn and net.ipv4.tcp_max_syn_backlog to 65535.
  2. Align web host settings. Set backlog=65535 in your Nginx listen rules.
  3. Turn on TCP BBR. Switch from Cubic to BBR. This protects phone guests from packet loss slowdowns.
  4. Clean up TIME_WAIT. Turn on net.ipv4.tcp_tw_reuse. Lower net.ipv4.tcp_fin_timeout to 15 seconds.
  5. Set file caps. Set soft and hard file caps of 65535 in limits.conf and systemd.
  6. Check with CLI tools. Run sysctl --system. Check live queues with ss -s.

You get fast cloud servers with fast local storage in India. You get month-to-month terms. You get clear prices for each plan. You get a full refund in 30 days. You get a daily backup kept for 7 days.

Need help with your cloud servers? Reach out to our team on WhatsApp for fast, direct help.

Written by

Renish Mithani

Hosted in India, written in English

  • 11 min read

Share this post

Need help?

Ask us on WhatsApp

Our team replies during Indian business hours. Ask us anything about hosting, and we will help. We are the people who run the servers, so we can answer the hard ones too.

That is the end of this post. If you want to keep reading, the posts below are the ones we share with it. We write every post ourselves, and each one stands on its own.

We write about hosting, servers, backups, and the day to day work of running a site for a customer. There is no sales pitch in a post, and every post is free to read.

We write them for the people who run a site from India, and we keep the words plain. We do not write for a prize, and we do not sell you anything here. Read the post, take what you need, and ignore the rest.

Related posts

We rank these by the tags they share with the post you came from. Read one to learn more. Every post is free to read.

Cookie Preferences