DEV Community

HimanshuTamoli
HimanshuTamoli

Posted on

Network Ports Explained: How Servers Know Which Application Should Handle a Request

If you're learning backend development, you've probably seen things like:

localhost:3000
localhost:5000
:80
:443
Enter fullscreen mode Exit fullscreen mode

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?
Enter fullscreen mode Exit fullscreen mode

For example:

192.168.1.10:3000
Enter fullscreen mode Exit fullscreen mode

Here:

  • 192.168.1.10 is the IP address.
  • 3000 is 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
Enter fullscreen mode Exit fullscreen mode

That server could be running:

NGINX
Node.js API
PostgreSQL
Redis
SSH
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

That's similar to an IP address.

Inside the building:

Apartment 101
Apartment 102
Apartment 103
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

So:

203.0.113.10:443
Enter fullscreen mode Exit fullscreen mode

can be thought of as:

203.0.113.10 → Which machine?
443           → Which network service?
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Port

A port identifies a logical network endpoint associated with a service.

Example:

443
Enter fullscreen mode Exit fullscreen mode

Together:

203.0.113.10:443
Enter fullscreen mode Exit fullscreen mode

You can think of this as:

Machine + Service
Enter fullscreen mode Exit fullscreen mode

This is why developers frequently write endpoints as:

IP:PORT
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

Conceptually:

Node.js Application
        │
        ↓
   Listen on :3000
        │
        ↓
Operating System
Enter fullscreen mode Exit fullscreen mode

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");
});
Enter fullscreen mode Exit fullscreen mode

When you run it, the application starts listening on:

localhost:3000
Enter fullscreen mode Exit fullscreen mode

You can then open:

http://localhost:3000
Enter fullscreen mode Exit fullscreen mode

The simplified flow is:

Browser
   │
   │ HTTP request
   ↓
localhost:3000
   │
   ↓
Operating System
   │
   ↓
Node.js Process
   │
   ↓
GET /
   │
   ↓
HTTP Response
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

means:

Connect to port 3000 on this computer.

This is extremely common during development.

You might run:

npm run dev
Enter fullscreen mode Exit fullscreen mode

and your application may start at:

http://localhost:3000
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

and your application would listen on:

:5000
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

TCP and UDP Ports

Ports are used with transport protocols such as TCP and UDP.

For example:

TCP + 443
Enter fullscreen mode Exit fullscreen mode

is commonly used for HTTPS.

And:

UDP + 53
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Here:

Source IP:        192.168.1.20
Source Port:      52000

Destination IP:   203.0.113.10
Destination Port: 443
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

For example:

Client A
10.0.0.5:51001
      ↓
Server
10.0.0.10:443
Enter fullscreen mode Exit fullscreen mode

and:

Client B
10.0.0.6:51002
      ↓
Server
10.0.0.10:443
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Then you start another application configured for:

Application B → :3000
Enter fullscreen mode Exit fullscreen mode

You will generally get an error because the address/port combination is already in use.

In Node.js, you may see:

EADDRINUSE
Enter fullscreen mode Exit fullscreen mode

which means:

Address already in use
Enter fullscreen mode Exit fullscreen mode

The solution is usually to stop the existing process or use another port:

Application A → :3000
Application B → :4000
Enter fullscreen mode Exit fullscreen mode

Open, Closed, and Blocked Ports

These terms are often confused.

Open Port

A service is listening and accepting connections.

Port 443
   ↓
HTTPS service
   ↓
Listening
Enter fullscreen mode Exit fullscreen mode

Closed Port

Nothing is listening on the port.

Port 3000
   ↓
No service
Enter fullscreen mode Exit fullscreen mode

Blocked Port

A firewall or network security rule prevents traffic from reaching the service.

For example:

Internet
   │
   ↓
Firewall
   │
   ├── 443   ✓ Allowed
   └── 3000  ✗ Blocked
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

You probably don't want every port publicly accessible.

A typical setup might allow:

80  → Public
443 → Public
Enter fullscreen mode Exit fullscreen mode

while restricting:

22   → Restricted
3000 → Internal
5432 → Internal
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Here:

  • 443 is 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

The browser then connects to the server using HTTPS.

HTTPS normally uses:

443
Enter fullscreen mode Exit fullscreen mode

So the simplified flow is:

https://example.com
        ↓
203.0.113.10:443
        ↓
      Server
        ↓
   HTTPS service
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

instead of:

https://example.com:443
Enter fullscreen mode Exit fullscreen mode

That's because 443 is the standard port for HTTPS.

The browser knows the default port associated with the protocol.

Similarly:

http://example.com
Enter fullscreen mode Exit fullscreen mode

normally uses port:

80
Enter fullscreen mode Exit fullscreen mode

But when you're developing locally, you often see:

localhost:3000
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

The user visits:

https://example.com
Enter fullscreen mode Exit fullscreen mode

The request reaches the server through port 443.

NGINX receives it and can forward it internally to:

localhost:3000
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

That's simply a common convention.

There is nothing inherently special about 3000.

Your application could use:

3001
4000
5000
8000
8080
Enter fullscreen mode Exit fullscreen mode

or another available port.

For example:

app.listen(8080);
Enter fullscreen mode Exit fullscreen mode

means the application listens on:

:8080
Enter fullscreen mode Exit fullscreen mode

Port Ranges

Port numbers range from:

0 → 65535
Enter fullscreen mode Exit fullscreen mode

They are commonly divided into three broad categories:

0–1023
Well-known ports

1024–49151
Registered ports

49152–65535
Dynamic/private ports
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

These ports are associated with widely used protocols and services.


Registered Ports

The range:

1024–49151
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Here:

53124
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Notice how the port appears at different stages.

The public service may be available on:

443
Enter fullscreen mode Exit fullscreen mode

while the internal Node.js application may be listening on:

3000
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

2. A server can use many ports

:22
:80
:443
:3000
:5432
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Or even simpler:

IP Address → Which machine?
Port       → Which service?
Enter fullscreen mode Exit fullscreen mode

For example:

203.0.113.10:443
Enter fullscreen mode Exit fullscreen mode

means:

203.0.113.10 → destination machine
443           → destination port
Enter fullscreen mode Exit fullscreen mode

And:

localhost:3000
Enter fullscreen mode Exit fullscreen mode

means:

localhost → this machine
3000      → service listening on port 3000
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

So when you see:

IP:PORT
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (1)

Collapse
 
marcusykim profile image
Marcus Kim •

The NGINX:443 Node.js:3000 PostgreSQL:5432 example makes the deployment implications concrete, especially alongside your distinction between listening and publicly reachable. One detail I'd add is that the bind address matters too: a service listening on 127.0.0.1:3000 has different exposure from one on 0.0.0.0:3000, even though the port is identical. For a small team, documenting the intended bind address and access rules for each service makes deployment reviews easier and helps catch accidental exposure before it becomes an incident.