Ports and conflicts in local development
A port is a number from 0 to 65535 that tells your machine which program should receive a connection. Normally only one program can listen on a given address and port, so a second dev server either fails to start or moves to another port by itself. To fix a clash, find the process that owns the port, decide whether it is yours to stop, then stop it politely or give your server a different port. To prevent clashes, give each project a fixed port and write the plan down once.
Why dev servers clash
A server binds an address and a port, then listens. Normally the operating system lets only one program hold that pair, so a second bind fails with EADDRINUSE. Defaults make a clash likely: Next.js, Nuxt, and Rails all default to 3000, and Django and Laravel’s artisan serve both default to 8000. The network port entry covers the number ranges and why TCP and UDP have separate port spaces. The ports index maps which tools share a default.
What a tool does when its port is busy
Tools react in three ways. Some move to another port without asking, so the server may not be where you configured it: Vite does this unless you pass --strictPort, and Next.js does it only if you did not choose a port. Some fail and exit, such as Django, Flask, and Rails. Angular asks in a terminal and exits with an error in a script. Read the URL your server prints before you open a browser tab.
Reading order
- The server will not start. Follow find what is using a port and free it, or let the port in use command generator write the commands for your system.
- Another device cannot reach it. Read localhost vs 127.0.0.1 vs 0.0.0.0, then the localhost and loopback address entries.
- You are setting up a stack. Give each service its own port with the local dev port planner before you write any config.
- One tool misbehaves. Open its page from the ports index, for example PostgreSQL.
Stopping it from happening again
Set each project’s port in one place, and make the tool fail instead of drifting where it supports that, as --strictPort does in Vite. In Node.js tests, listen on port 0 and read the port the operating system assigns.
Where Rig fits
Everything above works without Rig. Rig’s who_owns_port MCP tool finds the owner with lsof (netstat and tasklist on Windows), returns its process ID and command, and suggests a free port, and kill_port sends SIGTERM before SIGKILL. The Rig app also shows who owns a busy port and offers to reclaim it: see Common port conflicts and Ports, crashes, and reclaim.
Limits
A port that is free when you check can be taken before your server binds, so a check is a hint, not a lock. The command generator writes commands and never runs them, and the planner works only from the list you give it, so neither can see what is running on your machine.
Tools in this topic
- Free tool
Port in use command generator
Get the exact commands to find which process uses a port and stop it on macOS, Linux, or Windows, with every flag explained and the safe order first.
- Free tool
Local dev port planner
List the services you run locally and get a port plan with no clashes. It flags privileged and ephemeral ports and gives .env, Procfile, and Compose snippets.
Guides in this topic
- Guide
Find what is using a port and free it
Find the process listening on a port and stop it safely on macOS, Linux, and Windows, with commands for each system, TERM before KILL, and fixes that last.
- Guide
localhost vs 127.0.0.1 vs 0.0.0.0
What localhost, 127.0.0.1, and 0.0.0.0 mean for a dev server, who can reach each bind address, and why your phone cannot open 127.0.0.1.
Glossary terms in this topic
- Glossary
EADDRINUSE
EADDRINUSE is the error code for “address already in use”. What it is, how it works, and a common confusion.
- Glossary
Network port
A network port is a 16-bit number, 0 to 65535, that identifies an endpoint on a host for a transport protocol such as TCP or UDP.
- Glossary
localhost
localhost is the reserved hostname for the machine you are on. What it is, how it works, and a common confusion.
- Glossary
Loopback address
A loopback address is an IP address that sends traffic back to the same machine. What it is, how it works, and a common confusion.
Port references in this topic
- Port guide
Vite dev server
Vite tries the next available port by default, so the port it ends up on may not be the one you configured.
- Port guide
Next.js dev server
next dev moves to the next free port, but only if you did not choose one.
- Port guide
Nuxt dev server
From Nuxt 4.6, nuxt dev moves to another free port when the one it asked for is taken, logs which port it chose, and exits instead if you pass --strictPort.
- Port guide
Astro dev server
Astro tries the next available port when the one you gave is already in use, so the server may not be on 4321.
- Port guide
Angular dev server
ng serve checks the port before it starts.
- Port guide
Storybook dev server
Without --exact-port, Storybook looks for a free port starting at the one you asked for and moves on.
- Port guide
Laravel artisan serve
php artisan serve tries the next port.
- Port guide
Django runserver
Django does not look for another port. runserver prints “Error: That port is already in use.” and exits with status 1, so nothing serves your project until you start it again on a free port, for example python manage.py runserver 8001.
- Port guide
Rails server
Rails does not look for another port. rails server resolves the port once, from -p, then the PORT environment variable, then 3000, so when that port is taken the web server cannot bind and the start fails.
- Port guide
Flask development server
Flask does not pick another port.
- Port guide
PostgreSQL server
When the port is busy, the server does not start.
- Port guide
MySQL server
mysqld cannot start while another program holds the TCP/IP port or Unix socket file it wants.
Knowledge base articles in this topic
Blog posts in this topic
- Blog
Port already in use, without lsof
Rig owns the ports your projects bind. When :3000 is taken, you see which process has it and reclaim it from the board instead of another lsof ritual.
- Blog
Reclaim a port from the board
When :3000 is taken, Rig shows which process owns it. Reclaim without another lsof archaeology session.
Related topics
Frequently asked questions
Why does my dev server say the port is already in use?
Another socket already holds that address and port. It is often an earlier copy of the same server still running in another tab, a background job, or a container. Find the owner and read its command before you stop anything.
Do two tools with the same default port always clash?
Only when both run at once on the same address. Some tools then move to another port by themselves and others exit, so check what your tool does when its port is taken. Give each project its own fixed port in its config so the result is the same every time.
Is it safe to kill whatever is using a port?
Not before you look. Read the command and its parent first. Your own earlier dev server is safe to stop. A database, a system service, or another user’s process is not yours to stop, so move your app to another port instead. Send a TERM signal first, and keep KILL for a process that ignores it.
Can a free port be taken before my server starts?
Yes. A port that is free when you check can be taken before your server binds, so a check is a hint, not a lock. In Node.js tests, listen on port 0 and the operating system assigns an unused port, which you read from server.address().port once the server is listening.
See how Rig fits in
Rig is a Mac app that starts, stops, and watches the processes in a project from one window. The knowledge base explains each part in plain language.
Related
Section links
- Port in use command generator
- Local dev port planner
- Find what is using a port and free it
- localhost vs 127.0.0.1 vs 0.0.0.0
- EADDRINUSE: definition and meaning
- Network port: definition and meaning
- localhost: definition and meaning
- Loopback address: definition and meaning
- Vite dev server default ports: 5173 and 4173
- Next.js dev server default port: 3000
- Nuxt dev server default port: 3000
- Astro dev server default port: 4321
- Angular dev server default port: 4200
- Storybook dev server default port: 6006
- Laravel artisan serve default port: 8000
- Django runserver default port: 8000
- Rails server default port: 3000
- Flask development server default port: 5000
- PostgreSQL server default port: 5432
- MySQL server default ports: 3306 and 33060
- Common port conflicts
- Ports, crashes, and reclaim
- LAN share with QR
- Firewall and network tips
- Port already in use — without lsof
- Reclaim a port from the board
- Running local dev processes: from terminal tabs to a process manager
- MCP open_url gotchas