Files
docs/content/privacy/self-hosting-performance.md
2026-07-28 07:20:32 -05:00

5.6 KiB
Raw Blame History

title, description, section, order
title description section order
Self-Hosting Without a CDN: Performance Tips How to make your self-hosted site fast without relying on Cloudflare or other CDNs. privacy 3

Self-Hosting Without a CDN: Performance Tips

A common objection to self-hosting is "but it won't be fast without a CDN." That's not true for most sites. With proper configuration, a well-tuned Nginx server on a decent VPS will load pages in under 200ms for visitors on the same continent — more than fast enough for a great user experience.


Tip 1 — Enable HTTP/2 and HTTP/3

HTTP/2 multiplexes requests over a single connection. HTTP/3 (QUIC) reduces latency even further.

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    # HTTP/3 requires Nginx 1.25+ with quic support
    listen 443 quic reuseport;
}

Check that HTTP/2 is active by looking at the Chrome DevTools → Network tab — your requests should show h2 as the protocol.


Tip 2 — Aggressive static file caching

Serve static assets with long cache lifetimes and immutable headers so browsers never re-request them:

location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff2?)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
    access_log off;
}

With immutable caching, the browser will never check if the file has changed until the user force-reloads.


Tip 3 — Enable Gzip compression

Compress text-based responses:

gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 5;
gzip_min_length 256;
gzip_types
    text/plain
    text/css
    text/javascript
    application/javascript
    application/json
    application/xml
    image/svg+xml;

This can reduce HTML, CSS, and JS payloads by 6080%.


Tip 4 — Use a PHP opcode cache

For WordPress and other PHP sites, enable OPcache:

; /etc/php/8.3/cli/conf.d/10-opcache.ini
opcache.enable=1
opcache.memory_consumption=128
opcache.max_accelerated_files=10000
opcache.revalidate_freq=120

This keeps compiled PHP scripts in memory, avoiding recompilation on every request.


Tip 5 — Install a WordPress caching plugin

For WordPress sites, use a caching plugin that generates static HTML:

  • WP Super Cache or W3 Total Cache: Generate static HTML files served directly by Nginx
  • LiteSpeed Cache: If you're running LiteSpeed (LSAPI mode)

See our W3 Total Cache Configuration guide for detailed setup instructions without a CDN.


Tip 6 — Tune Nginx worker settings

worker_processes auto;
worker_rlimit_nofile 65535;

events {
    worker_connections 4096;
    use epoll;
    multi_accept on;
}

auto sets the worker count to the number of CPU cores. worker_connections 4096 allows each worker to handle 4,000 concurrent connections.


Tip 7 — Serve images efficiently

  • Use WebP instead of JPEG/PNG (30% smaller). Convert with cwebp:
    sudo apt install webp -y
    cwebp -q 80 input.jpg -o output.webp
    
  • Use responsive images with srcset so mobile devices don't download desktop-sized images
  • Lazy-load below-the-fold images with loading="lazy" attribute:
    <img src="photo.jpg" loading="lazy" alt="...">
    
  • Compress images with a tool like ImageMagick or optipng before uploading

Tip 8 — Optimize your database

For MySQL/MariaDB:

  • Enable query cache (MySQL 5.7 and earlier)
  • Run mysqlcheck -o --all-databases weekly
  • Remove unused plugins and post revisions in WordPress
  • Use an index on frequently queried columns
-- Clean up WordPress post revisions
DELETE FROM wp_posts WHERE post_type = 'revision';

-- Optimize tables
OPTIMIZE TABLE wp_posts, wp_postmeta;

Tip 9 — Set proper buffer sizes

client_body_buffer_size 128k;
client_max_body_size 50m;
client_header_buffer_size 1k;
large_client_header_buffers 4 8k;
output_buffers 32 32k;
postpone_output 1460;

These settings prevent Nginx from buffering more data than necessary per connection.


Tip 10 — Choose a geographically close VPS location

Arcline's data center location matters. A VPS in Dallas will serve US visitors faster than one in Frankfurt. For international audiences, consider:

  • One VPS in the US + one in Europe with a simple round-robin DNS
  • Or just accept slightly higher latency for overseas visitors — a 200ms response time is still perfectly usable

Benchmarking your setup

After making these changes, test your performance:

# Install siege for load testing
sudo apt install siege -y
siege -c 50 -t 60s https://example.com

# Or use curl to measure response time
curl -w "@curl-format.txt" -o /dev/null -s https://example.com

Create a format file (curl-format.txt):

    time_namelookup:  %{time_namelookup}s
       time_connect:  %{time_connect}s
    time_appconnect:  %{time_appconnect}s
   time_redirect:  %{time_redirect}s
time_pretransfer:  %{time_pretransfer}s
   time_starttransfer:  %{time_starttransfer}s
                     ----------
          time_total:  %{time_total}s

Real-world results

A typical Arcline VPS running WordPress with:

  • Nginx + PHP 8.3 FPM
  • OPcache enabled
  • W3 Total Cache (page cache + database cache)
  • WebP images
  • Gzip compression

Will serve pages in 150300ms to US visitors and handle 500+ concurrent users on a $15/mo plan.

You don't need Cloudflare to be fast. You need a well-configured server.


What's next