Backend — Easy Notes

Full Notes Interview Q&A

The same backend topics, explained simply. Read this first, then move on to the full notes. Each topic number matches the full notes.

Part 1 — Foundations

1. What Backend Is

In plain words

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.
Client browser / mobile app Server your Node.js code Database stores the data 1. request 2. query 3. data 4. response The client asks. The server thinks. The database remembers. Almost every backend feature is this same round trip.
The basic request flow. Learn this picture well. Every other topic adds one piece to it.
Remember: frontend checks are for a nice user experience. Backend checks are for safety and correct data.

2. How the Internet Works

In plain words

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.
Remember: DNS finds the server, TCP connects to it, TLS makes it private, and HTTP carries the actual request.

3. HTTP Basics

In plain words

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
Remember: 401 means "I don't know who you are". 403 means "I know you, but you can't do this".

4. Cookies, Caching and CORS

In plain words

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-Cookie header. 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=3600 says "keep it for one hour".
  • CORS is a browser rule. A page on a.com cannot read data from b.com unless b.com says yes.
  • The server says yes with the Access-Control-Allow-Origin header.
  • CORS only exists in browsers. Tools like Postman ignore it. So CORS is not security for your API.
Remember: a CORS error is the browser protecting the user. You fix it on the server, by allowing the right origin.
Part 2 — Node.js

5. What Node.js Is

In plain words

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 */ });
Remember: Node is fast because it never sits idle while waiting for I/O (input/output like disk and network).

6. The Event Loop

In plain words

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.

Call stack runs your JS, one line at a time Helpers (OS) timers, files, network, database Callback queue finished jobs wait in line hand off done Event loop: when the call stack is empty, bring in the next callback Waiting happens in the helpers, so the one JS thread is never stuck doing nothing.
A simple model of the event loop. The full notes show the real phases, but this picture is enough for most interviews.

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
Remember: sync code first, then microtasks (promises), then macrotasks (timers). And never block the loop.

7. Async Code

In plain words

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/await makes async code look like normal code. Use try/catch for errors.
  • Promise.all runs 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
  }
}
Remember: async/await is just a nicer way to write promises. Use Promise.all when jobs don't depend on each other.

8. Streams & Buffers

In plain words

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);
Remember: streams keep memory use small and steady, no matter how big the file is.

9. Modules, Memory and Processes

In plain words

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() and module.exports. ES Modules: import and export.
  • 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.json lists your packages. package-lock.json locks 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
Remember: one Node process uses one CPU core for your JS. Use cluster or PM2 to use them all.
Part 3 — Building APIs

10. Express Basics

In plain words

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.

Request logger next() express.json next() auth next() Route handler res.json(data) no token? send 401, stop order matters: top to bottom
Each middleware either calls 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.body is 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
Remember: Express is just routes plus a chain of middleware. Order matters: first registered, first run.

11. Project Structure

In plain words

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.
src/ ├─ routes/ URL → controller ├─ controllers/ read req, send res ├─ services/ business rules ├─ models/ database work ├─ middleware/ auth, validation, errors └─ server.js starts the app
Remember: controller = HTTP, service = rules, repository = database. Each layer only talks to the one below it.

12. Errors & Validation

In plain words

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" });
});
Remember: validate at the door, throw errors anywhere, and handle them in one place.

13. REST API Design

In plain words

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, not POST /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
Remember: nouns in the URL, actions in the HTTP method, and always paginate lists. GraphQL is the main alternative: the client picks the fields it wants.

14. Files, Email and Real-time

In plain words

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.
Remember: files go to object storage, emails go to a background job, and live updates use WebSockets.
Part 4 — Data

15. Database Basics

In plain words

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.
Remember: PostgreSQL is a safe default. Choose MongoDB when your data is naturally document-shaped.

16. SQL Basics

In plain words

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

  • SELECT reads, INSERT adds, UPDATE changes, DELETE removes.
  • WHERE filters rows. ORDER BY sorts. LIMIT takes only a few.
  • JOIN combines two tables. INNER JOIN = only matches. LEFT JOIN = all left rows, even with no match.
  • GROUP BY makes groups. HAVING filters 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;
Remember: WHERE filters rows before grouping. HAVING filters groups after grouping.

17. Indexes

In plain words

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 EXPLAIN to see if your query uses an index.
-- Make "find orders by user" fast
CREATE INDEX idx_orders_user ON orders (user_id);
Remember: an index trades slower writes for much faster reads. It is the first fix for a slow query.

18. Transactions

In plain words

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.
  • COMMIT saves the changes. ROLLBACK undoes 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)
Remember: a transaction is "all or nothing". Explain ACID with the bank transfer example.

19. MongoDB / NoSQL

In plain words

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
}
Remember: embed what you read together; reference what is shared or keeps growing.

20. ORMs & Migrations

In plain words

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 } });
Remember: N+1 is the most common ORM performance bug. Fix it by fetching related data in one go.

21. Caching & Redis

In plain words

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.

App Redis cache fast (memory) Database slower (disk) 1. check HIT: fast reply 2. MISS: ask the database 3. save a copy Next time, the same request is a HIT.
Cache-aside: check the cache first. On a miss, read the database and the app saves a copy in the cache with an expiry time.

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;
}
Remember: caching trades fresh data for speed. Always decide how and when the cached copy gets updated.
Part 5 — Security

22. Login Basics

In plain words

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
Remember: hash passwords with bcrypt, and check permission plus ownership on every request.

23. Sessions, JWT and OAuth

In plain words

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.

CLIENT SERVER POST /login email + password token (a signed JWT) server checked the password, then signed the token GET /orders header: Authorization: Bearer <token> 200 OK + your orders server checked the signature first The token proves who you are. The server stores no session.
Login with a JWT. The client sends the token on every request. The server only checks the signature.

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. localStorage can 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
Remember: sessions are easy to cancel; JWTs scale easily but are hard to cancel. Short access token + refresh token is the usual answer.

24. Attacks & Defences

In plain words

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: SameSite cookies, 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]);
Remember: never build SQL with string joining. Use parameterized queries, and check permissions on every request.
Part 6 — Scale & Ops

25. Architecture Patterns

In plain words

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.
Remember: start with a monolith. Split into microservices only when a part really needs to scale or be owned separately.

26. Scaling

In plain words

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.

Users Load balancer shares the traffic Server 1 same code Server 2 same code Server 3 same code Shared database + Redis
Horizontal scaling. Servers keep no user data in memory, so any server can answer any request.

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.
Remember: stateless servers behind a load balancer, plus caching and a well-indexed database. That answers most "how would you scale?" questions.

27. Queues & Background Jobs

In plain words

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));
Remember: if the user doesn't need to wait for it, put it in a queue.

28. Testing

In plain words

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
});
Remember: test behaviour and edge cases (empty, wrong user, duplicate), not just the happy path.

29. Deployment

In plain words

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
Remember: Docker for the same environment everywhere, env variables for config, CI/CD for safe automatic releases.

30. Observability

In plain words

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");
Remember: metrics tell you something is wrong, traces tell you where, and logs tell you why.
Revision

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.
Remember: in an interview, give the simple answer first, then one example. That is better than a long, perfect definition.

Learning Path

Go step by step. Build something small at each step.

  1. HTTP basics — methods, status codes, JSON, headers.
  2. JavaScript async — promises and async/await. Everything else depends on this.
  3. Node.js — modules, the event loop, reading files.
  4. Express — routes, middleware, error handling.
  5. One database — PostgreSQL with basic SQL, or MongoDB with Mongoose. Learn indexes early.
  6. Auth — bcrypt, JWT or sessions, checking permissions.
  7. Project — build a full CRUD API (create, read, update, delete) with login, validation and pagination.
  8. Next level — Redis caching, a background queue, file uploads, a few tests.
  9. Deploy it — Docker, environment variables, put it online.
  10. Then — read the full notes and practise the interview Q&A.
Remember: for every feature, ask three questions. What if it is called twice? What if the wrong user calls it? What if it is called 10,000 times a minute?