Start MySQL and you get 3306; start PostgreSQL and you get 5432. I usually accept these numbers without a second thought, but one day I started wondering who decided them, and how. Some numbers, like 80 and 443, feel standard. Others, like 3000 and 8080, are the ones you keep running into in local development.
So, using MySQL and PostgreSQL as the entry point, I went digging into the pedigree of port numbers. I covered databases, HTTP, and development servers, relying mainly on official documentation and IANA registration data. It helps a little to think of a port number as a street address, and of IANA as the land registry.
To give away something like a conclusion up front, port numbers come in roughly two types. One is numbers tightly bound to standards and IANA registrations. 80 for HTTP, 443 for HTTPS, 20/21 for FTP, 22 for SSH, and 25 for SMTP fall into this group. For these, the reason the number is used today is relatively clear.
The other is numbers that took root as default settings of products and tools. MySQL's 3306, PostgreSQL's 5432, Tomcat's 8080, 3000 for Rails and Next.js, 5000 for Flask, 8000 for Django, 8888 for Jupyter, and so on. For these, the current default can be confirmed officially, but why that particular number was chosen is often not documented. You can find out who lives there, but not why they picked that address.
How Port Numbers Are Managed
To begin with, port numbers are managed by IANA. RFC 6335 divides them into three broad ranges.
| Range | Name | What it's for |
|---|---|---|
| 0-1023 | System Ports | Standard services such as HTTP, SSH, and DNS |
| 1024-49151 | User Ports | Range that applications and services register and use |
| 49152-65535 | Dynamic / Private Ports | Range for temporary or private use |
On Unix-like operating systems such as Linux, binding to a port below 1024 requires privileges. These are the so-called privileged ports, and the rule has been around for a long time. Given that constraint, it seems entirely natural that high ports have been favored for local development and application servers. Think 8080, 3000, 5000, 8000, and 8888. You can run a server without root.
That said, being registered with IANA and being used by default by some piece of software are two different things. The name on the deed and the person actually living there often don't match. 3000, for example, is a familiar face in web development, but it isn't registered at IANA as a "web development port." Oracle Database's 1521 has long served as the default listener port in Oracle products, yet the IANA registrant isn't Oracle.
Kubernetes API Server's 6443 is the same story. It's commonly used as the default in Kubernetes, but it isn't registered for Kubernetes at IANA. A number can be firmly entrenched in the field and still not match its IANA registrant.
MySQL's 3306
What can be confirmed officially about MySQL is that the default port for the classic MySQL protocol is 3306. MySQL's official documentation treats 3306 as the default. The IANA registry, too, lists 3306 asmysql. Its assignee/contact shows Monty's name. It seems safe to say the registration is tied to Michael "Monty" Widenius, the creator of MySQL.
The crucial question, though, why 3306, is one I couldn't find a clear answer to within the primary sources I checked. The story you often see is that "3306 was chosen because it was the next free number after 3305." Plausible, sure. But at least from the MySQL docs and IANA data I looked at, it's hard to state that explanation as fact.
Here's what I could confirm about MySQL 3306. It is officially MySQL's default. It is registered with IANA asmysql, and Monty's name appears on that registration. Why the number is 3306, however, remains unknown within the scope of this research. That is about as far as it's safe to go.
PostgreSQL's 5432
PostgreSQL, too, has 5432 registered with IANA as the PostgreSQL Database port. Tom Lane's name is in the assignee/contact. Old official PostgreSQL documentation also confirms that default port 5432 was in use from quite early on. At the very least, it's fair to say 5432 took hold early in the history of the PostgreSQL lineage.
Here, too, though, the official archives I checked didn't tell me why it's 5432. PostgreSQL descends from Berkeley POSTGRES. So it's tempting to think the reason for 5432 also dates back to the Berkeley days. But to declare, based only on these sources, that "the meaning of the number 5432 originates at Berkeley" would be a bit reckless.
MySQL 3306 and PostgreSQL 5432 are both numbers that took root as product defaults and are also registered with IANA. The origin of the numbers themselves, on the other hand, is a separate question. That's a territory where primary sources are thin.
Ports for Other Databases
SQL Server's 1433 is described in Microsoft's official documentation as the TCP port used by the default instance. It's also registered with IANA asms-sql-s 1433. Why 1433, though, is something I couldn't find in the primary sources this time.
Oracle Database's 1521 is a slightly different case. Oracle's official documentation describes 1521 as the default port for Oracle Net Listener. It's an extremely well-known number in the field. Look up 1521 at IANA, however, and the registered name isn't Oracle but ncube-lm.
On top of that, IANA carries a note about Oracle's use: "Unauthorized Use Known on port 1521." A standard fixture in the Oracle world, yet hard to call officially registered for Oracle at IANA. It's like a resident who isn't on the deed but has nailed a nameplate to the door and stayed for decades. There's something rather charming about it.
Redis's 6379 and MongoDB's 27017 also have defaults confirmed in official docs. MongoDB's 27017 is registered with IANA as well. But the origins of these numbers, too, weren't clear within the scope of this research.
Elasticsearch is a little more convoluted. Its official documentation describes the default forhttp.port as 9200-9300 and the default for transport.port as 9300-9400, both as ranges. In conversation we tend to say "Elasticsearch is 9200 and 9300." Strictly speaking, though, it's better to separate the value most likely to be used first from the configured range.
HTTP's 80 and HTTPS's 443
HTTP 80 and HTTPS 443, by contrast, were among the easiest origins to trace of everything I looked at. RFC 1945 indicates that when the port is omitted from anhttp:// URL, 80 is assumed. The current RFC 9110 also describes the default for http as TCP 80 and for https as TCP 443. These aren't local development conventions; they're numbers fixed by specification.
Is 8080 Just Two 80s?
At IANA, 8080 is registered ashttp-alt. The description is HTTP Alternate, an alternative port for HTTP. Tomcat also tries to bind to 8080 by default. Its documentation notes that if you change the port, a number above 1024 is preferable. Given the privileged-port restrictions on Unix-like systems, the reason to use a high port like 8080 in place of 80 is easy to understand.
On the other hand, the oft-repeated explanation that "8080 is two 80s side by side" didn't appear in any of the IANA, RFC, or Tomcat primary sources I checked. I get why the number invites that reading. But from primary sources, you can say 8080 is registered as an alternate HTTP port, and no further. You can't claim it became 8080 because someone put two 80s together.
Is 3000 the Web Development Standard?
3000 was the number that left the strongest impression on me during this research. Rails, Express, Create React App, Next.js, Grafana: a great many development tools and applications use 3000. If you do web development,localhost:3000 has become something like a childhood home.
At IANA, however, 3000 is not a web development port. Look it up and you'll find other uses, such as HBCI. It's like checking the deed to your childhood home and finding a stranger's name on it. So 3000 should be seen not as an official web development port but as a de facto standard that took hold in the world of local development.
Rails' old guides use 3000 too, which confirms Rails was using it relatively early. But the sources I checked don't let me go as far as saying Rails is the origin of 3000. Popular projects like Rails used it, and Express and Next.js did too. As a result, the feeling that "web development means 3000" grew stronger. Wouldn't that be the most natural reading?
5000, 8000, 8888, 4200, 5173
Flask uses 5000, Django 8000, Jupyter Notebook 8888, Angular CLI 4200, and Vite 5173 as defaults. All of these current defaults can be confirmed in official docs. The reasons, though, weren't in the official documentation I checked. Why Flask is 5000, why Django is 8000, why Jupyter is 8888: all remain a mystery.
For Vite's 5173 and Angular's 4200, you'll find assorted theories floating around elsewhere. If you limit yourself to what primary sources can confirm, though, there isn't much to say. The current default is confirmed; the reason for the number is unknown. Writing it that way is simply the honest thing to do.
Docker, Kubernetes, Prometheus
For the Docker daemon's remote API, 2375 is described as the conventional port for non-TLS and 2376 for TLS. Docker's documentation uses the word "conventional." It's closer to a Docker operational custom than a number fixed by a standard.
Kubernetes API Server listens on 6443 by default. But at IANA, 6443 isn't Kubernetes; it'ssun-sr-https. Once again, the product default and the IANA registered name don't match.
Prometheus uses 9090 as its default. The default is confirmed in official docs. Still, why 9090 is something I couldn't trace within the scope of this research.
Sorting Out the Folklore
Something struck me while researching. With port numbers, "how it's used today" and "why that number was chosen" tend to get jumbled together. Lining up common explanations against what I could confirm gives the following.
| Common explanation | View within what I researched |
|---|---|
| HTTP uses 80 | Confirmed in RFC |
| HTTPS uses 443 | Confirmed in RFC |
| 8080 is an alternate HTTP port | Confirmed at IANA |
| 8080 is two 80s side by side | Not confirmed in the primary sources this time |
| MySQL 3306 was the next free number after 3305 | Not confirmed in the primary sources this time |
| PostgreSQL 5432 comes from Berkeley and the reason is already explained | Use of 5432 is confirmed, but the reason for the number is not |
| 3000 is an official web development port | Not so at IANA; better viewed as a de facto standard |
| Oracle 1521 is for Oracle at IANA too | The IANA registrant is not Oracle |
| Elasticsearch's default is strictly 9200 and 9300 | Official settings describe it as a range |
| Kubernetes 6443 is for Kubernetes at IANA too | Not for Kubernetes at IANA |
The Full List of Ports
While I'm at it, here's a list of the numbers covered.
| Port | Common use | View this time |
|---|---|---|
| 20/21 | FTP | Number from the standard protocol |
| 22 | SSH | Number from the standard protocol |
| 25 | SMTP | Number from the standard protocol |
| 53 | DNS | Number from the standard protocol |
| 67/68 | DHCP | Number from the standard protocol |
| 80 | HTTP | Default specified in RFC |
| 443 | HTTPS | Default specified in RFC |
| 8080 | HTTP alternate / Tomcat | Confirmed as an HTTP alternate port, but the wordplay origin is unconfirmed |
| 3000 | Rails / Express / Next.js, etc. | De facto for web development, but not a web standard at IANA |
| 3306 | MySQL | Official default and IANA registration confirmed, reason for the number unconfirmed |
| 5432 | PostgreSQL | Official default and IANA registration confirmed, reason for the number unconfirmed |
| 1433 | SQL Server | Official default and IANA registration confirmed, reason for the number unconfirmed |
| 1521 | Oracle Net Listener | Standard for Oracle, but the IANA registrant is not Oracle |
| 5000 | Flask | Official default confirmed, reason for the number unconfirmed |
| 6379 | Redis | Official default confirmed, reason for the number unconfirmed |
| 8000 | Django | Official default confirmed, reason for the number unconfirmed |
| 8888 | Jupyter Notebook | Official default confirmed, reason for the number unconfirmed |
| 1883 | MQTT | Standard MQTT port registered with IANA |
| 8883 | MQTT over TLS | Standard secure MQTT port registered with IANA |
| 2375/2376 | Docker daemon remote API | Conventional Docker ports |
| 27017 | MongoDB | Official default and IANA registration confirmed, reason for the number unconfirmed |
| 4200 | Angular CLI | Official default confirmed, reason for the number unconfirmed |
| 5173 | Vite | Official default confirmed, reason for the number unconfirmed |
| 6443 | Kubernetes API Server | Kubernetes default, but the IANA registrant is for another use |
| 9090 | Prometheus | Official default confirmed, reason for the number unconfirmed |
| 9200/9300 | Elasticsearch | Strictly, both HTTP and transport are described as ranges |
Defaults That Became Rules
The more familiar a port number is, the more you assume there must be some clear reason behind it. Actually digging in, though, I found surprisingly few whose origins can be traced through primary sources. Some, like HTTP 80 and HTTPS 443, are easy to explain within the standards. Numbers like MySQL 3306, PostgreSQL 5432, 3000, 5000, 4200, and 5173, meanwhile, are used as a matter of course today, yet rarely come with an account of why that number.
This feels very much like the history of software. Something that started as a small default value spreads through users, documentation, sample code, Docker images, cloud configurations and so on. Then, before anyone notices, it's fixed in place as "just the way it is." A number someone typed on a whim may have been copied into configuration files around the world for decades. It's a little amusing to think about.
So when talking about port numbers, separating two things makes everything much clearer. One is that we use this number now; the other is that we know why it was chosen. The nameplate and the deed don't always tell the same story.
That's the story of my look into the origins of common port numbers, starting from MySQL's 3306 and PostgreSQL's 5432. For these two as well, the fact that they're used is clear. But as for the original reason packed into those numbers, at least within what I researched, there was still a blank left. The more ordinary the number, the less its origin gets told.