Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

Nginx vs Apache: Performance, Config, and Use Cases

By Kokil Thapa | Last reviewed: September 2026

Choosing between web servers is not a trivia question—it shapes how your PHP app scales, how fast pages load, and how painful deploys become. Nginx vs Apache: Performance, Config, and Use Cases is the decision every Laravel, WordPress, and custom PHP team hits when provisioning a VPS or migrating off shared hosting. I've run both on Ubuntu production boxes for client sites since 2010, often alongside Linux system administration work on shared EC2 infrastructure. This guide compares request architecture, copy-paste config, and the scenarios where each server actually wins—not marketing benchmarks.

Which is faster for PHP and Laravel: Nginx or Apache?

Raw speed depends on what you measure. Nginx typically wins on static assets, TLS termination, and high-concurrency keep-alive connections. Apache with event MPM and PHP-FPM closes much of that gap for dynamic PHP. Neither server executes PHP natively in a modern stack—both hand off to PHP-FPM.

On a production Laravel 13 application with PHP 8.5 and OPcache enabled, the difference between Nginx and Apache often sits in single-digit milliseconds per request. Database queries, N+1 problems, and missing indexes hurt far more than your web server choice. I've seen teams chase Nginx after a slow-query audit would have fixed 80% of latency in one afternoon.

Where Nginx pulls ahead is sustained concurrency. Its event-driven model handles thousands of idle connections—WebSockets, long-polling, mobile clients—without spawning a worker per socket. Apache's prefork MPM, still common on older shared hosts, allocates memory per process. That becomes expensive under traffic spikes during Dashain sales on a e-commerce platform.

CriteriaNginxApache
Static file throughputExcellent—sendfile, direct kernel offloadGood with mod_cache; slower at extreme concurrency
PHP execution modelPHP-FPM via fastcgi_pass (standard)PHP-FPM via proxy_fcgi (recommended) or legacy mod_php
Memory under loadLower per connectionHigher with prefork; event/worker MPM improves this
Per-directory configServer block only—no .htaccess.htaccess supported—convenient, slower
Reverse proxy / load balancingFirst-class, lightweightmod_proxy works; Nginx is more common here
Module ecosystemCore modules + Lua (OpenResty)Rich module library (mod_security, mod_rewrite)
Typical 2026 PHP stackLEMP (Nginx + PHP-FPM + MySQL 9.7)LAMP (Apache + PHP-FPM + MySQL 8.4 LTS)

For Laravel specifically, both servers perform similarly when PHP-FPM pool sizes, OPcache, and Redis 8.10 session caching are tuned correctly. Read our dedicated Nginx vs Apache for PHP sites in 2026 breakdown for PHP-version-specific notes.

Nginx vs Apache Performance ProfileNginxStatic files: highConcurrency: highBest for: LEMP, proxyApacheStatic files: good.htaccess: flexibleBest for: LAMP, legacyPHP-FPM (both servers)Dynamic PHP latency is nearly identicalBottleneck: DB queries, not web server
Nginx vs Apache performance: both rely on PHP-FPM for dynamic Laravel and WordPress workloads in 2026.

How do Nginx and Apache handle requests differently?

Apache's traditional prefork model forks a child process per connection. Each process loads the full Apache binary and any linked modules. Under heavy traffic, process count climbs and RAM consumption follows. Event MPM (available since Apache 2.4) uses a small pool of threads—closer to Nginx behaviour—but prefork persists on many managed hosts.

Nginx uses an asynchronous, event-driven loop. A handful of worker processes handle many connections through epoll/kqueue. Static files stream with minimal overhead. Dynamic requests proxy to upstream services—PHP-FPM, Node.js 26 LTS, or a Laravel Octane Swoole socket.

The .htaccess difference matters operationally. Apache reads per-directory override files on every request unless AllowOverride is disabled. That lets WordPress users drop rewrite rules without SSH access. It also means filesystem stat calls on every hit—a hidden cost on busy sites. Nginx requires all rules in server blocks. You edit config and reload. No runtime directory scanning.

Apache request path

  1. Client connects to port 443 (TLS via mod_ssl or terminating proxy).
  2. Apache worker accepts connection and parses request headers.
  3. If .htaccess exists, Apache reads it from disk (unless disabled).
  4. mod_rewrite applies rules; virtual host matches DocumentRoot.
  5. For PHP-FPM: mod_proxy_fcgi forwards to unix:/run/php/php8.5-fpm.sock.
  6. PHP-FPM worker executes script; response returns through Apache.

Nginx request path

  1. Client connects; Nginx worker accepts via event loop.
  2. server_name and location blocks match from compiled config.
  3. Static files served directly; PHP locations use fastcgi_pass.
  4. Nginx passes SCRIPT_FILENAME and PATH_INFO to PHP-FPM.
  5. PHP-FPM returns response; Nginx may gzip, add headers, cache.
Request Handling ArchitectureNginx (event-driven)Worker processes (few)Many connections per workerNo .htaccess lookupfastcgi_pass to PHP-FPMApache (process/thread)Worker or prefork pool.htaccess per requestmod_rewrite rulesproxy_fcgi to PHP-FPMBoth
Nginx uses an event loop; Apache uses process or thread pools—both terminate at PHP-FPM for modern PHP apps.

How do you configure Nginx vs Apache for a Laravel application?

Laravel 13 expects all requests to route through public/index.php. Both servers must rewrite unknown paths to the front controller. They must deny access to .env, storage/, and vendor/. They must pass correct FastCGI parameters so Laravel resolves paths properly.

On Ubuntu 24 with PHP 8.5, install PHP-FPM first. Then configure your web server to proxy only public/ as the document root—not the project root. Exposing the Laravel root directory is a recurring security mistake I've patched on inherited deployments.

Nginx server block for Laravel 13

server {
    listen 443 ssl http2;
    server_name app.example.com;
    root /var/www/laravel/public;
    index index.php;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php8.5-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
        fastcgi_hide_header X-Powered-By;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}

Use $realpath_root instead of $document_root. Symlinked Deployer 7 releases break path resolution without it. After editing, run nginx -t then systemctl reload nginx. Our Laravel on Ubuntu VPS with Nginx guide covers the full LEMP setup including queue workers and scheduler cron.

Apache virtual host for Laravel 13

<VirtualHost *:443>
    ServerName app.example.com
    DocumentRoot /var/www/laravel/public

    <Directory /var/www/laravel/public>
        AllowOverride All
        Require all granted
    </Directory>

    <FilesMatch \.php$>
        SetHandler "proxy:unix:/run/php/php8.5-fpm.sock|fcgi://localhost"
    </FilesMatch>

    ErrorLog ${APACHE_LOG_DIR}/laravel-error.log
    CustomLog ${APACHE_LOG_DIR}/laravel-access.log combined
</VirtualHost>

Laravel ships an public/.htaccess with standard rewrite rules. With AllowOverride All, those rules apply automatically. For production performance, move rewrites into the virtual host and set AllowOverride None—same philosophy as Nginx's single config file.

Enable required Apache modules on Ubuntu:

sudo a2enmod rewrite proxy proxy_fcgi ssl headers
sudo systemctl restart apache2

WordPress on WooCommerce 11.1 follows the same pattern. The try_files or mod_rewrite block sends pretty permalinks to index.php. See WordPress Nginx vs Apache for high-traffic sites for caching-layer differences.

When should you choose Nginx over Apache in production?

Pick Nginx when you control the server, expect meaningful traffic, or need reverse-proxy features. Pick Apache when you depend on .htaccess, run legacy mod_php code, or your host only supports cPanel-style LAMP stacks.

  • New Laravel or Symfony 8.1 projects: Nginx + PHP-FPM is the community default. Tooling, tutorials, and Forge-style panels assume it.
  • Reverse proxy in front of app servers: Terminate TLS at Nginx, proxy to PHP-FPM or Octane. Add rate limiting and caching at the edge.
  • Static-heavy sites with CDN fallback: Nginx serves assets efficiently when Cloudflare or Bunny CDN misses occur.
  • Microservices or multi-app VPS: One Nginx instance routes by server_name to multiple PHP-FPM pools.
  • Shared hosting or WordPress multisite with .htaccess: Apache remains simpler for non-technical site owners who edit permalinks through wp-admin.
  • Legacy PHP 5.x or mod_php apps: Migration to PHP-FPM is required either way—but Apache mod_php still exists on old hosts.
Nginx or Apache? Decision TreeNew PHP 8.3+ project?YesChoose NginxLEMP + PHP-FPMNoLegacy / shared host?Apache + .htaccessNeed reverse proxy?Nginx at edgeTune PHP-FPM either wayDB + OPcache matter most
Use this Nginx vs Apache decision tree when scoping a new VPS or migration project in 2026.

For legal-tech portals I've built—booking forms, document uploads, client dashboards—the server choice mattered less than correct PHP-FPM pool sizing and Redis session storage. A notary service portal on Nginx handles traffic fine when queries are indexed and assets are cached.

Hybrid setups work well. Apache serves legacy WordPress on port 8080 internally. Nginx sits on port 443, terminates TLS 1.3, and reverse-proxies to Apache. You gain Nginx edge performance without rewriting every .htaccess rule overnight. Our reverse proxy with Nginx article walks through that pattern.

What are common migration pitfalls when switching from Apache to Nginx?

Apache-to-Nginx migrations fail for predictable reasons—not because Nginx is harder, but because teams translate config literally instead of functionally. I've handled this on sister sites sharing a Deployer 7 pipeline where one stale rewrite rule broke admin login for two days.

Rewrite rule translation

Apache mod_rewrite conditions do not map one-to-one to Nginx if directives. Nginx if is fragile inside location blocks. Prefer try_files, named locations, and map directives. Test every URL pattern—especially trailing slashes, pagination, and API prefixes.

Missing FastCGI parameters

Without fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name, Laravel returns blank pages or 404 on symlinked releases. Without fastcgi_param PATH_INFO where needed, some legacy routes break.

Client body size limits

Apache's LimitRequestBody becomes Nginx's client_max_body_size. Legal portals uploading PDF scans hit 413 errors when this stays at the 1 MB default. Set 32m or higher for document workflows.

Permission and socket paths

PHP-FPM socket ownership must allow the web server user—www-data on Ubuntu—to connect. After migration, run ls -la /run/php/ and confirm pool user matches. A common post-deploy error is 502 Bad Gateway with nothing useful in Laravel logs.

Follow the step-by-step Apache to Nginx migration guide before cutting over DNS. Test with a hosts-file entry first. Keep Apache running on an alternate port for instant rollback.

Production LEMP Stack TopologyInternet / CDNTLS 1.3 terminationNginxStatic + reverse proxyPHP-FPM 8.5Laravel 13 appRedis 8.10Cache + sessionsMySQL 9.7 / MariaDB 12.3Indexed queries, nightly backupsDeployer 7 symlink swap + PHP-FPM reload after release
Typical Nginx production topology for Laravel: edge server, PHP-FPM, Redis, and MySQL on Ubuntu VPS.

How do caching, TLS, and monitoring differ between Nginx and Apache?

Both servers support HTTP caching, compression, and modern TLS. Nginx's proxy_cache and fastcgi_cache are widely used for full-page caching of anonymous responses. Apache's mod_cache works but sees less adoption in greenfield PHP projects.

For TLS, configure cipher suites and HSTS on whichever server terminates HTTPS. Our TLS 1.3 vs 1.2 for Nginx guide applies directly. Apache 2.4 with mod_ssl supports TLS 1.3 on OpenSSL 1.1.1+—same baseline as Nginx on Ubuntu 24.

Monitoring should cover both the web server and PHP-FPM. Watch active processes, slow request logs, and 502/504 rates. Tools like Netdata expose Nginx stub_status and PHP-FPM pool metrics with minimal config. Pair server metrics with application-level profiling—Laravel Debugbar in staging, MySQL slow query logs in production.

Application caching matters more than server caching for authenticated Laravel apps. Redis 8.10 for sessions and query results beats micro-optimising worker_processes. Read caching strategies for web performance for layer-by-layer guidance.

When benchmarking, use realistic workloads—not hello-world static files alone. Include authenticated dashboard pages, file uploads, and webhook endpoints. A JSON formatter helps inspect API response payloads during load tests. For hosting decisions in Nepal, factor in local VPS pricing—Rs 1,500–3,000/month (~USD 11–22) for entry boxes—and whether your provider defaults to Apache cPanel or plain Ubuntu.

Official references remain the source of truth for directive syntax: the Nginx documentation and the Apache 2.4 documentation. PHP-FPM pool configuration is covered in the PHP manual.

Key Takeaways

  • For new PHP 8.3+ / Laravel 13 projects, Nginx + PHP-FPM is the practical default—lower memory under concurrency and first-class reverse-proxy support.
  • Dynamic PHP performance is nearly identical between servers; tune PHP-FPM pools, OPcache, Redis, and database indexes before switching web servers.
  • Apache wins when you need .htaccess flexibility on shared hosting or run legacy mod_php workloads without migration budget.
  • Always set $realpath_root in Nginx FastCGI params and restrict the document root to public/ for Laravel and Symfony apps.
  • Migrate Apache rewrites functionally—not line-for-line—and test file uploads, admin routes, and API endpoints before DNS cutover.
  • Hybrid topologies (Nginx edge + Apache backend) let you migrate incrementally without breaking WordPress .htaccess workflows.

People Also Ask

Can I run Nginx and Apache on the same server?

Yes. A common pattern binds Nginx to ports 80 and 443, then reverse-proxies to Apache on 127.0.0.1:8080. You get modern TLS termination and static-file speed at the edge while Apache handles legacy .htaccess rules internally. Ensure only one server binds to the public ports.

Is Apache still relevant in 2026?

Apache remains widely deployed—especially on shared hosting, cPanel servers, and enterprise environments with existing mod_security rules. Apache 2.4 with event MPM and PHP-FPM is a legitimate production stack. It is not obsolete; it is less common for new VPS deployments where teams want leaner configs.

Does Nginx replace Apache for WordPress?

Nginx runs WordPress 7.1 and WooCommerce 11.1 excellently with PHP-FPM and the correct try_files block. You lose .htaccess convenience—permalinks must be handled in the server block. Managed WordPress hosts often use Nginx internally even when the control panel says "Apache compatible."

Which web server uses less RAM on a small VPS?

Nginx typically consumes less RAM under concurrent connections because it does not fork a heavy process per client. On a 1 GB VPS running Laravel, Nginx plus PHP-FPM leaves more headroom for MySQL and Redis. Apache with prefork MPM can exhaust memory during traffic spikes unless worker counts are capped aggressively.

Pick the server that matches your ops reality

Nginx vs Apache: Performance, Config, and Use Cases is not a winner-take-all contest. Nginx fits modern LEMP deployments, reverse-proxy edges, and teams that manage config through Git and Deployer. Apache fits shared hosting, .htaccess-dependent WordPress setups, and environments where changing the web server is not worth the migration risk.

Start with your constraints: hosting panel, team skill, traffic profile, and whether you need proxy features today. Then tune PHP-FPM, caching, and database queries—the layers that actually move response times. If you want help choosing and configuring the right stack for a production app, contact us or explore speed optimization services and website migration support. For a full LEMP walkthrough, see the LEMP stack on Ubuntu guide and our Laravel booking platform portfolio for a real deployed example.

Frequently Asked Questions

For modern PHP 8.5 with PHP-FPM and OPcache, the gap is usually single-digit milliseconds. Nginx wins on static files and high concurrency; database and app code matter far more.

Apache traditionally forks a process per connection with prefork MPM, which raises RAM under spikes. Event MPM uses threads and closes much of the gap. Nginx uses an event-driven loop where a few workers handle many connections via epoll. Both hand dynamic PHP to PHP-FPM in a 2026 stack. Apache also reads .htaccess on each request unless AllowOverride is disabled, adding filesystem stat overhead Nginx avoids because rules live only in server blocks.

Point the document root at public/, not the project root. Use try_files to route unknown paths to index.php, fastcgi_pass to the PHP 8.5-FPM unix socket, and set SCRIPT_FILENAME with realpath_root for Deployer 7 symlinked releases. Deny hidden files except .well-known, add security headers, run nginx -t, then reload. Exposing the Laravel root directory is a recurring security mistake on inherited deployments.

Set DocumentRoot to public/ and enable rewrite, proxy, proxy_fcgi, ssl, and headers modules. Use SetHandler with proxy:unix socket to PHP 8.5-FPM. Laravel’s public/.htaccess works with AllowOverride All, but for production move rewrites into the virtual host and set AllowOverride None, matching Nginx’s single-config approach. Restart Apache after enabling modules. WordPress on WooCommerce 11.1 follows the same front-controller pattern.

Pick Nginx when you control the server, expect meaningful traffic, or need reverse-proxy features. It is the default for new Laravel 13 and Symfony 8.1 projects with PHP-FPM. Use it to terminate TLS at the edge, rate-limit, cache anonymous responses, serve static assets efficiently, or route multiple apps by server_name on one VPS. Community tooling and Forge-style panels assume Nginx. Static-heavy sites and microservice layouts benefit from its lower memory per connection.

Choose Apache when you depend on .htaccess without SSH access, run on shared hosting or cPanel LAMP stacks, or maintain legacy mod_php code without migration budget. WordPress multisite and non-technical owners who edit permalinks through wp-admin fit Apache well. Apache 2.4 with event MPM and PHP-FPM remains a legitimate production stack. Enterprise environments with existing mod_security rules also keep Apache. For many legal-tech portals, correct PHP-FPM pool sizing and Redis 8.10 sessions mattered more than the web server brand.

Yes. Bind Nginx to ports 80 and 443, terminate TLS 1.3 there, and reverse-proxy to Apache on 127.0.0.1:8080. Only one server should bind public ports.

Yes. It remains common on shared hosting, cPanel, and enterprise setups with mod_security—not obsolete, just less common for new VPS LEMP deployments.

Translating mod_rewrite line-for-line instead of functionally breaks admin login and API routes; prefer try_files, map, and named locations over fragile if blocks. Missing realpath_root in FastCGI params causes blank Laravel pages on symlinked Deployer releases. Apache LimitRequestBody becomes client_max_body_size—legal portals uploading PDFs hit 413 at Nginx’s 1 MB default; set 32m or higher. Confirm PHP-FPM socket ownership lets www-data connect. Test trailing slashes, pagination, uploads, and webhooks via hosts file before DNS cutover; keep Apache on an alternate port for rollback.

Neither executes PHP natively in a recommended setup. Nginx passes requests via fastcgi_pass to PHP-FPM; Apache uses mod_proxy_fcgi or the legacy mod_php on older hosts. Laravel 13 and WordPress both rely on this handoff. Tune PHP-FPM pool sizes, OPcache, and Redis 8.10 session caching on either server. Performance differences for dynamic pages often sit in single-digit milliseconds when both are configured correctly. Slow queries, N+1 problems, and missing indexes hurt latency far more than switching web servers.

Apache reads per-directory .htaccess on every request unless AllowOverride is disabled. That enables WordPress users to drop rewrite rules without SSH, but it adds filesystem stat calls on every hit—a hidden cost on busy sites. Nginx requires all rules in server blocks; you edit config and reload with no runtime directory scanning. For production Laravel or high-traffic WordPress, move rewrites into the virtual host and disable AllowOverride None. The operational convenience of .htaccess trades against measurable overhead under load.

Both support HTTP caching, compression, and TLS 1.3 on Ubuntu 24 with OpenSSL 1.1.1+. Nginx proxy_cache and fastcgi_cache are widely used for full-page caching of anonymous responses; mod_cache on Apache works but sees less adoption in greenfield PHP projects. Configure cipher suites and HSTS on whichever server terminates HTTPS. Monitor web server and PHP-FPM together—active processes, slow logs, 502/504 rates. Tools like Netdata expose Nginx stub_status and PHP-FPM metrics. For authenticated Laravel apps, Redis 8.10 beats micro-optimising worker_processes.

Entry VPS boxes in Nepal typically run Rs 1,500–3,000 per month, roughly USD 11–22. Both web servers run on plain Ubuntu; the price difference comes from provider defaults—Apache cPanel versus unmanaged Ubuntu—more than Nginx versus Apache licensing, since both are free open-source software.

A common post-migration 502 shows little in Laravel logs because the failure sits between Nginx and PHP-FPM. Check that the unix socket path matches fastcgi_pass, PHP-FPM is running, and www-data can read the socket—run ls -la on /run/php/ and confirm pool user ownership. Wrong SCRIPT_FILENAME without realpath_root also breaks symlinked Deployer 7 releases. Verify nginx -t passes and reload succeeded. Keep Apache on an alternate port during cutover so you can roll back instantly if upstream connectivity fails.

LEMP is Nginx, PHP-FPM, and MySQL 9.7—the typical 2026 default for new Laravel 13 VPS deployments. LAMP is Apache, PHP-FPM, and MySQL 8.4 LTS, still common on managed and shared hosting. Both pair with Redis 8.10 for sessions and caching. For greenfield PHP 8.3+ projects you control, Nginx plus PHP-FPM is the practical community default. Apache plus PHP-FPM closes most dynamic performance gaps when event MPM is enabled. Hybrid topologies—Nginx on 443 proxying to Apache on 8080—let you migrate incrementally without rewriting every WordPress .htaccess rule overnight.

Share this article

0 Comments

Leave a comment

Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

Quick Contact Options
Choose how you want to connect me: