What happens when you run your code
Processes, ports and localhost: the three ideas underneath every "it runs on my machine" moment.
Starting from zero
This course is about one journey: an app that runs on your laptop, seen by exactly one person (you), turning into a system that safely serves millions of people at once. That journey has a shape. The same few decisions repeat at every scale — add a server, add a database, add a cache, add a queue, split a service — and each one has a clear moment where it stops being optional. By the end of this course you'll have a mental checklist for all of it, plus a cheat sheet that fits on one page.
We start at the very beginning, because the words "server," "client," and "host" get used loosely all the time, and precision here pays off for the rest of the course.
Imagine your computer is a big house with lots of rooms. When you tell one room "wake up and wait by the door for anyone with the number 3000 on their letter," that room is now a little worker waiting for mail addressed exactly to door 3000. Anyone else in the house can walk up and hand it a letter. That's really all a running app is.
A process is just a running program
When you typenpm start, python app.py, or ./my-server, the operating system does the same basic thing every time: it loads your program into memory, gives it its own private chunk of memory, its own execution timeline, and starts running its instructions. That running instance is called a process.
A process is not your source code — your code is inert text sitting on disk. A process is that code actively executing, with:
- Its own memory (variables, loaded modules, open files)
- A process ID (PID) the OS uses to track it
- A relationship to other processes (a parent that started it, children it might spawn)
If you close the terminal or kill the process, all of that goes away. This is why a locally running app disappears the moment you press Ctrl+C — the process ends, and nothing is left running in memory.
Your machine
├── Process 1 (PID 501): your text editor
├── Process 2 (PID 812): your browser
├── Process 3 (PID 1190): your app — "node app.js"
└── Process 4 (PID 1191): a database, e.g. Postgres
A port is a mailbox number
A single machine can be running many processes at once, and several of them might want to talk over the network. The operating system needs a way to know: "this incoming network message — which of the 40 running processes is it for?"
The answer is a port: a number from 0–65535 that a process can bind to, telling the OS "route anything addressed to this port, on this machine, to me." Once your app binds to port 3000, the OS will not let a second process also bind to port 3000 at the same time — that's the source of the extremely commonError: address already in use message.
Incoming request → "give this to port 3000" → OS routes it → your Node.js process
Incoming request → "give this to port 5432" → OS routes it → your Postgres process
Common well-known ports you'll keep running into throughout this course: 80 (HTTP), 443 (HTTPS), 22 (SSH), 5432 (Postgres), 3306 (MySQL), 6379 (Redis). None of these are hardcoded into the internet — they're just conventions everyone agreed to follow so you don't have to guess.
localhost is "this machine, talking to itself"
When you visithttp://localhost:3000 or http://127.0.0.1:3000, you are not going out onto the internet at all. 127.0.0.1 is a special loopback address — every computer reserves it to mean "me." A request to 127.0.0.1 never touches your network card, your Wi-Fi, or your router. It goes directly from your browser process to your app process, both running on the exact same physical machine.
This explains a very common beginner confusion: telling a friend to open http://localhost:3000 on their own laptop does nothing useful — their localhost refers to their machine, which isn't running your app. Your app has to actually be reachable from their machine's network path, which is the whole subject of the next lesson.
The math behind it: what one process can actually do
Every process, no matter how well written, does work at a finite rate. Say each request your app handles — reading a database row, formatting a response, sending it back — takes 50 milliseconds of pure work, handled one at a time, in sequence.
That's the entire ceiling for a single, strictly-sequential worker. If 21 requests arrive in the same second, one of them waits. This single formula — work-per-request divided into available time — is the seed of almost every scaling decision in this course. Later lessons build on it: concurrency (doing other things while waiting on I/O), multiple processes, multiple machines, and caching (making the "0.05 seconds" number smaller in the first place) are really just four different ways of pushing against this one limit.
Common mistakes
- Confusing "my code" with "my running app." Editing a file on disk does nothing to an already-running process — you have to restart it (or use a tool with hot-reload, which does the restart for you automatically).
- Assuming a port number is special or reserved by the internet. Port 3000 isn't "the React port" by any global rule — it's just the default a few tools picked. Any unused port number works.
- Sharing a
localhostlink with someone else and being confused when it doesn't work for them — theirlocalhostis their own machine. - Forgetting a process dies with its terminal. Closing the terminal (or losing SSH connection to a remote machine) kills the process unless it was started in a way designed to survive that (covered later, in the hosting lesson).
A few more concepts worth knowing
- Environment variables — small key/value settings (like
PORT=3000orDATABASE_URL=...) passed into a process at start time, instead of hardcoded into the source code, so the same code can run differently in different places. - Standard streams (stdin/stdout/stderr) — every process has an input stream and two output streams (normal output and errors); this is why
console.logshows up in your terminal. - Exit codes — a process reports a number (0 for success, nonzero for failure) when it stops, which is how scripts and infrastructure automatically detect crashes.
- Threads — a process can have multiple threads of execution sharing the same memory; most beginner apps don't manage these directly, but it's the mechanism underneath concurrency inside one process.
Summary
A running app is just a process, bound to a port, waiting for messages.localhost means "this exact machine," which is why it can't be shared with anyone else as-is. And every process — however small — has a hard throughput ceiling set by how long each unit of work takes, which is the number every later scaling technique is trying to improve. Next, we look at what a "server" really is, and why the word describes a role your own laptop can play, not a special kind of hardware.