Linux Kernel Sysctl Tuning Checklist – Proven Steps to Improve Performance
This article debunks the myth that simply copying a sysctl.conf yields a 30% boost, and presents a rigorous engineering loop—baseline measurement, hypothesis formulation, gray‑scale changes, observation of side effects, and rollback—along with detailed scripts, metrics, and per‑parameter guidance for memory, network, file handles, and more.
Why copying a sysctl.conf file is risky
Kernel parameters only affect resource allocation, queuing, reclamation and failure policies; they cannot magically increase CPU, memory, disk IOPS or network bandwidth. The same setting that helps a short‑lived gateway may cause latency spikes for a database, and a dirty‑page limit suitable for a 128 GB host can trigger long write‑backs on a 4 GB VM.
Establish a testable hypothesis
A valid tuning effort must answer four questions: what is the business bottleneck, which kernel mechanism limits it, which metrics will prove improvement, and what side‑effect thresholds trigger a rollback. Example: if the listen queue overflows, increasing net.core.somaxconn should reduce connection drops without worsening CPU, memory or P99 latency.
Build a baseline
Collect a representative baseline over a real load cycle. The script below samples key system files every 10 seconds for 30 iterations and stores the results for later comparison.
#!/usr/bin/env bash
set -euo pipefail
OUT_DIR="/var/tmp/kernel-tuning-baseline-$(date +%Y%m%d-%H%M%S)"
INTERVAL=10
COUNT=30
mkdir -p "$OUT_DIR"
uname -a >"$OUT_DIR/uname.txt"
sysctl -a >"$OUT_DIR/sysctl-before.txt" 2>&1 || true
for ((i=1; i<=COUNT; i++)); do
stamp="$(date --iso-8601=seconds)"
{
echo "timestamp=$stamp"
cat /proc/loadavg
cat /proc/meminfo
cat /proc/pressure/cpu
cat /proc/pressure/memory
cat /proc/pressure/io
} >"$OUT_DIR/sample-$i.txt"
ss -s >"$OUT_DIR/ss-$i.txt"
sleep "$INTERVAL"
done
echo "baseline_dir=$OUT_DIR"When sysstat is installed, run sar -u ALL 1 10, sar -q 1 10, etc., and avoid interpreting %iowait as raw disk utilization without considering await, queue depth and application I/O latency.
Memory parameters – controlling reclamation and write‑back
vm.swappinesscontrols the kernel's preference between reclaiming anonymous pages and file pages; it does not guarantee no swapping. Reduce it on database hosts to lower anonymous page swap, but setting it to 0 does not prevent OOM under severe pressure. Verify swap activity with free -h, vmstat, and /proc/pressure/memory.
Dirty‑page thresholds can be expressed as ratios ( vm.dirty_background_ratio, vm.dirty_ratio) or as absolute bytes ( vm.dirty_background_bytes, vm.dirty_bytes). On large‑memory machines the byte‑based settings are preferred. Example configuration (for a host with ample RAM and a storage write‑through of B bytes/s and a worst‑case flush time of T seconds):
# /etc/sysctl.d/60-CHANGE_ID-memory.conf
vm.dirty_background_bytes = 268435456
vm.dirty_bytes = 1073741824
vm.dirty_background_ratio = 0
vm.dirty_ratio = 0
# Adjust only after evidence of write‑back pressure
vm.swappiness = 10Apply the file with sysctl -p /etc/sysctl.d/60-CHANGE_ID-memory.conf and verify the values with sysctl vm.dirty_* vm.swappiness.
Network parameters – locating packet loss
The effective TCP accept queue is limited by the application’s listen(backlog), net.core.somaxconn, and the SYN backlog net.ipv4.tcp_max_syn_backlog. Raising kernel limits alone does not help if the application still requests a small backlog. Enable SYN cookies before increasing the queue.
# /etc/sysctl.d/60-CHANGE_ID-listen.conf
net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_syncookies = 1Observe the impact with ss -lntp (Send‑Q reflects the backlog limit, Recv‑Q shows queued connections) and
nstat -az | grep -E 'ListenOverflows|ListenDrops|SyncookiesSent|SyncookiesFailed'. If the backlog overflows while CPU soft‑interrupts are saturated, consider increasing net.core.netdev_max_backlog only after confirming that the NIC RX ring, soft‑irq distribution, and RPS/RSS statistics support it.
# /etc/sysctl.d/60-CHANGE_ID-netdev.conf
net.core.netdev_max_backlog = 8192When adjusting NIC ring sizes, first query the driver’s maximum with ethtool -g INTERFACE_NAME, then apply a new RX size (e.g., 4096) with ethtool -G INTERFACE_NAME rx 4096, and keep the original value in a backup file for rollback.
File handles and inotify limits
System‑wide file‑handle limit is fs.file-max, while per‑process limits are controlled by RLIMIT_NOFILE, LimitNOFILE in systemd units, and the application’s own settings. Raising fs.file-max alone does not prevent “Too many open files” errors if the service’s ulimit -n remains unchanged.
# /etc/systemd/system/SERVICE_NAME.service.d/limits.conf
[Service]
LimitNOFILE=262144Backup current values with sysctl fs.file-max fs.file-nr and inspect the process’s open FD count via /proc/PID/fd. For inotify, monitor fs.inotify.max_user_instances, fs.inotify.max_user_watches, and the number of active watches using a script that scans /proc/*/fd for anon_inode:inotify entries.
Overcommit, Transparent Huge Pages, and congestion control
vm.overcommit_memoryselects the allocation policy (0 heuristic, 1 always allow, 2 strict) and works together with vm.overcommit_ratio or vm.overcommit_kbytes. Different workloads (Redis, database forks, scientific computing) may require different settings; consult the application’s documentation before changing.
sysctl vm.overcommit_memory vm.overcommit_ratio vm.overcommit_kbytes
grep -E '^(CommitLimit|Committed_AS|MemAvailable|SwapTotal|SwapFree):' /proc/meminfo
journalctl -k -g 'Out of memory|oom-kill|Killed process' --since '-24 hours' --no-pagerTransparent Huge Pages (THP) can reduce page‑table pressure but may cause latency spikes during compaction. Check the current mode with cat /sys/kernel/mm/transparent_hugepage/enabled and the defrag mode with cat /sys/kernel/mm/transparent_hugepage/defrag. THP is usually controlled via kernel boot parameters or a dedicated systemd unit, not by writing echo never into /etc/sysctl.conf.
TCP congestion control can be inspected with sysctl net.ipv4.tcp_available_congestion_control and switched with sysctl net.ipv4.tcp_congestion_control. BBR is beneficial only for traffic limited by congestion and RTT; it does not fix DNS latency, CPU saturation, or physical packet loss. Test BBR on a controlled load before rolling it out.
Auditable change process
1. Generate a candidate .conf file with a unique CHANGE_ID, back up current values, and apply only that file using sysctl -p. The script below records existing values and installs the candidate without restarting services.
#!/usr/bin/env bash
set -euo pipefail
CHANGE_ID="CHANGE_ID"
SOURCE_FILE="/var/tmp/${CHANGE_ID}-candidate.conf"
TARGET_FILE="/etc/sysctl.d/60-${CHANGE_ID}.conf"
BACKUP_FILE="/var/tmp/${CHANGE_ID}-runtime-before.tsv"
[[ -f "$SOURCE_FILE" ]] || { echo "missing $SOURCE_FILE" >&2; exit 1; }
: >"$BACKUP_FILE"
while IFS='=' read -r raw_key raw_value; do
key=$(printf '%s' "$raw_key" | xargs)
[[ -z "$key" || "$key" == \#* ]] && continue
sysctl -n "$key" >/dev/null 2>&1 || true
printf '%s\t%s
' "$key" "$(sysctl -n "$key" 2>/dev/null || echo unavailable)" >>"$BACKUP_FILE"
done < "$SOURCE_FILE"
install -m 0644 "$SOURCE_FILE" "$TARGET_FILE"
sysctl -p "$TARGET_FILE"
echo "applied=$TARGET_FILE backup=$BACKUP_FILE"2. Perform a gray‑scale rollout: start with a node that has no traffic, verify that no side effects appear, then gradually introduce traffic while monitoring the same metrics used for the baseline.
#!/usr/bin/env bash
set -euo pipefail
SERVICE_NAME="SERVICE_NAME"
LISTEN_PORT="PORT"
systemctl is-active --quiet "$SERVICE_NAME"
ss -lnt "sport = :$LISTEN_PORT" | grep -q LISTEN
systemctl --failed --no-legend
journalctl -u "$SERVICE_NAME" --since '-10 minutes' -p warning --no-pager
nstat -az | grep -E 'ListenOverflows|ListenDrops|TcpRetransSegs'
cat /proc/pressure/memory
cat /proc/pressure/io3. Use incremental counters (e.g., nstat -az) to compare before‑and‑after values rather than relying on cumulative totals.
#!/usr/bin/env bash
set -euo pipefail
DURATION=60
OUT_DIR="/var/tmp/net-window-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$OUT_DIR"
nstat -az >"$OUT_DIR/start.txt"
nstat >/dev/null
sleep "$DURATION"
nstat >"$OUT_DIR/delta.txt"
grep -E 'TcpRetransSegs|ListenOverflows|ListenDrops|TCPSynRetrans|IpInDiscards' "$OUT_DIR/delta.txt" || true
echo "evidence_dir=$OUT_DIR"4. Define rollback triggers (e.g., P99 latency increase >20%, error‑rate breach, PSI rise) and keep a script that restores the original values from the backup TSV and disables the candidate file.
#!/usr/bin/env bash
set -euo pipefail
CHANGE_ID="CHANGE_ID"
BACKUP_FILE="/var/tmp/${CHANGE_ID}-runtime-before.tsv"
TARGET_FILE="/etc/sysctl.d/60-${CHANGE_ID}.conf"
DISABLED_FILE="/var/tmp/$(basename "$TARGET_FILE").rolled-back"
[[ -s "$BACKUP_FILE" ]] || { echo "invalid backup" >&2; exit 1; }
while IFS=$'\t' read -r key value; do
sysctl -w "${key}=${value}"
done < "$BACKUP_FILE"
if [[ -f "$TARGET_FILE" ]]; then
mv "$TARGET_FILE" "$DISABLED_FILE"
fi
echo "rolled_back=true disabled_file=$DISABLED_FILE"Monitoring and alerting for side effects
Prometheus queries that help track the impact of sysctl changes (adjust metric names to match your exporter):
# Memory available ratio
node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes
# TCP retransmissions per second
rate(node_netstat_Tcp_RetransSegs[5m])
# Listen queue overflow rate
rate(node_netstat_TcpExt_ListenOverflows[5m])
# Network receive drops per device (excluding lo)
rate(node_network_receive_drop_total{device!~"lo"}[5m])
# Memory PSI waiting seconds rate
rate(node_pressure_memory_waiting_seconds_total[5m])Do not set fixed thresholds on raw rates; relate retransmissions to total segments and consider device‑specific baselines.
A drift‑detection script can expose the number of managed keys whose runtime value differs from the desired configuration, feeding a gauge metric to Prometheus.
#!/usr/bin/env bash
set -euo pipefail
CONF="/etc/sysctl.d/60-CHANGE_ID.conf"
TEXTFILE_DIR="/var/lib/node_exporter/textfile_collector"
TMP_FILE=$(mktemp "${TEXTFILE_DIR}/sysctl_drift.prom.XXXXXX")
trap 'rm -f "${TMP_FILE}"' EXIT
drift=0
while IFS='=' read -r raw_key raw_value; do
key=$(printf '%s' "$raw_key" | xargs)
[[ -z "$key" || "$key" == \#* ]] && continue
expected=$(printf '%s' "$raw_value" | xargs)
actual=$(sysctl -n "$key" 2>/dev/null || echo unavailable)
[[ "$actual" != "$expected" ]] && drift=$((drift+1))
done < "$CONF"
printf '# HELP node_sysctl_drift_keys Number of managed sysctl keys with drift
' >"$TMP_FILE"
printf '# TYPE node_sysctl_drift_keys gauge
' >>"$TMP_FILE"
printf 'node_sysctl_drift_keys %d
' "$drift" >>"$TMP_FILE"
chmod 0644 "$TMP_FILE"
mv "$TMP_FILE" "${TEXTFILE_DIR}/sysctl_drift.prom"Typical scenarios and trade‑offs
High‑concurrency reverse proxy : Verify listen‑queue overflows, Recv‑Q near limit, FD usage, and CPU soft‑interrupt saturation before raising somaxconn or SYN backlog. Also watch queueing latency and accept‑rate.
Write‑intensive logging or object service : Observe P99 write latency, block device await, dirty/writeback counters, and nr_throttled_written. Adjust vm.dirty_*_bytes only after confirming that write‑back bandwidth is the bottleneck.
In‑memory database : Correlate MemAvailable, swap activity, memory PSI, OOM logs, and THP statistics. Tune vm.swappiness, overcommit, and THP based on the database’s memory model and vendor recommendations.
Technical review checklist
Confirm the parameter exists on the target kernel and its range matches the distro documentation.
Identify the current source of the value and ensure no later sysctl.d file overrides it.
Baseline must cover peak load and be repeatable in a controlled benchmark.
Each candidate value must have evidence of a specific bottleneck; avoid "nice‑to‑have" tweaks.
Back up persistent files, runtime values, application configs, and NIC settings.
Run sysctl --system syntax check; ensure only the intended file is loaded.
High‑risk network or reboot actions require traffic shedding, redundancy, and out‑of‑band access plans.
Validate results by measuring counter increments and business metrics, not merely sysctl output.
Rollback scripts, trigger thresholds, owners, and observation windows must be documented in the change ticket.
Verify post‑reboot consistency during a maintenance window and sync the final values to configuration management.
Parameters not suitable for a generic checklist
The following parameters are frequently seen in copy‑paste articles but should only be changed with concrete evidence for the specific workload: vm.drop_caches – forces cache eviction; useful for controlled tests, not for routine "free memory". vm.min_free_kbytes – affects low‑watermark; setting too high wastes memory. net.ipv4.tcp_fin_timeout – only affects FIN‑WAIT‑2, not generic TIME_WAIT problems. net.ipv4.tcp_max_tw_buckets – too small forces early TIME_WAIT destruction, which can have protocol side effects. kernel.pid_max, kernel.threads-max – process creation limits also involve cgroup pids.max and systemd TasksMax. net.ipv4.ip_forward – routing switch, not a performance knob; mis‑enabling expands attack surface. net.ipv4.conf.*.rp_filter – reverse‑path filtering; changing it can break asymmetric routing.
Auditable implementation workflow
1. Generate a candidate file without touching global config
Place the change in an isolated file named with a numeric prefix and a unique CHANGE_ID. The script records existing values, installs the candidate, and loads it with sysctl -p. No services are restarted automatically.
2. Gray‑scale rollout
Start on a node with no traffic, verify no side effects, then gradually introduce load while monitoring the same baseline metrics. Ensure that any observed improvement is not caused by unrelated factors.
3. Incremental measurement
Because kernel counters are cumulative, capture a snapshot with nstat -az, wait a defined window, capture another snapshot, and compare the deltas. This isolates the effect of the change.
4. Define rollback triggers
Rollback should be triggered by concrete thresholds such as P99 latency increase >20%, error‑rate breach, memory PSI rise, or significant increase in retransmissions or listen‑queue overflows.
5. Verify after reboot
Consistency after reboot is not guaranteed by a successful runtime change. During a maintenance window, reboot a test node, then compare the persisted .conf file with the runtime values using a verification script.
#!/usr/bin/env bash
set -euo pipefail
CONF="/etc/sysctl.d/60-CHANGE_ID.conf"
FAILED=0
while IFS='=' read -r raw_key raw_value; do
key=$(printf '%s' "$raw_key" | xargs)
expected=$(printf '%s' "$raw_value" | xargs)
[[ -z "$key" || "$key" == \#* ]] && continue
actual=$(sysctl -n "$key" 2>/dev/null || echo unavailable)
if [[ "$actual" != "$expected" ]]; then
printf 'MISMATCH key=%s expected=%s actual=%s
' "$key" "$expected" "$actual" >&2
FAILED=1
fi
done < "$CONF"
exit $FAILEDScalar parameters are handled directly; array‑type sysctls may need field‑wise comparison.
Monitoring side‑effects
For Prometheus, the following queries (adjust metric names to match your exporters) help surface regressions:
# Memory available ratio
node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes
# TCP retransmissions per second
rate(node_netstat_Tcp_RetransSegs[5m])
# Listen queue overflow rate
rate(node_netstat_TcpExt_ListenOverflows[5m])
# Network receive drops per device (excluding lo)
rate(node_network_receive_drop_total{device!~"lo"}[5m])
# Memory PSI waiting seconds rate
rate(node_pressure_memory_waiting_seconds_total[5m])Do not set absolute thresholds; instead relate metrics to baseline rates and consider duration of anomalies.
Conclusion
A reliable "optimization checklist" ends up being a very short list of parameters that are demonstrably beneficial for the specific workload. Parameters without evidence should be omitted, and any change must be backed by a reproducible baseline, gray‑scale rollout, incremental measurement, and a clear rollback plan.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Ops Community
A leading IT operations community where professionals share and grow together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
