Learning objectives
After reading this article you will be able to:
- Understand what a web server does between the request and the response
- Tell a static file server, an application server and a reverse proxy apart
- Know when to use Nginx, Apache or Node.js itself
Every time you open a website, something on the other end receives the browser's request and decides what to send back. That something is the web server. Sometimes it is Nginx handing over an HTML file, sometimes Apache running PHP, sometimes your own Node.js code answering with JSON.
Understanding what the web server does explains a lot that otherwise looks like magic: why a static site is cheap to host, why you get a 502 when your app crashes, and why so many people put Nginx in front of Node.
What is a web server?#
A web server is a program that listens on a network port, receives HTTP requests and sends back HTTP responses. The response can be a file that already exists on disk (HTML, CSS, an image), a page generated on the fly by an application, or data for an API.
The term is also used for the machine that runs this program. In practice, when someone asks "which web server do you use?", the answer is software: Nginx, Apache, Caddy, or the server built into your language.
By default, HTTP uses port 80 and HTTPS uses port 443. In development you often see ports like 3000 or 8080, because on Linux ports below 1024 require special privileges.
How does a web server work under the hood?#
The life of a request almost always follows the same steps:
- Listen. The server opens a port and waits for TCP connections.
- Accept and decrypt. A connection arrives. If it is HTTPS, the server runs the TLS handshake with the domain's certificate.
- Read the request. Method (
GET,POST), path (/products/42), headers (Host,Cookie,Accept) and sometimes a body. - Decide what to do. The
Hostheader tells it which site to serve. The path tells it whether to read a file from disk or forward the request to an application. - Respond. It sends the status code (
200,404,500), headers (Content-Type,Cache-Control) and the body. - Log. It writes a line to the access log, with IP, path, status and duration.
A real exchange, simplified:
GET /index.html HTTP/1.1
Host: example.com
Accept: text/html
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 1256
Cache-Control: max-age=3600
<!doctype html>...When something goes wrong along the way, the status code tells you where. A 404 is a file or route that does not exist; a 502 is the web server complaining about the application behind it. The details are in HTTP 500, 502, 503 and 504 errors.
Static server, application server and reverse proxy: what is the difference?#
The same software can play different roles, and that is where most of the confusion comes from:
- Static file server. Reads ready-made files from disk and returns them as they are. Fast and light, because it runs no code per request. This is what serves a static site.
- Application server. Runs your code to build each response: queries the database, applies rules, renders HTML or JSON. An Express, Django or Laravel app plays this role.
- Reverse proxy. Sits in front of one or more applications, receives the visitor's request and forwards it. It usually handles TLS, compression, caching and load distribution. See what a reverse proxy is.
A common setup combines all three: Nginx receives everything on port 443, serves /static/ straight from disk and forwards the rest to a Node.js process on port 3000.
What is Nginx?#
Nginx is an open source HTTP server and reverse proxy, known for handling many connections with little memory. According to its official docs, it has one master process, which reads the configuration and maintains the workers, and several worker processes, which handle requests with an event-based model. The number of workers can match the number of CPU cores.
Configuration lives in central files, organized in server and location blocks. The example below serves static files and forwards everything else to an application:
server {
listen 80;
server_name example.com;
# static files straight from disk: /static/logo.png comes from /var/www/static/logo.png
location /static/ {
root /var/www;
}
# everything else goes to the Node.js application
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}After editing, nginx -t checks the syntax and nginx -s reload applies the configuration. If the new configuration has an error, the master process keeps the old one running.
When to use it: as a reverse proxy in front of applications, for static sites, for TLS termination on your own server (VPS) and for response caching.
What is Apache?#
The Apache HTTP Server (httpd) is one of the oldest web servers still in wide use. Its architecture revolves around modules. Multi-processing modules (MPMs) define how it accepts connections: prefork (one process per connection, compatible with older software), worker and event (threaded). On modern systems the default is almost always event.
Apache's best-known feature is .htaccess: a file placed in a directory that changes the configuration for that directory only, without admin access to the server. That is why it dominates shared hosting with PHP and WordPress. Apache's own docs recommend avoiding .htaccess when you have access to the main configuration, because the server looks for these files in every directory on every request, which costs performance.
When to use it: shared hosting, PHP applications that ship with an .htaccess file, and environments that need per-directory rules.
Is Node.js a web server?#
It can be. Node.js ships the node:http module, which creates a complete HTTP server in a few lines. The Node docs explain that an app runs in a single process, without creating a thread per request, and uses non-blocking I/O to handle many connections at once.
// server.mjs: a minimal web server with no dependencies
import { createServer } from "node:http";
const port = Number(process.env.PORT ?? 3000);
const server = createServer((req, res) => {
if (req.url === "/") {
res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" });
res.end("Hello from the web server\n");
return;
}
res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
res.end("Not found\n");
});
// 0.0.0.0 accepts connections from outside the container, not just the machine itself
server.listen(port, "0.0.0.0", () => console.log(`Listening on port ${port}`));Run it with node server.mjs and test it with curl -i http://localhost:3000/. In practice, almost nobody writes routes by hand: frameworks like Express, Fastify or Next.js sit on top of the same http module.
In this model, Node is the application server. It can serve static files, but it is not optimized for that the way Nginx is. TLS and caching usually live in a layer in front.
Nginx, Apache or Node: which should you use?#
| Nginx | Apache | Node.js (http, Express) |
|
|---|---|---|---|
| Typical role | Reverse proxy and static files | Files, PHP, shared hosting | Application server |
| Model | Event-driven, workers | MPMs (prefork, worker, event) | One process, non-blocking I/O |
| Configuration | Central files | Central files and per-directory .htaccess |
JavaScript code |
| Runs your logic | No (forwards to the app) | Yes, with modules such as PHP | Yes, it is the app |
A few rules of thumb:
- Pure static site: any file server works, and many hosts serve the files without you configuring anything. See the difference between static and dynamic websites.
- Node.js, Python or Go app on a VPS: the app listens on an internal port and Nginx sits in front with TLS.
- WordPress or legacy PHP: Apache with
.htaccessis the path of least resistance. - Application hosting platform: the platform's edge usually plays the reverse proxy role, and you only write the app. See the difference in web hosting vs app hosting.
How to do this on Square Cloud#
The setup in this article, a reverse proxy in front and the app behind it, comes already assembled on Square Cloud. The platform network plays the edge Nginx role, with an Anycast CDN, HTTP/3, WebSockets, a WAF and automatic TLS, and every web application gets a *.squareweb.app subdomain with HTTPS. You write only the application server (Express, FastAPI, Django, Laravel or another) and deploy it to an isolated container, among several runtimes such as Node.js, Python and Go. See the runtimes available today on Runtimes. The app must listen on 0.0.0.0, on the port in the PORT variable, which the platform sets, and the proxy does not cut long connections: WebSocket and SSE pass through unbuffered.
If the site has no server-side code, the static sites runtime is this article's file server, already configured: nginx is always running and serving your folder, and an update (a commit, an upload or an edit in the file manager) goes live right away, with no nginx -s reload and no restart. For a SPA, a vite.html answers every path that isn't a file.
Each web application needs at least 512 MB of your plan's RAM, and Hobby, from R$12.49 per month, covers sites; custom domains start on Standard. The cookieless web analytics included in every plan shows visits, routes and status codes collected on the server, which helps you find the 404s and 5xx errors your app returns. See how to publish on the Sites page.
Website hosting
Static and SSR sites with automatic TLS and a global CDN
FAQs
Is a web server hardware or software?
The term covers both, but in everyday use it almost always means the software, such as Nginx, Apache or a Node.js process, that speaks HTTP. The machine it runs on is the physical or virtual server.
Do I need Nginx to run a Node.js application?
No. Node.js handles HTTP on its own. Nginx comes in as a reverse proxy when you want TLS, caching, static files or several apps on one IP, and many hosting platforms already play that role in front of your app.
What is the difference between Nginx and Apache?
Both serve files and act as proxies. Nginx uses an event-driven model and central configuration. Apache has multi-processing modules (MPMs) and accepts per-directory .htaccess files, common in shared PHP hosting.
Which port does a web server listen on?
By default, HTTP uses port 80 and HTTPS uses 443. In development, ports like 3000 or 8080 are common, and on hosting platforms the port usually comes from the platform through an environment variable.
More in Websites
See all 20 articles- What is a static site (and how to host one)A static site is a set of ready-made HTML, CSS and JavaScript files served the same to every visitor. Learn how it works, when to use one and how to host it.
- How much does it cost to host a website?Hosting a website costs anywhere from nothing to a few dozen dollars a month. See what goes into the bill: hosting, domain, traffic and extras, with real limits.
- How much does static site hosting cost?Hosting a static site costs between zero and a few dozen dollars a month in most cases. See how traffic sets the price, with step-by-step math.
- How much does it cost to host a Next.js app?Hosting a Next.js app costs from zero with a static export to tens of dollars a month with a server. See the billing models, traffic math and hidden costs.