Backend — Easy Notes
The same backend topics, explained simply. Read this first, then move on to the full notes. Each topic number matches the full notes.
1. What Backend Is
The backend is the part of an app that runs on a server. A server is a computer you control, not the user's phone or laptop.
Think of a restaurant. The dining room is the frontend. The kitchen is the backend. Customers never see the kitchen, but all the real cooking happens there.
Key points
- The client (browser or mobile app) sends a request. The server sends back a response.
- The backend stores data in a database, so it is still there tomorrow.
- It holds the business rules. Example: "Can this user cancel this order?"
- It checks who you are (login) and what you may do (permissions).
- It talks to other services: payments, email, SMS, AI.
- Never trust the browser. Anyone can change frontend code. So the backend must check everything again.
2. How the Internet Works
Computers find each other with IP addresses, like 142.250.1.1. People use names like google.com. DNS turns the name into the IP address.
DNS is like your phone's contact list. You tap "Mom". The phone finds the real number for you.
Key points
- DNS = the internet's phone book. Name in, IP address out.
- TCP = a safe delivery method. Data arrives complete and in order. Used by websites and databases.
- UDP = a fast delivery method. No checks, some data may be lost. Used for video calls and games.
- HTTPS = HTTP plus encryption (TLS). Nobody in the middle can read or change your data.
- A port is a door number on a computer. 443 = HTTPS, 5432 = Postgres, 3000 = Node in development.
- A load balancer shares traffic between many servers. A CDN keeps copies of files close to users.
3. HTTP Basics
HTTP is the language a client and a server use to talk. The client sends a request. The server sends a response.
It is like ordering at a counter. You say what you want (the method and path). You get your food and a receipt (the body and the status code).
Key points
- A request has a method, a path, headers (extra info) and sometimes a body (the data).
- Methods: GET = read, POST = create, PUT = replace, PATCH = change a part, DELETE = remove.
- Stateless means the server forgets you after each request. That is why we need cookies and tokens.
- Idempotent means "doing it twice gives the same result as once". GET, PUT and DELETE are idempotent. POST is not.
- Status codes: 2xx = success, 4xx = client's mistake, 5xx = server's mistake.
- Know these: 200 OK, 201 Created, 400 Bad Request, 401 Not logged in, 403 Not allowed, 404 Not found, 500 Server error.
GET /api/users/7 HTTP/1.1 // method + path
Authorization: Bearer abc123 // header: who I am
HTTP/1.1 200 OK // status: it worked
{ "id": 7, "name": "Ada" } // body: the data
4. Cookies, Caching and CORS
A cookie is a small note the server gives the browser. The browser sends it back on every request.
A cookie is like a wristband at a concert. You show it at every door, so staff know you already paid.
Key points
- The server sets a cookie with the
Set-Cookieheader. The browser sends it back automatically. HttpOnly= JavaScript cannot read it.Secure= only sent over HTTPS.SameSite= blocks some attacks from other sites.- HTTP caching means the browser keeps a copy.
Cache-Control: max-age=3600says "keep it for one hour". - CORS is a browser rule. A page on
a.comcannot read data fromb.comunlessb.comsays yes. - The server says yes with the
Access-Control-Allow-Originheader. - CORS only exists in browsers. Tools like Postman ignore it. So CORS is not security for your API.
5. What Node.js Is
Node.js lets you run JavaScript on a server, outside the browser. It uses one main thread. A thread is one worker that runs code.
Node is like one fast waiter. He takes your order and gives it to the kitchen. He does not stand and wait. He serves other tables until your food is ready.
Key points
- Node = V8 (the engine that runs JS) + libuv (a helper library for slow work like files and network).
- Blocking = the code waits and nothing else can run. Non-blocking = the code hands off the slow job and keeps going.
- Most backend work is waiting: for the database, for a file, for another API. Node is great at waiting.
- Good for: APIs, chat apps, real-time apps, streaming.
- Bad for: heavy math or video processing. This keeps the one thread busy and everyone waits.
- "Single-threaded" means your JavaScript runs on one thread. Behind the scenes, helpers work in parallel.
// Blocking: everyone waits while the file loads
const data = fs.readFileSync("big.txt");
// Non-blocking: Node keeps serving others, then runs the callback
fs.readFile("big.txt", (err, data) => { /* use data */ });
6. The Event Loop
The event loop is a loop that never stops. It checks: "Is the main thread free? Is any slow job finished?" If yes, it runs the next finished job's code.
Think of a doctor's waiting room. Patients wait in a line. When the doctor is free, the next patient goes in. The doctor sees one patient at a time.
Key points
- Your normal code (sync code) always runs first, top to bottom.
- A callback is a function you give to Node to run later, when a job is done.
- Microtasks (promise
.then,process.nextTick) run before macrotasks (setTimeout, I/O). - If your code runs a very long loop, the event loop is blocked. No other request gets served.
- Fix for heavy work: move it to a worker thread or a background job.
console.log("1"); // sync: runs first
setTimeout(() => console.log("4"), 0); // macrotask: runs last
Promise.resolve().then(() => console.log("3")); // microtask: before timers
console.log("2"); // sync
// Output: 1, 2, 3, 4
7. Async Code
Async code starts a job now and gets the result later. A promise is an object that says "I will give you a value later, or an error".
A promise is like the buzzer a café gives you. You sit down. It buzzes when your coffee is ready, or the staff tell you they ran out.
Key points
- Three styles, old to new: callbacks → promises → async/await.
- Too many nested callbacks is called callback hell. It is hard to read.
- A promise has 3 states: pending (waiting), fulfilled (success), rejected (error).
async/awaitmakes async code look like normal code. Usetry/catchfor errors.Promise.allruns jobs at the same time. It fails if any one job fails.- Common mistake: forgetting
await. You get a promise, not the data.
async function loadPage(id) {
try {
// Both run at the same time, so it is faster
const [user, orders] = await Promise.all([getUser(id), getOrders(id)]);
return { user, orders };
} catch (err) {
console.error("Something failed", err); // catch any error here
}
}
8. Streams & Buffers
A buffer is a box of raw bytes (computer data). A stream moves data in small pieces, called chunks, instead of all at once.
A stream is like drinking with a straw, sip by sip. You don't need to pour the whole bottle into your mouth at once.
Key points
- Reading a 2 GB file at once needs 2 GB of memory. Streaming it needs only a small amount.
- Four types: Readable (source), Writable (destination), Duplex (both), Transform (changes data on the way).
- Used for big files, video, uploads, downloads.
- Backpressure = "slow down" signal when the receiver is slower than the sender.
pipe()handles it for you.
// Send a big file to the user, piece by piece
fs.createReadStream("big-video.mp4").pipe(res);
9. Modules, Memory and Processes
A module is one file of code that you can share with other files. Node has two ways to do it: require (old) and import (new).
Modules are like LEGO pieces. Each piece does one job. You snap them together to build the app.
Key points
- CommonJS:
require()andmodule.exports. ES Modules:importandexport. - A module is loaded once and then cached (saved). Every file gets the same copy.
- Garbage collection = Node cleans up memory you no longer use, automatically.
- A memory leak = memory that keeps growing and is never freed. Common cause: a global array that only grows.
- To use all CPU cores, run many copies of the app (cluster or PM2).
package.jsonlists your packages.package-lock.jsonlocks exact versions. Commit both.
// math.js
export function add(a, b) { return a + b; }
// app.js
import { add } from "./math.js";
console.log(add(2, 3)); // 5
10. Express Basics
Express is a small library that makes building a Node server easy. It gives you routes (which URL runs which code) and middleware.
Middleware is like airport security. You pass through checks one by one: ticket, ID, bag scan. Any check can stop you. If all pass, you reach the gate.
next() to pass the request on, or sends a response and stops the chain.Key points
- A route = a method + a path + a function. Example:
app.get("/users", fn). - A middleware is a function with
(req, res, next). It runs before your route. next()= "go to the next step". If you forget it and send nothing, the request hangs.req.params= parts of the URL.req.query= after the?.req.body= the sent data.express.json()reads JSON bodies. Without it,req.bodyis undefined.- The error handler has 4 arguments
(err, req, res, next)and goes last.
import express from "express";
const app = express();
app.use(express.json()); // middleware: read JSON body
app.get("/users/:id", (req, res) => { // route
res.json({ id: req.params.id }); // send a response
});
app.listen(3000); // start the server
11. Project Structure
Split your code into layers. Each layer has one job. This is called separation of concerns.
In a restaurant, the waiter takes orders, the chef cooks, and the store-room keeper handles stock. Nobody does everyone's job.
Key points
- Routes → match the URL to a controller.
- Controller → reads the request and sends the response. Only HTTP work.
- Service → the business rules. Example: "A shipped order can't be cancelled."
- Repository / model → talks to the database. Only data work.
- Why? Code is easier to test, reuse and change. You can swap the database and touch only one layer.
- Keep secrets and settings in environment variables (
.env), not in code.
12. Errors & Validation
Validation means checking that incoming data is correct before you use it. Error handling means catching problems and sending a clear reply.
Validation is like a bouncer at a club door. He checks your ID before you enter. Bad data never gets inside.
Key points
- Check all input: body, URL params, query string. Never trust the client.
- Use a library like Zod or Joi to describe the correct shape of the data.
- Send 400 or 422 for bad input. Send 500 for unexpected server bugs.
- Use one central error handler. Don't write error replies in 20 places.
- In production, never show the stack trace (internal error details) to users.
- Mass assignment bug: saving the whole
req.body. A user could send"role": "admin". Only pick the fields you allow.
// Central error handler: 4 arguments, registered last
app.use((err, req, res, next) => {
console.error(err); // log full details for you
res.status(err.status || 500)
.json({ message: err.message || "Something went wrong" });
});
13. REST API Design
REST is a simple style for designing APIs. URLs name things (resources). HTTP methods say what to do with them.
A library has shelves for books. "GET book 42" means show it. "DELETE book 42" means remove it. The shelf name stays the same; only the action changes.
Key points
- Use nouns, not verbs:
POST /orders, notPOST /createOrder. - Use plural names:
/users,/products. - Use the correct status code: 201 after create, 404 if not found.
- Pagination = return data in pages, like
?page=2&limit=20. Never return a huge list at once. - Versioning = put a version in the URL, like
/api/v1/. Then old apps keep working. - Keep the same JSON shape for every success and every error.
GET /api/v1/products // list products
GET /api/v1/products/42 // get one product
POST /api/v1/products // create a product
PATCH /api/v1/products/42 // update part of it
DELETE /api/v1/products/42 // delete it
14. Files, Email and Real-time
Apps often need to save uploaded files, send emails, and push live updates. Each has a standard, simple solution.
You don't keep your car in your living room. You use a garage. In the same way, you don't keep big files on your app server. You use file storage like S3.
Key points
- Uploads: use multer to read files. Save them in S3 or Cloudinary, not on the server disk.
- Always check file size and file type. Give files random names.
- Email: use a provider like SendGrid or Resend. Send it in the background, so the API stays fast.
- Polling = the client asks again and again: "Anything new?" Simple, but wasteful.
- WebSocket = a connection that stays open both ways. Best for chat and live games.
- SSE (Server-Sent Events) = the server pushes updates one way. Good for notifications.
15. Database Basics
A database stores data safely, so it survives restarts. There are two main types: SQL (tables) and NoSQL (documents and other shapes).
SQL is like a spreadsheet with strict columns. NoSQL (MongoDB) is like a folder of forms, where each form can have slightly different fields.
Key points
- SQL (Postgres, MySQL): tables, rows, fixed columns, strong rules. Great for money and orders.
- NoSQL (MongoDB): flexible JSON-like documents. Great for data whose shape changes.
- Redis is a key-value store in memory. Very fast. Used for cache and sessions.
- Connection pool = a set of open database connections that requests share. Opening a new one each time is slow.
- CAP theorem in one line: when the network breaks, a distributed database must pick between correct data and staying online.
16. SQL Basics
SQL is the language you use to ask a relational database for data. You describe what you want. The database works out how to get it.
It is like asking a librarian: "Give me all books by this author, newest first." You don't search the shelves yourself.
Key points
SELECTreads,INSERTadds,UPDATEchanges,DELETEremoves.WHEREfilters rows.ORDER BYsorts.LIMITtakes only a few.- JOIN combines two tables. INNER JOIN = only matches. LEFT JOIN = all left rows, even with no match.
GROUP BYmakes groups.HAVINGfilters those groups.- Primary key = unique ID of a row. Foreign key = a link to a row in another table.
- Normalization = don't store the same data in many places.
-- Each user's name and how many orders they made
SELECT u.name, COUNT(o.id) AS total_orders
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
GROUP BY u.name;
17. Indexes
An index is a sorted list that helps the database find rows fast. Without it, the database reads every row.
An index is like the index at the back of a book. You look up a word and jump straight to the page. No need to read the whole book.
Key points
- Without an index, the database does a full scan (checks every row). Very slow on big tables.
- Add indexes on columns you search, join or sort by. Example:
email,user_id. - Indexes make reads faster but writes slower, and they use extra space.
- Don't index every column. Only the ones you really query.
- Use
EXPLAINto see if your query uses an index.
-- Make "find orders by user" fast
CREATE INDEX idx_orders_user ON orders (user_id);
18. Transactions
A transaction groups many database steps into one. Either all steps succeed, or none of them happen.
Sending money to a friend: your account goes down and theirs goes up. If only one step happened, money would vanish. A transaction prevents that.
Key points
- ACID = the 4 promises of a transaction. Atomic = all or nothing. Consistent = rules stay true. Isolated = transactions don't mix. Durable = saved even after a crash.
COMMITsaves the changes.ROLLBACKundoes them.- Race condition = two requests change the same data at the same time. Example: two people buy the last item.
- Fix it with a single safe update, or a lock. Isolation levels control how strict this is; the full notes cover them.
BEGIN;
UPDATE accounts SET balance = balance - 500 WHERE id = 1; -- take money
UPDATE accounts SET balance = balance + 500 WHERE id = 2; -- give money
COMMIT; -- both happen together (or ROLLBACK if anything fails)
19. MongoDB / NoSQL
MongoDB stores data as documents. A document looks like a JSON object. Documents live in collections (like tables).
A document is like a full patient file. Name, address and past visits are all inside one folder, not spread across many cabinets.
Key points
- No fixed columns. Each document can have different fields.
- Embed = put related data inside the document. Good when you always read them together.
- Reference = store only the other document's ID. Good when data is shared or grows forever.
- One document can be at most 16 MB. So never embed a list that grows forever, like comments.
- Mongoose is a Node library that adds schemas (shape rules) to MongoDB.
// One order document, with its items embedded inside
{
"_id": "o1",
"user": "u7", // reference to a user
"items": [ { "product": "Pen", "qty": 2 } ], // embedded list
"total": 40
}
20. ORMs & Migrations
An ORM (Object-Relational Mapper) lets you use the database with normal JavaScript code instead of raw SQL. A migration is a saved file that changes the database structure.
An ORM is a translator. You speak JavaScript, the database speaks SQL, and the ORM translates between you.
Key points
- Popular ORMs: Prisma, Sequelize, TypeORM. Mongoose for MongoDB.
- ORMs save time, but can hide slow queries.
- N+1 problem: 1 query to get a list, then 1 more query for each item. 100 items = 101 queries.
- Fix N+1 by loading related data together (
include,populate, or a JOIN). - Migrations are like Git for your database structure. Never change production tables by hand.
// BAD: one extra query per post (N+1)
for (const post of posts) post.author = await User.findById(post.userId);
// GOOD: load posts and authors together
const posts = await prisma.post.findMany({ include: { author: true } });
21. Caching & Redis
A cache keeps a copy of data in a fast place, so you don't fetch it again and again. Redis is a popular cache that keeps data in memory (RAM).
Keeping water on your desk is a cache. You don't walk to the kitchen for every sip. You only go when the bottle is empty.
Key points
- Cache hit = data found in cache (fast). Cache miss = not found, go to the database.
- TTL (time to live) = how long the copy stays before it expires. Example: 5 minutes.
- Invalidation = deleting the old copy when the real data changes. This is the hard part.
- Cache data that is read often and changes rarely. Example: a product page.
- Redis is also used for sessions, rate limiting, queues and leaderboards.
async function getProduct(id) {
const cached = await redis.get(`product:${id}`); // 1. check cache
if (cached) return JSON.parse(cached); // hit: done
const product = await db.product.findUnique({ where: { id } }); // 2. miss: ask DB
await redis.set(`product:${id}`, JSON.stringify(product), "EX", 300); // 3. save 5 min
return product;
}
22. Login Basics
Authentication = proving who you are (login). Authorization = checking what you are allowed to do.
At a hotel, showing your ID at the front desk is authentication. Your room key opening only your room, not every room, is authorization.
Key points
- Never store passwords as plain text. Store a hash instead.
- A hash is a one-way scramble. You can't turn it back into the password.
- Use bcrypt or argon2. They are slow on purpose, so guessing passwords takes too long.
- A salt is random text added to each password before hashing. Same passwords then get different hashes.
- Roles (admin, user) control what people can do. This is called RBAC (role-based access control).
- Always check ownership: user 5 must not read user 6's invoice just by changing the ID.
const hash = await bcrypt.hash(password, 12); // on sign-up: save this
const ok = await bcrypt.compare(input, user.passwordHash); // on login: true or false
23. Sessions, JWT and OAuth
After login, the server must remember you. Two common ways: a session (the server keeps a record) or a JWT (you carry a signed token).
A session is like a coat check: you get a number and the staff keep your coat. A JWT is like a stamped passport: you carry it, and anyone can check the stamp is real.
Key points
- Session: the server stores your login (in Redis or the database). The browser only holds an ID in a cookie. Easy to log out instantly.
- JWT (JSON Web Token) has 3 parts:
header.payload.signature. The signature proves nobody changed it. - A JWT is not encrypted. Anyone can read the payload. Never put passwords or secrets in it.
- A JWT can't easily be cancelled before it expires. So use a short access token (15 min) plus a refresh token to get new ones.
- Store tokens in an HttpOnly cookie if you can.
localStoragecan be read by attacker scripts. - OAuth = "Login with Google". Google proves who you are, and your app gets a token. Use a library for it.
// Create a token at login
const token = jwt.sign({ id: user.id }, process.env.JWT_SECRET, { expiresIn: "15m" });
// Check it in middleware on later requests
const data = jwt.verify(token, process.env.JWT_SECRET); // throws if fake or expired
24. Attacks & Defences
Attackers try to trick your server with bad input. Most defences follow one idea: keep user data separate from your code.
A bank teller reads your note as a request, not as an order to obey. "Give me everyone's money" on a form is just text, not a command.
Key points
- SQL injection: user input becomes part of the SQL. Fix: parameterized queries (placeholders like
$1). - XSS (Cross-Site Scripting): attacker's JavaScript runs in another user's browser. Fix: escape output, use HttpOnly cookies.
- CSRF (Cross-Site Request Forgery): another site makes your browser send a request with your cookies. Fix:
SameSitecookies, CSRF tokens. - Broken access control: changing an ID in the URL shows someone else's data. Fix: check ownership every time.
- Brute force: guessing passwords many times. Fix: rate limiting (limit requests per minute).
- Also: use HTTPS,
helmet()for safe headers, keep secrets out of Git and logs, update packages.
// UNSAFE: input is glued into the SQL text
db.query("SELECT * FROM users WHERE email = '" + email + "'");
// SAFE: input is sent separately, never run as code
db.query("SELECT * FROM users WHERE email = $1", [email]);
25. Architecture Patterns
A monolith is one app that does everything. Microservices are many small apps, each doing one job, talking over the network.
A monolith is one big shop that sells everything. Microservices are a market with many small stalls. Each stall runs on its own, but they must coordinate.
Key points
- Monolith: simple to build, test and deploy. Can get big and messy over time.
- Microservices: each part scales and deploys alone. But much more complex: network errors, many deploys, harder debugging.
- Start with a modular monolith: one app, with clean separate modules inside.
- API gateway = one front door for many services. It handles login checks and routing.
- Event-driven = services send messages like "OrderPlaced", and others react to them.
26. Scaling
Scaling means handling more users. Vertical = a bigger machine. Horizontal = more machines.
A busy shop can hire one super-fast cashier (vertical), or open more cash counters (horizontal). More counters has no real limit.
Key points
- A load balancer sends each request to a healthy server.
- For horizontal scaling, servers must be stateless: no sessions or files kept inside one server.
- Keep shared state in Redis, the database or S3. Then you can add or remove servers freely.
- The database is usually the bottleneck (the slowest part). Fix it with indexes, caching and read replicas (copies used only for reading).
- Other easy wins: pagination, compression, a CDN, and moving slow work to background jobs.
- Always measure first. Don't guess where the slow part is.
27. Queues & Background Jobs
A queue is a waiting line for jobs. The API puts a job in the line and replies quickly. A separate worker does the job later.
At a dry cleaner, you drop off clothes and get a ticket right away. You don't wait in the shop while they wash. The work happens in the back.
Key points
- Use a queue for slow work: emails, image resizing, PDF reports, imports.
- The user gets a fast reply. The work still happens, just a bit later.
- If a job fails, the queue retries it, waiting a bit longer each time.
- A job may run twice. So make it idempotent: running it twice must not cause harm.
- Tools: BullMQ (uses Redis, great for Node), RabbitMQ, Kafka, AWS SQS.
// In the API: add the job and reply fast
await emailQueue.add("welcome", { email: user.email });
res.status(202).json({ message: "Accepted" });
// In a separate worker process: do the slow work
new Worker("email", async (job) => sendEmail(job.data.email));
28. Testing
Tests are small programs that check your code works. They run automatically, so you catch bugs before users do.
Testing is like a car check before a long trip. You test the brakes, lights and tyres before you drive, not after a crash.
Key points
- Unit test = test one small function alone.
- Integration test = test parts together, like a route plus a real test database.
- E2E (end-to-end) test = test the whole app like a real user.
- Test pyramid: many unit tests, fewer integration tests, very few E2E tests.
- Mock = a fake version of an outside service (like payments), so tests stay fast and safe.
- Tools: Jest or Vitest, plus Supertest to call your API in tests.
it("returns 404 for a missing user", async () => {
const res = await request(app).get("/users/999"); // call the API
expect(res.status).toBe(404); // check the result
});
29. Deployment
Deployment means putting your app on a real server so users can reach it. Docker packs your app and everything it needs into one box, called a container.
A container is like a lunch box. Everything you need is packed inside, so it works the same at home, at school or at work.
Key points
- Docker fixes "it works on my machine". The app runs the same everywhere.
- Environment variables hold settings and secrets. Each environment (dev, staging, production) has its own.
- CI/CD = on every push, tests run automatically (CI), then the app deploys automatically (CD).
- Add a health check route like
/health, so the load balancer knows the app is alive. - Graceful shutdown = finish current requests before stopping the app.
- Take database backups, and test that you can restore them.
# A tiny Dockerfile
FROM node:22-alpine # start from Node
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev # install only production packages
COPY . .
CMD ["node", "server.js"] # start the app
30. Observability
Observability means being able to see what your app is doing in production. It has three tools: logs, metrics and traces.
It is like a car dashboard. Speed and fuel are metrics. The warning light is an alert. The mechanic's notes are logs.
Key points
- Logs = text records of what happened. Example: "Payment failed for order 42".
- Metrics = numbers over time. Example: requests per second, error rate, response time.
- Traces = the path of one request through many services, with time spent at each step.
- Write logs as JSON (structured logs), so you can search them. Use a library like pino.
- Add a request ID to every log line, so you can follow one request.
- Never log passwords, tokens or card numbers. Set alerts for what users feel, like high error rates.
// Hard to search
console.log("User " + id + " failed to pay");
// Easy to search and filter
logger.error({ userId: id, requestId: req.id }, "payment failed");
Quick Revision
The most-asked questions, with short and simple answers. Say these in your own words.
Basics & HTTP
- What does the backend do? It stores data, runs business rules, and checks who you are and what you may do.
- What happens when you type a URL? DNS finds the IP, the browser connects (TCP + TLS), sends an HTTP request, and shows the response.
- What does stateless mean? The server forgets you after each request. Cookies or tokens remind it who you are.
- GET vs POST? GET reads data. POST sends data to create something.
- PUT vs PATCH? PUT replaces the whole thing. PATCH changes only some fields.
- What is idempotent? Doing it twice gives the same result as once. GET, PUT, DELETE are; POST is not.
- 401 vs 403? 401 = not logged in. 403 = logged in, but not allowed.
- What is CORS? A browser rule. The server must allow other websites to read its responses.
Node.js
- What is Node.js? A runtime that runs JavaScript on the server, using V8 and libuv.
- Why is Node fast with one thread? It never waits. Slow jobs go to helpers, and the thread serves others.
- What is the event loop? A loop that runs finished callbacks when the main thread is free.
- Promise vs setTimeout, which runs first? The promise. Microtasks run before timers.
- What is a promise? An object holding a future value: pending, fulfilled or rejected.
- Promise.all? Runs jobs at the same time and waits for all. Fails if any one fails.
- What blocks the event loop? Long sync code, like a huge loop or
readFileSync. - What is a stream? Data moved in small chunks, so memory use stays low.
APIs & Express
- What is middleware? A function
(req, res, next)that runs before the route handler. - What does next() do? Passes the request to the next middleware.
- How do you handle errors in Express? One error middleware with 4 arguments, registered last.
- What is REST? Nouns in URLs, HTTP methods for actions, correct status codes.
- Why paginate? So you never send a huge list. It keeps responses fast and small.
- Why separate controller, service and repository? Each has one job, so code is easier to test and change.
- WebSocket vs polling? WebSocket keeps one open two-way connection. Polling asks again and again.
Databases
- SQL vs NoSQL? SQL = tables with strict rules. NoSQL = flexible documents. Pick by your data's shape.
- What is an index? A sorted lookup that makes reads fast but writes a bit slower.
- What is a transaction? Many steps that all succeed or all fail together.
- What is ACID? Atomic, Consistent, Isolated, Durable.
- INNER vs LEFT JOIN? INNER = only matching rows. LEFT = all left rows, even without a match.
- What is the N+1 problem? One query per item in a list. Fix: load related data together.
- Embed or reference in MongoDB? Embed what you read together. Reference what is shared or grows forever.
- What is caching? Keeping a fast copy of data, often in Redis, with an expiry time (TTL).
Security & Scale
- Authentication vs authorization? Who you are vs what you may do.
- How do you store passwords? Hash them with bcrypt. Never plain text.
- Session vs JWT? Session = server stores login, easy to cancel. JWT = signed token, no lookup, hard to cancel.
- Is a JWT encrypted? No. Anyone can read it. The signature only proves it wasn't changed.
- How do you stop SQL injection? Parameterized queries. Never join input into SQL text.
- Vertical vs horizontal scaling? Bigger machine vs more machines behind a load balancer.
- Why stateless servers? So any server can handle any request, and you can add servers freely.
- Monolith vs microservices? Start with a monolith. Split only when one part really needs it.
- Why use a queue? To do slow work in the background, so the API replies fast.
Learning Path
Go step by step. Build something small at each step.
- HTTP basics — methods, status codes, JSON, headers.
- JavaScript async — promises and async/await. Everything else depends on this.
- Node.js — modules, the event loop, reading files.
- Express — routes, middleware, error handling.
- One database — PostgreSQL with basic SQL, or MongoDB with Mongoose. Learn indexes early.
- Auth — bcrypt, JWT or sessions, checking permissions.
- Project — build a full CRUD API (create, read, update, delete) with login, validation and pagination.
- Next level — Redis caching, a background queue, file uploads, a few tests.
- Deploy it — Docker, environment variables, put it online.
- Then — read the full notes and practise the interview Q&A.