Introduction
For VPS users with pay-per-use or limited data transfer plans, bandwidth overage is the most common source of surprise bills. Whether you’re using DigitalOcean, Vultr, or Linode, exceeding your plan’s data allowance can cost significantly more than expected. This guide presents a complete traffic monitoring and cost-saving strategy to help you stay in control of your VPS bandwidth usage.
Why Do You Need Traffic Monitoring?
Most VPS plans include a certain amount of free monthly data (e.g., 1TB/month). Beyond that, charges apply per GB. For VPS instances running websites, APIs, or file downloads, traffic consumption can grow rapidly:
- Static websites: ~1,000 daily page views consume about 5–10 GB
- Video/file downloads: A single popular file downloaded 100 times may exhaust your monthly quota
- API services: High-frequency calls can generate unexpected traffic
- DDoS attacks: An unprotected VPS can consume massive amounts of traffic within hours
Solution 1: Real-Time Monitoring with Prometheus + Node Exporter
Install Node Exporter
# Create node_exporter user
sudo useradd --no-create-home --shell /bin/false node_exporter
# Download and install
wget https://github.com/prometheus/node_exporter/releases/download/v1.7.0/node_exporter-1.7.0.linux-amd64.tar.gz
tar xvf node_exporter-*.tar.gz
sudo cp node_exporter-*/node_exporter /usr/local/bin/
sudo chown node_exporter:node_exporter /usr/local/bin/node_exporter
# Create systemd service
sudo tee /etc/systemd/system/node_exporter.service > /dev/null <<EOF
[Unit]
Description=Node Exporter
After=network.target
[Service]
User=node_exporter
ExecStart=/usr/local/bin/node_exporter
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now node_exporter
Configure Prometheus
# prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'node'
static_configs:
- targets: ['localhost:9100']
Solution 2: Visualize Traffic Data with Grafana
Key Monitoring Metrics
Configure the following panels in Grafana:
| Metric | Description | Alert Threshold |
|---|---|---|
node_network_receive_bytes_total | Received traffic | Monthly cumulative > 80% of quota |
node_network_transmit_bytes_total | Sent traffic | Monthly cumulative > 80% of quota |
rate(node_network_receive_bytes[5m]) | Real-time receive rate | > 100 MB/s |
rate(node_network_transmit_bytes[5m]) | Real-time send rate | > 100 MB/s |
Traffic Trend Panel Configuration
Create a panel showing monthly traffic trends using this PromQL query:
# Cumulative received traffic this month
increase(node_network_receive_bytes_total{device="eth0"}[30d])
# Cumulative sent traffic this month
increase(node_network_transmit_bytes_total{device="eth0"}[30d])
Solution 3: Simple Shell Script for Traffic Alerts
If you don’t want to deploy a full Prometheus stack, use a simple Shell script:
#!/bin/bash
# traffic_alert.sh - Simple traffic monitoring script
INTERFACE="eth0"
MONTHLY_QUOTA_GB=1000
ALERT_THRESHOLD=80 # Percentage
# Get this month's used traffic (bytes)
USED_BYTES=$(cat /sys/class/net/${INTERFACE}/statistics/rx_bytes)
USED_BYTES=$((USED_BYTES + $(cat /sys/class/net/${INTERFACE}/statistics/tx_bytes)))
# Convert to GB
USED_GB=$(echo "scale=2; $USED_BYTES / 1073741824" | bc)
# Calculate usage percentage
USAGE_PERCENT=$(echo "scale=2; $USED_GB * 100 / $MONTHLY_QUOTA_GB" | bc)
# Check if threshold exceeded
if (( $(echo "$USAGE_PERCENT > $ALERT_THRESHOLD" | bc -l) )); then
echo "$(date): WARNING! ${INTERFACE} traffic usage at ${USAGE_PERCENT}% (${USED_GB}GB/${MONTHLY_QUOTA_GB}GB)" | \
mail -s "VPS Traffic Alert" your-email@example.com
fi
Add the script to crontab to run hourly:
crontab -e
0 * * * * /path/to/traffic_alert.sh
Solution 4: Use Cloudflare CDN to Reduce Outbound Traffic
For publicly accessible websites, Cloudflare CDN is the most effective cost-saving solution:
Advantages
- Cache static resources: CSS, JS, images are served from edge nodes, not consuming origin traffic
- Transfer compression: Automatic gzip/brotli compression reduces data transferred
- Free tier: Unlimited bandwidth, 100K requests/day
- DDoS protection: Built-in free protection prevents attack-related traffic waste
Configuration Steps
# 1. Enable Cloudflare proxy (orange cloud icon)
# 2. Turn on auto-compression
# Settings -> Optimization -> Compression -> On
# 3. Set cache rules
# Cache Rules -> Cache Everything -> TTL: 1 hour
# 4. Enable Brotli compression
# Edge Browser Caching -> True Client IP
Solution 5: Bandwidth Throttling & QoS Configuration
Limit Interface Bandwidth with tc
# Limit eth0 maximum outbound bandwidth to 100Mbps
sudo tc qdisc add dev eth0 root handle 1: htb default 12 rtt 250 mpu 0 \
maxburst 14 avpkt 1000 bandwidth 100mbit ceil 100mbit
# Add sub-queue
sudo tc class add dev eth0 parent 1: classid 1:12 htb rate 100mbit ceil 100mbit burst 15k
Limit Docker Container Traffic with cgroup
# Create cgroup and limit bandwidth
sudo cgcreate -g net_cls,net_pids:/docker-limited
sudo cgset -r net_pids.limit=100 docker-limited
Traffic Optimization Best Practices
1. Enable HTTP/2 and HTTP/3
# nginx.conf
http {
# HTTP/2
listen 443 ssl http2;
# Brotli compression
brotli on;
brotli_comp_level 6;
brotli_types text/plain text/css application/json application/javascript;
}
2. Image Optimization
# Convert to WebP format using cwebp
cwebp -q 80 input.jpg -o output.webp
# Typically reduces file size by 30-50%
3. API Response Compression
location /api/ {
gzip on;
gzip_types application/json text/plain;
gzip_min_length 1000;
}
4. Database Query Optimization
Reducing unnecessary database queries can significantly lower application-layer traffic:
-- Analyze slow queries with EXPLAIN
EXPLAIN SELECT * FROM posts WHERE status = 'published';
-- Add appropriate indexes
CREATE INDEX idx_posts_status ON posts(status);
Automated Monthly Traffic Report
Create a script to generate monthly traffic reports:
#!/bin/bash
# monthly_traffic_report.sh
REPORT_DATE=$(date +%Y-%m)
QUOTA_GB=1000
# Statistics for this month
RX_TOTAL=$(awk '/eth0/ {sum += $1} END {print sum}' /proc/net/dev)
TX_TOTAL=$(awk '/eth0/ {sum += $2} END {print sum}' /proc/net/dev)
RX_GB=$(echo "scale=2; $RX_TOTAL / 1073741824" | bc)
TX_GB=$(echo "scale=2; $TX_TOTAL / 1073741824" | bc)
TOTAL_GB=$(echo "scale=2; $RX_GB + $TX_GB" | bc)
USAGE_PCT=$(echo "scale=2; $TOTAL_GB * 100 / $QUOTA_GB" | bc)
# Generate report
cat <<EOF
========================================
VPS Monthly Traffic Report - ${REPORT_DATE}
========================================
Received: ${RX_GB} GB
Sent: ${TX_GB} GB
Total: ${TOTAL_GB} GB
Quota: ${QUOTA_GB} GB
Usage: ${USAGE_PCT}%
----------------------------------------
EOF
Conclusion
By implementing the solutions above, you can:
- Monitor in real-time your VPS traffic usage
- Get early warnings to avoid unexpected overage fees
- Optimize content delivery to reduce unnecessary traffic
- Generate regular reports to continuously improve operations
Remember, prevention is always cheaper than remediation. Spend a small amount of time setting up monitoring systems, and you’ll save hundreds of dollars in overage fees every month.
