I can build a website that looks good and feels alive. A form takes my input, I press submit, and the data vanishes.
But where does it go?
"The backend," you might say. Fair, but how does it get there? A week ago, I couldn't have told you. So I ran my first Node.js server to find out. This post is what I learned, including the mistakes.
Frontend vs. Backend
The frontend is everything you can see: the sign-in form, the buttons, the layout. The backend is everything else, working out of sight: the server, the API, the database, and the rules that connect them.
Whenever you open a website, your browser (the client) sends a request to a server. The server does its work and sends a response back. That's the client-server model, and nearly everything on the web follows it.
Take logging in. You type your details and press the button. The backend checks them against records in the database and replies with either "Welcome!" or "Wrong password."
Do you always need a database? No. A backend can work without a database. You need one when your application needs to save data persistently.
Why Node.js and Not Just JavaScript?
JavaScript was originally built to run inside the browser. Node.js is a runtime built on Google's V8 engine that lets JavaScript run outside the browser. It's not a new language, just another place JavaScript can run.
I chose it because I can use one language for both frontend and backend. Node.js also comes with npm, a package manager that helps developers install and manage libraries, so you don't have to write everything yourself.
Building My First Node.js Server
Step 1: Install Node.js
Download the LTS version from nodejs.org, then check that it worked:
node -v
npm -v
If both show version numbers, you're ready.
Step 2: Create a project
mkdir my-first-backend
cd my-first-backend
npm init -y
This creates a project folder and a package.json file, which stores your project's details and dependencies.
Step 3: Write the server
Create a file named server.js:
const http = require('http');
const PORT = process.env.PORT || 3000;
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello from my first Node.js server!');
});
server.listen(PORT, () => {
console.log(`Server running at http://localhost:${PORT}`);
});
-
httpis a built-in Node.js module. -
createServer()creates a server that runs your callback for every incoming request. -
reqis the incoming request, andresis the response you send back. -
res.end()sends the message and finishes the response. -
server.listen(PORT)waits for requests on the specified port. By default, that's port3000. A port is like a numbered door on your computer.
Step 4: Run it
node server.js
The terminal keeps running. That's normal, because the server is waiting for requests. Press Ctrl + C to stop it.
Step 5: Open your browser
Visit http://localhost:3000. You should see:
Hello from my first Node.js server!
Seeing my own server answer my browser made everything click.
What actually happened?
- The browser sent an HTTP request to my server.
- Node.js ran my callback function.
- The server sent back a response, and the browser displayed it.
localhost means my own computer, so the server is accessible locally. A deployed server runs on a remote machine and can be accessed by others if it's configured for public access.
My server doesn't receive or store form data yet. It simply returns a message. To handle real form submissions, I'll need to read the incoming request body, validate the data, and decide whether to store it in a database.
5 Common Problems I Faced (and How I Fixed Them)
1. EADDRINUSE: port already in use
I ran node server.js and got an error saying port 3000 was already in use. I had forgotten that my old server was still running in another terminal. I stopped it with Ctrl + C and ran the command again.
If you can't find the old terminal, identify the process using the port:
netstat -ano | findstr :3000
The last column shows the process ID (PID). After confirming that it's the process you want to stop, run:
taskkill /PID 1234 /F
Replace 1234 with the actual PID.
You can also use a different port, like 3001.
2. Cannot find module
Node told me it couldn't find my file. The cause was a small typo in the file name, and I was also in the wrong folder.
node sever.js # wrong
node server.js # right
npm install express # install Express if needed
Now I check the spelling and run dir on Windows (or ls on macOS and Linux) to confirm I'm in the right folder.
3. Connection refused
My browser showed "This site can't be reached." The server wasn't running, so nothing was listening. I started it again and the page loaded.
node server.js
Also make sure the port in the browser (localhost:3000) matches the port the server is using.
4. No error handling
I didn't think about this at first, because my server only returned one message. But unhandled errors can cause requests to fail or, in some cases, bring down a server. That's why error handling matters.
For example, try/catch can handle errors when parsing JSON:
try {
const data = JSON.parse('not valid json');
console.log(data);
} catch (err) {
console.error('Invalid JSON:', err.message);
}
Here, the invalid JSON is caught instead of causing an uncaught exception. In a real server, I'd also validate incoming requests and handle errors from asynchronous operations appropriately.
5. Hardcoding the port and secrets
I initially wrote 3000 directly in my code. That works on my laptop, but hosting services may provide a port through an environment variable. That's why I used:
const PORT = process.env.PORT || 3000;
server.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Secrets like API keys and database passwords should never be hardcoded into your code.
For local development, they can go in a .env file. I add that file to .gitignore so it isn't accidentally committed to GitHub:
.env
node_modules/
For production, secrets should be configured securely through the hosting platform's environment settings.
Where Does Express Come In?
As apps grow, handling every request by hand gets repetitive. Express is a framework that makes building servers and APIs easier. It isn't built in, so install it first:
npm install express
Then create a simple server:
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.send('Welcome to the homepage!');
});
app.listen(PORT, () => {
console.log(`Express server running on port ${PORT}`);
});
app.get('/') means "when someone sends a GET request to the homepage, run this function."
What I Learned
I started this journey with one question: where does my data go?
Now I know. It goes to a server, a program that waits for requests and answers them. My first one only said “Hello,” but it was mine, and it was running on my own laptop.
Next stop: REST APIs and MongoDB. I’m not afraid of the backend anymore. I’m curious about it.


Top comments (1)
Insightful