If you're learning backend development, you've probably seen things like:
localhost:3000 localhost:5000 :80 :443 At first, the port number can seem like just another configuration value.
But why does a server need a port when it already has an IP address?
If one server is running a Node.js API, PostgreSQL, Redis, and NGINX at the same time, how does the operating system know which application should receive an incoming request?
That's the problem ports solve.
What Is a Port?
A network port is a logical endpoint used to identify a network service or application on a device.
A simple mental model is:
IP Address → Which machine? Port → Which service? For example:
192.168.1.10:3000 Here:
-
192.168.1.10is the IP address. -
3000is the port.
The IP address gets the traffic to the correct machine.
The port helps the operating system determine which application should receive that traffic.
Why Isn't an IP Address Enough?
This is the key question.
Imagine a server with this IP address:
203.0.113.10 That server could be running:
NGINX Node.js API PostgreSQL Redis SSH All of these services are running on the same machine, so they share the machine's network interfaces and IP addresses.
If a packet arrives for:
203.0.113.10 the operating system knows:
This traffic belongs to this machine.
But it still needs to determine:
Which application should receive it?
That's where the port comes in.
The services can listen on different ports:
203.0.113.10:22 → SSH 203.0.113.10:80 → HTTP 203.0.113.10:443 → HTTPS 203.0.113.10:3000 → Node.js 203.0.113.10:5432 → PostgreSQL 203.0.113.10:6379 → Redis Now the operating system has a way to distinguish between the services.
Think of It Like a Building
A useful analogy is an apartment building.
Suppose the building has this address:
221B Example Street That's similar to an IP address.
Inside the building:
Apartment 101 Apartment 102 Apartment 103 are different destinations.
The building address tells you which building to visit.
The apartment number tells you where inside the building to go.
Networking works similarly:
IP Address → Building Port → Service/endpoint So:
203.0.113.10:443 can be thought of as:
203.0.113.10 → Which machine? 443 → Which network service? This is an analogy, not a literal description of how networking works, but it's a useful mental model.
IP Address vs Port
Let's separate the two concepts.
IP address
An IP address identifies a network destination.
Example:
203.0.113.10 Port
A port identifies a logical network endpoint associated with a service.
Example:
443 Together:
203.0.113.10:443 You can think of this as:
Machine + Service This is why developers frequently write endpoints as:
IP:PORT What Does It Mean When an Application "Listens" on a Port?
You'll often hear:
"My Node.js server is listening on port 3000."
This means the application has created a network socket and is waiting for incoming connections on that port.
For example:
app.listen(3000); Conceptually:
Node.js Application │ ↓ Listen on :3000 │ ↓ Operating System The operating system can now associate incoming traffic for that listening endpoint with the appropriate process.
A Simple Node.js Example
Consider this Express application:
const express = require("express"); const app = express(); app.get("/", (req, res) => { res.send("Hello from the server!"); }); app.listen(3000, () => { console.log("Server running on port 3000"); }); When you run it, the application starts listening on:
localhost:3000 You can then open:
http://localhost:3000 The simplified flow is:
Browser │ │ HTTP request ↓ localhost:3000 │ ↓ Operating System │ ↓ Node.js Process │ ↓ GET / │ ↓ HTTP Response The port 3000 is what allows the operating system to identify the network endpoint associated with your Node.js application.
What Is localhost?
localhost refers to the local machine.
So:
localhost:3000 means:
Connect to port 3000 on this computer.
This is extremely common during development.
You might run:
npm run dev and your application may start at:
http://localhost:3000 The browser and application are communicating through the local machine's networking stack.
One Server Can Have Many Ports
A server doesn't have just one port.
A single machine can have many applications listening on different ports.
For example:
SERVER 203.0.113.10 │ ┌────────────┼────────────┐ ↓ ↓ ↓ :80 :443 :3000 HTTP HTTPS Node.js │ :5432 PostgreSQL The IP address identifies the machine.
The ports distinguish the network services.
Common Ports
Some port numbers are commonly associated with specific services.
| Port | Common use |
|---|---|
22 | SSH |
53 | DNS |
80 | HTTP |
443 | HTTPS |
3000 | Common development port |
5432 | PostgreSQL |
6379 | Redis |
These are conventions, not permanent rules.
For example, Node.js does not require port 3000.
You could write:
app.listen(5000); and your application would listen on:
:5000 Ports Are Logical, Not Physical
A network port is not a physical connector.
It's different from:
- USB port
- Ethernet port
- HDMI port
A network port is a logical number used by networking protocols and the operating system.
For TCP and UDP, port numbers range from:
0 - 65535 TCP and UDP Ports
Ports are used with transport protocols such as TCP and UDP.
For example:
TCP + 443 is commonly used for HTTPS.
And:
UDP + 53 is commonly used for DNS.
This is important because a port number alone isn't the complete identity of a network endpoint.
Conceptually:
Protocol + IP + Port forms part of the information used to identify network communication.
Source Port vs Destination Port
When a client connects to a server, there is usually both a source port and a destination port.
For example:
Client 192.168.1.20:52000 │ │ ↓ Server 203.0.113.10:443 Here:
Source IP: 192.168.1.20 Source Port: 52000 Destination IP: 203.0.113.10 Destination Port: 443 The server is listening on port 443.
The client's operating system typically selects an ephemeral source port for the connection.
How Can Thousands of Users Connect to Port 443?
A common beginner question is:
If a server has only one port 443, how can thousands of users connect to it?
Because the destination port isn't the only thing that identifies a connection.
For TCP, the connection is associated with information such as:
Source IP Source Port Destination IP Destination Port Protocol For example:
Client A 10.0.0.5:51001 ↓ Server 10.0.0.10:443 and:
Client B 10.0.0.6:51002 ↓ Server 10.0.0.10:443 Both clients can connect to the same server port.
Their connection information is different, so the operating system can keep track of them independently.
What Happens If Two Applications Use the Same Port?
Suppose you already have:
Application A → :3000 Then you start another application configured for:
Application B → :3000 You will generally get an error because the address/port combination is already in use.
In Node.js, you may see:
EADDRINUSE which means:
Address already in use The solution is usually to stop the existing process or use another port:
Application A → :3000 Application B → :4000 Open, Closed, and Blocked Ports
These terms are often confused.
Open Port
A service is listening and accepting connections.
Port 443 ↓ HTTPS service ↓ Listening Closed Port
Nothing is listening on the port.
Port 3000 ↓ No service Blocked Port
A firewall or network security rule prevents traffic from reaching the service.
For example:
Internet │ ↓ Firewall │ ├── 443 ✓ Allowed └── 3000 ✗ Blocked A service can be listening on a port but still be unreachable from outside the machine if a firewall blocks the traffic.
Ports and Firewalls
Ports become especially important when deploying applications to a server.
Suppose your server has:
22 → SSH 80 → HTTP 443 → HTTPS 3000 → Node.js 5432 → PostgreSQL You probably don't want every port publicly accessible.
A typical setup might allow:
80 → Public 443 → Public while restricting:
22 → Restricted 3000 → Internal 5432 → Internal A firewall controls which traffic can reach which ports.
This reduces the server's attack surface.
Why Keep Databases Behind the Firewall?
Suppose PostgreSQL is running on:
:5432 You usually don't want random internet clients connecting directly to it.
A better architecture is often:
INTERNET │ ↓ :443 │ ↓ NGINX │ ↓ Node.js :3000 │ ↓ PostgreSQL :5432 Here:
-
443is publicly accessible. - Node.js can communicate with PostgreSQL internally.
- PostgreSQL doesn't need to be exposed directly to the internet.
This is a common production architecture.
What Happens When You Visit a Website?
Consider:
https://example.com There are several steps involved.
First, the domain needs to resolve to an IP address through DNS.
Conceptually:
example.com ↓ DNS ↓ 203.0.113.10 The browser then connects to the server using HTTPS.
HTTPS normally uses:
443 So the simplified flow is:
https://example.com ↓ 203.0.113.10:443 ↓ Server ↓ HTTPS service The request is then processed by the server's networking and application layers.
Why Don't We Write :443?
You may have noticed that we normally write:
https://example.com instead of:
https://example.com:443 That's because 443 is the standard port for HTTPS.
The browser knows the default port associated with the protocol.
Similarly:
http://example.com normally uses port:
80 But when you're developing locally, you often see:
localhost:3000 because 3000 isn't the default HTTP port.
A Real Production Example
Let's look at a common Node.js deployment.
You might have:
INTERNET │ │ HTTPS :443 ↓ ┌─────────────┐ │ NGINX │ └─────────────┘ │ │ proxy ↓ localhost:3000 │ ↓ ┌─────────────┐ │ Node.js │ │ API │ └─────────────┘ │ ↓ PostgreSQL The user visits:
https://example.com The request reaches the server through port 443.
NGINX receives it and can forward it internally to:
localhost:3000 where the Node.js application is running.
The user doesn't need to know that Node.js is using port 3000.
Why Is Port 3000 So Common?
You may see this constantly in JavaScript development:
localhost:3000 That's simply a common convention.
There is nothing inherently special about 3000.
Your application could use:
3001 4000 5000 8000 8080 or another available port.
For example:
app.listen(8080); means the application listens on:
:8080 Port Ranges
Port numbers range from:
0 → 65535 They are commonly divided into three broad categories:
0–1023 Well-known ports 1024–49151 Registered ports 49152–65535 Dynamic/private ports This classification is useful as a general mental model, although the exact rules and allocations are more nuanced.
Well-Known Ports
Ports 0–1023 are commonly referred to as well-known ports.
Examples include:
22 → SSH 53 → DNS 80 → HTTP 443 → HTTPS These ports are associated with widely used protocols and services.
Registered Ports
The range:
1024–49151 contains registered ports associated with various applications and services.
Again, registration does not mean an application is forced to use that port.
Applications can often be configured to use another available port.
Dynamic or Ephemeral Ports
When a client makes an outgoing connection, the operating system typically chooses a temporary source port.
For example:
Client 192.168.1.20:53124 │ ↓ Server 203.0.113.10:443 Here:
53124 could be an ephemeral source port.
The exact ephemeral port range depends on the operating system and its configuration.
A Complete Request Flow
Let's combine everything.
Suppose a browser wants to access:
https://api.example.com/users A simplified flow looks like:
Browser │ │ DNS lookup ↓ api.example.com │ ↓ Server IP │ │ TCP connection ↓ Server:443 │ ↓ HTTPS server / NGINX │ │ reverse proxy ↓ Node.js:3000 │ ↓ /users route │ ↓ Database │ ↓ Response │ ↓ Browser Notice how the port appears at different stages.
The public service may be available on:
443 while the internal Node.js application may be listening on:
3000 The port doesn't represent the entire application architecture. It identifies a network endpoint at a particular layer of the system.
Ports Are About Routing Traffic to Processes
At the application level, it is tempting to think:
"Port 3000 belongs to Node.js."
That's not quite correct.
Port 3000 doesn't inherently belong to Node.js.
Instead, a process binds to a network endpoint.
For example:
Node.js → 0.0.0.0:3000 The operating system maintains the relationship between the network endpoint and the process.
Another application could use port 3000 after the Node.js process stops and releases it.
So ports are not permanently assigned to applications.
A Few Important Things to Remember
1. A port is not an IP address
IP → Machine/network destination Port → Network service/endpoint 2. A server can use many ports
:22 :80 :443 :3000 :5432 can all exist on the same machine.
3. Port numbers are configurable
Node.js doesn't require 3000.
4. Open doesn't always mean publicly reachable
A firewall can block traffic even when a service is listening.
5. Ports are logical
They're not physical connectors.
6. TCP and UDP have separate port spaces
A TCP port and a UDP port with the same number aren't the same endpoint.
The Mental Model You Should Remember
If you're learning backend development, don't memorize hundreds of port numbers.
Understand this:
REQUEST │ ↓ IP ADDRESS │ ↓ SERVER │ ↓ PORT │ ↓ SERVICE │ ↓ APPLICATION Or even simpler:
IP Address → Which machine? Port → Which service? For example:
203.0.113.10:443 means:
203.0.113.10 → destination machine 443 → destination port And:
localhost:3000 means:
localhost → this machine 3000 → service listening on port 3000 Conclusion
Ports are one of those networking concepts that look complicated at first but become straightforward once you understand the problem they're solving.
A server can run many network services at the same time. The IP address helps identify the machine, while the port identifies the network endpoint associated with a particular service.
A typical server might look like:
SERVER 203.0.113.10 │ ┌────────────┼────────────┐ ↓ ↓ ↓ :22 :443 :3000 SSH HTTPS Node.js │ :5432 PostgreSQL So when you see:
IP:PORT don't think of the port as just a random number.
Think:
"I know which machine I want. Now I need to specify which network service I want to communicate with."
That's the fundamental purpose of network ports.