Development
Fullstack Developer
The definitive guide for full-stack engineers, covering Frontend (React, Next.js, TypeScript), Backend (Node.js, Express), Databases (SQL/NoSQL), System Design, and DevOps.
What you will be asked about
How to prepare
- Go through the topic list above and mark every one you cannot explain for five minutes unprepared. Those are your gaps.
- Pair every concept with a story from your own work — interviewers probe depth, and depth comes from having actually done it.
- Do the DSA rounds anyway. Almost every role in this list still screens with coding.
- Prepare two projects you can whiteboard end to end, including what you would change now.
Also do
Fullstack Developer interview questions460
JavaScript Fundamentals40
1. var: Function-scoped, can be re-declared and updated, and is hoisted with a value of `undefined`. 2. let: Block-scoped, can be updated but not re-declared in the same scope, and is hoisted to the 'Temporal Dead Zone'. 3. const: Block-scoped like let, but cannot be updated or re-declared; it must be initialized at the time of declaration.
Hoisting is JavaScript's default behavior of moving declarations to the top of the current scope. Variables declared with `var` are hoisted and initialized as `undefined`. Functions declarations are fully hoisted. `let` and `const` are hoisted but not initialized. Example: ```javascript console.log(x); // undefined var x = 5; foo(); // 'Hello' function foo() { console.log('Hello'); } ```
1. `==` (Abstract Equality): Performs type coercion before comparing. For example, `'5' == 5` is true. 2. `===` (Strict Equality): Compares both value and type without coercion. For example, `'5' === 5` is false.
A closure is a function that remembers its outer lexical environment even after the outer function has finished executing. They are useful for data privacy (emulating private methods), partial application of functions, and maintaining state in asynchronous callbacks.
The value of `this` depends on how a function is called: 1. Global context: Window (or global). 2. Object method: The object the method belongs to. 3. Constructor/Class: The new instance created. 4. Arrow functions: Lexical `this` (inherits from the parent scope). 5. Explicit binding: `call`, `apply`, or `bind` define `this` manually.
1. `undefined`: Means a variable has been declared but has not yet been assigned a value. 2. `null`: An intentional assignment of 'no value'. `typeof undefined` is 'undefined', whereas `typeof null` is 'object' (a legacy bug in JS).
Arrow functions provide a shorter syntax. Key differences: 1. They do not have their own `this` (they use lexical this). 2. They do not have the `arguments` object. 3. They cannot be used as constructors (cannot use `new`). 4. They do not have a `prototype` property.
1. Declaration: `function foo() {}`. These are hoisted, meaning they can be called before they are defined. 2. Expression: `const foo = function() {}`. These are not hoisted as functions (they follow variable hoisting rules) and cannot be called before the line they are defined on.
These methods are used to set the `this` context: 1. `call()`: Invokes the function immediately with arguments passed individually. 2. `apply()`: Invokes the function immediately with arguments passed as an array. 3. `bind()`: Returns a new function with the `this` context set, to be called later.
The event loop is a mechanism that allows JavaScript to perform non-blocking I/O operations despite being single-threaded. It constantly checks the Call Stack; if it's empty, it takes the first task from the Callback Queue (or Microtask Queue) and pushes it to the stack for execution.
A Promise is an object representing the eventual completion (or failure) of an asynchronous operation and its resulting value. It can be in one of three states: Pending, Fulfilled, or Rejected.
1. `Promise.all()`: Waits for all promises to resolve and returns an array of results. If any promise fails, the whole thing rejects. 2. `Promise.race()`: Returns the result of the first promise that settles (either resolves or rejects).
Async/await is syntactic sugar over Promises. `async` makes a function return a promise, and `await` pauses the execution of the async function until the promise resolves, making asynchronous code look and behave more like synchronous code.
Callback hell refers to deeply nested callbacks that make code hard to read and maintain. It can be avoided by: 1. Using Promises. 2. Using Async/Await. 3. Modularizing code into smaller, named functions.
A higher-order function is a function that either takes one or more functions as arguments or returns a function as its result. Examples include `map`, `filter`, and `reduce`.
1. `map`: Creates a new array by applying a function to every element. 2. `filter`: Creates a new array with elements that pass a test. 3. `reduce`: Executes a reducer function on each element, resulting in a single output value. Example: ```javascript const nums = [1, 2, 3, 4]; const squared = nums.map(n => n * n); // [1, 4, 9, 16] const evens = nums.filter(n => n % 2 === 0); // [2, 4] const sum = nums.reduce((acc, curr) => acc + curr, 0); // 10 ```
1. `slice()`: Returns a shallow copy of a portion of an array. It does not modify the original array. 2. `splice()`: Changes the contents of an array by removing or replacing existing elements and/or adding new elements. It does modify the original array.
Destructuring is a syntax that allows you to unpack values from arrays or properties from objects into distinct variables. For example: `const { name, age } = user;` or `const [first, second] = list;`.
Template literals use backticks (`` ` ``) instead of quotes. They allow for multi-line strings, string interpolation using `${expression}`, and tagged templates.
Both use the `...` syntax. 1. Spread: Expands an array or object into elements (e.g., `[...arr1, ...arr2]`). 2. Rest: Collects multiple elements into an array (e.g., `function sum(...nums) {}`).
1. Shallow Copy: Copies only the top-level properties. Nested objects still reference the same memory address as the original. 2. Deep Copy: Recursively copies all levels, ensuring nested objects are entirely new instances with no shared references.
1. Shallow: `const clone = { ...original };` or `Object.assign({}, original);`. 2. Deep: `JSON.parse(JSON.stringify(original))` (has limitations) or use `structuredClone(original)` (modern standard).
Prototypal inheritance is a feature where objects inherit properties and methods from other objects. Every object has an internal link to another object called its prototype. When a property is accessed that isn't on the object itself, JS looks at the prototype.
The prototype chain is a series of links between objects. When you search for a property, JS goes up the chain (`obj` -> `obj.__proto__` -> `obj.__proto__.__proto__`) until it either finds the property or reaches `null` (the end of the chain).
Introduced in ES6, classes are syntactic sugar over prototypal inheritance. They provide a cleaner way to create objects and handle inheritance using keywords like `class`, `constructor`, `static`, and `extends`.
1. Classical: Classes inherit from other classes (blueprint to blueprint). Used in Java/C++. 2. Prototypal: Objects inherit directly from other objects. It is more flexible as objects can be modified at runtime.
Modules allow you to break code into separate files. You use `export` to make variables/functions available and `import` to use them in another file. This helps with maintainability and namespace management.
1. CommonJS: Uses `require()` and `module.exports`. Synchronous, used in Node.js. 2. ES6 Modules: Uses `import` and `export`. Asynchronous, static (analyzable at compile time), and standard in modern browsers.
1. Bubbling: The event starts from the target element and propagates up to the ancestors. 2. Capturing: The event starts from the top window and goes down to the target element.
You use the `event.stopPropagation()` method. This prevents the event from moving further up (bubbling) or down (capturing) the DOM tree.
Event delegation is a technique where you attach a single event listener to a parent element instead of multiple listeners to child elements. It leverages event bubbling to handle events on children, improving performance and memory usage.
Web Workers allow you to run JavaScript in the background on a separate thread from the main UI thread. This is useful for heavy computations that would otherwise freeze the browser interface.
1. localStorage: Persists data even after the browser is closed and reopened. 2. sessionStorage: Clears data when the page session ends (tab is closed). Both have a limit of roughly 5MB.
Cookies are small strings of data sent to the server with every HTTP request. Unlike Storage APIs, they have a tiny size limit (4KB), can have expiration dates, and are primarily used for session management and tracking.
CORS is a security mechanism that allows or restricts requested resources on a web page to be requested from another domain outside the domain from which the first resource was served. It uses HTTP headers like `Access-Control-Allow-Origin`.
Errors are handled using `try...catch` blocks for synchronous code and `.catch()` or `try...catch` with `async/await` for asynchronous code. You can also throw errors manually using the `throw` keyword.
1. `try`: Code that might fail. 2. `catch`: Code to handle the error if it occurs. 3. `finally`: Code that runs regardless of whether an error was thrown or caught (useful for cleanup).
Custom errors are classes that extend the built-in `Error` class. They allow you to add specific properties (like error codes) and perform specific error handling for different application-level failures.
Strict mode (`'use strict';`) is a way to opt in to a restricted variant of JS. it catches common coding bloopers, prevents the use of undeclared variables, and disables features that are confusing or poorly thought out.
Generators are functions that can be exited and later re-entered. They use the `function*` syntax and the `yield` keyword. They return an iterator object that can be used to control the execution of the function one step at a time.
Advanced JavaScript20
Both are techniques to limit the rate at which a function is executed. 1. Debouncing: Ensures a function is called only after a certain period of inactivity (e.g., search bar input). 2. Throttling: Ensures a function is called at most once every X milliseconds (e.g., window resize or scroll).
By using a timer. Each time the function is triggered, the previous timer is cleared and a new one starts. If the timer finishes, the function executes.
Memoization is an optimization technique that speeds up programs by storing the results of expensive function calls and returning the cached result when the same inputs occur again. It's usually implemented using an object or a Map as a cache.
1. WeakMap: A collection of key/value pairs where keys must be objects and are held weakly (they can be garbage collected if no other references exist). 2. WeakSet: A collection of unique objects held weakly.
1. Keys: Map keys can be any type; Object keys must be Strings or Symbols. 2. Order: Map maintains insertion order; Object does not guarantee it. 3. Size: Map has a `.size` property; Object size must be calculated manually.
Symbols are a primitive data type that provides unique, anonymous identifiers. They are often used as private keys for object properties to avoid name collisions.
An Iterable is an object that has a `Symbol.iterator` method. An Iterator is an object with a `next()` method that returns an object with `value` and `done` properties.
1. `for...of`: Iterates over values of an iterable (Array, Map, Set). 2. `for...in`: Iterates over enumerable properties (keys) of an object.
Currying is a transformation of functions that translates a function from callable as `f(a, b, c)` into callable as `f(a)(b)(c)`. It is useful for creating specialized versions of generic functions.
Function composition is a mechanism of combining multiple functions to build a more complex one. The output of one function becomes the input of the next: `f(g(x))`.
A pure function: 1. Always returns the same output for the same input. 2. Has no side effects (doesn't change external state, doesn't log to console, etc.).
Immutability means an object's state cannot be changed after it is created. It is important because it makes state management predictable, simplifies debugging, and allows frameworks like React to optimize rendering via reference checks.
1. Synchronous: Executes line by line; each line must wait for the previous one to finish. 2. Asynchronous: Allows multiple operations to run concurrently without blocking the execution flow.
1. Microtasks: (Promises, process.nextTick) have higher priority. They are executed immediately after the current task and before the next macrotask. 2. Macrotasks: (setTimeout, setInterval, I/O) are handled in the next loop iteration.
The runtime environment provides the engine (like V8) and the Web APIs (like DOM, timers, fetch) needed for JS to execute. It also includes the Event Loop and Task Queues.
Garbage collection is an automatic memory management process that clears memory occupied by objects that are no longer reachable or used by the program. JS primarily uses the 'Mark-and-Sweep' algorithm.
Memory leaks happen when objects are unintentionally kept in memory. Causes: 1. Accidental global variables. 2. Forgotten timers or callbacks. 3. Closures holding large objects. 4. Out-of-DOM references.
1. Shallow: Checks if references are the same or if top-level values match. 2. Deep: Recursively checks if all nested properties and values are identical.
By creating a class that takes an executor function. The executor receives `resolve` and `reject` functions. You maintain an internal state (pending/fulfilled/rejected) and a queue of callbacks to execute when the state changes.
A Proxy object allows you to create a wrapper for another object, which can intercept and redefine fundamental operations for that object, such as getting, setting, and defining properties.
TypeScript20
TypeScript is a strongly typed superset of JavaScript that compiles to plain JS. You should use it because it provides static typing, which catches errors at compile-time, improves code maintainability, and enhances developer productivity with better tooling/IDE support.
1. Type safety. 2. Improved IDE features (intellisense). 3. Better readability and documentation via types. 4. Easier refactoring of large codebases. 5. Support for modern JS features with backward compatibility.
Types are a way to describe the shape and structure of data. Basic types include `string`, `number`, `boolean`, `array`, `tuple`, `enum`, `any`, `void`, `null`, and `undefined`.
1. Interface: Can be merged (declaration merging) and are better for defining object shapes. 2. Type: More flexible; can define unions, intersections, and primitives. Generally, use interfaces until you need features specific to types.
1. Union (`|`): A value can be one of several types (e.g., `string | number`). 2. Intersection (`&`): Combines multiple types into one, requiring all properties from all types.
Generics allow you to create reusable components that work with a variety of types rather than a single one. For example: `function identity<T>(arg: T): T { return arg; }`.
Type inference is when TypeScript automatically determines the type of a variable based on its value without an explicit type annotation.
Type guards are expressions that perform a runtime check to narrow down a type within a specific scope. Examples include `typeof`, `instanceof`, and custom type predicates (`is`).
'any' disables all type checking for a variable. You should avoid it because it defeats the purpose of using TypeScript, making the code prone to runtime errors and losing IDE benefits.
Both can hold any value. However, `any` allows you to do anything with the value, while `unknown` is type-safe; you must perform some type checking/narrowing before you can operate on an `unknown` value.
Enums allow a developer to define a set of named constants. They make it easier to document intent or create a set of distinct cases. They can be numeric or string-based.
A tuple is an array with a fixed number of elements where each element has a known type. Example: `let person: [string, number] = ['Alice', 30];`.
`never` represents the type of values that never occur. It is used for functions that always throw an exception or those that have infinite loops, as well as in exhaustive type checking.
Optional properties are denoted by a `?` after the property name. They indicate that the property may or may not be present in the object.
`readonly` makes a property immutable after its initial assignment. It can only be set in the constructor or at the time of declaration.
1. `public`: Accessible from anywhere. 2. `private`: Accessible only within the class. 3. `protected`: Accessible within the class and its subclasses.
Abstract classes are base classes from which other classes may be derived. They cannot be instantiated directly and often contain abstract methods that must be implemented by subclasses.
Type assertion is a way to tell the compiler 'trust me, I know what I'm doing'. It is similar to type casting in other languages but performs no special check or restructuring of data. Example: `(someValue as string)`.
Utility types are built-in transformations. 1. `Partial<T>`: Makes all properties of T optional. 2. `Pick<T, K>`: Creates a type by picking keys K from T. 3. `Omit<T, K>`: Creates a type by removing keys K from T.
By enabling `strictNullChecks` in the config. This forces you to handle these cases explicitly using union types (e.g., `string | null`) and optional chaining (`?.`) or nullish coalescing (`??`).
React.js40
React is an open-source JavaScript library for building user interfaces, specifically single-page applications. It is popular because of its component-based architecture, Virtual DOM for performance, strong community, and one-way data flow.
Components are the building blocks of a React application. They are independent, reusable pieces of UI that can be composed together. They can be functional (functions) or class-based.
1. Functional: Plain JS functions, simpler, uses Hooks for state/lifecycle. 2. Class: ES6 classes, more boilerplate, uses `this.state` and lifecycle methods (deprecated in favor of functional).
Hooks are functions that let functional components 'hook into' React state and lifecycle features. Examples: `useState`, `useEffect`, `useContext`.
`useState` adds local state to a function. It returns an array with two elements: the current state value and a function to update it. Example: `const [count, setCount] = useState(0);`.
`useEffect` performs side effects (fetching data, subscriptions). It is called after every render by default, but its execution depends on its dependency array.
The second argument to `useEffect`. 1. Empty `[]`: Runs only on mount. 2. With values `[a, b]`: Runs on mount and whenever `a` or `b` changes. 3. Missing: Runs after every render.
1. `useEffect`: Runs asynchronously after the browser paints. 2. `useLayoutEffect`: Runs synchronously before the browser paints (used for measuring layout).
`useContext` provides a way to consume data from a React Context without wrapping a component in a Consumer. It simplifies accessing global state or themes.
`useReducer` is an alternative to `useState` for complex state logic involving multiple sub-values or when the next state depends on the previous one. It uses a reducer function (like Redux).
`useState` is better for simple values or independent state pieces. `useReducer` is better for complex state objects and state transitions that logic-heavy.
`useMemo` memoizes the result of a calculation. Use it to avoid expensive re-computations on every render when dependencies haven't changed.
`useCallback` memoizes the function instance itself. It's useful when passing callbacks to optimized child components to prevent unnecessary re-renders.
1. Accessing DOM elements directly. 2. Storing mutable values that persist across renders without triggering a re-render when they change.
Custom hooks are JS functions that start with 'use' and can call other hooks. They allow you to extract and reuse component logic across different components.
The Virtual DOM is a lightweight, in-memory representation of the real DOM. React uses it to calculate the minimal number of changes needed to update the UI (Diffing) and then applies those changes to the real DOM (Reconciliation).
Reconciliation is the algorithm React uses to diff the virtual DOM trees. It identifies which parts of the UI have changed and updates only those specific nodes in the real DOM to maximize performance.
JSX stands for JavaScript XML. It is a syntax extension that looks like HTML but is compiled into regular JS function calls (`React.createElement`).
Props (short for properties) are inputs to a component. They are read-only and allow data to be passed from parent to child components.
Prop drilling is the process of passing data through multiple levels of components that don't need it, just to reach a deep child. Avoid it using Context API or state management libraries like Redux.
A built-in feature to share data that can be considered 'global' (like themes or user auth) across the entire component tree without manual prop drilling.
Redux is a predictable state container for JS apps. It's used for managing global state in large applications, providing a single source of truth and making state changes predictable via actions and reducers.
1. Store: Holds the state. 2. Actions: Payloads of information that send data from the app to the store. 3. Reducers: Functions that specify how the state changes in response to an action.
Context is built-in and better for low-frequency updates. Redux is a library with more robust tools (middleware, devtools) and is better for high-frequency, complex state updates in large teams.
Redux Toolkit (RTK) is the official, recommended way to write Redux logic. It simplifies store setup, reduces boilerplate, and includes useful features like `createSlice` and `createAsyncThunk`.
Middleware allows you to intercept actions before they reach the reducer. Thunks and Sagas are used to handle side effects like asynchronous API calls.
1. Thunk: Uses functions (easy to learn). 2. Saga: Uses Generator functions (better for complex async flows and testing).
The lifecycle is the series of phases a component goes through: Mounting (added to DOM), Updating (props/state change), and Unmounting (removed from DOM).
Methods like `componentDidMount`, `componentDidUpdate`, and `componentWillUnmount` that allow execution of code at specific points in the component's life.
Forms are handled by making the input values part of the component's state, updating that state on change, and preventing default behavior on submit.
1. Controlled: React state handles the input data. 2. Uncontrolled: The DOM (via `useRef`) handles the input data.
A library for routing in React. It enables navigation without a full page reload by matching the URL to specific components using `<Route>` and `<Link>`.
`Link` is for basic navigation. `NavLink` is a special version that adds an 'active' class to the element when the route matches the current URL.
By creating a wrapper component that checks the authentication status. If the user is logged in, it renders the child component; otherwise, it redirects to a login page.
A technique to defer loading components until they are actually needed, reducing the initial bundle size. It is implemented using `React.lazy()` and `Suspense`.
The practice of splitting the app bundle into smaller chunks that can be loaded on demand. Tools like Webpack or Vite handle this, often triggered by `React.lazy()`.
A higher-order component that memoizes a component. Use it for pure functional components that render the same output given the same props to avoid unnecessary re-renders.
A class component that implements a shallow comparison of props and state in `shouldComponentUpdate` to prevent unnecessary re-renders.
A syntax (`<React.Fragment>` or `<>`) that allows you to group multiple elements without adding an extra node to the DOM.
Keys help React identify which items have changed, been added, or removed. They provide a stable identity to elements in a list, which is essential for efficient DOM updates and state preservation.
React Advanced20
SSR is the process of rendering the React components into HTML on the server and sending that fully formed HTML to the browser. This improves SEO and initial load speed.
Next.js is a React framework that provides built-in SSR, Static Site Generation, routing, and optimization. Benefits include better SEO, automatic code splitting, and improved performance.
1. SSG: HTML is generated at build time and reused for every request. 2. SSR: HTML is generated on the server for each request.
A Next.js feature that allows you to update static pages after you've built the site, without needing to rebuild the entire site. It re-generates pages in the background as requests come in.
Portals provide a way to render children into a DOM node that exists outside the hierarchy of the parent component (e.g., modals, tooltips).
Class components that catch JS errors anywhere in their child component tree, log those errors, and display a fallback UI instead of crashing the whole app.
A component that lets you 'wait' for some code to load and declaratively specify a loading state (like a spinner) while waiting.
A set of new features that help React apps stay responsive and gracefully adjust to the user’s device capabilities and network speed by allowing React to interrupt a long-rendering task.
An HOC is a function that takes a component and returns a new component, typically adding new functionality or data.
A pattern where a component’s prop is a function that returns a React element, allowing for sharing code between components.
A pattern where components work together to form a unit (e.g., `<Select>` and `<Option>`) where the parent manages the state and shares it implicitly with children.
A library for testing React components that focuses on testing user behavior rather than implementation details.
By simulating user interactions (clicks, typing) and asserting that the UI responds as expected using tools like Jest and React Testing Library.
A testing technique that captures the rendered output of a component and compares it to a previously saved 'snapshot' to detect unintended UI changes.
1. Shallow: Renders only the component itself, not its children. 2. Mount: Full DOM rendering including children.
1. `useMemo` and `useCallback`. 2. `React.memo()`. 3. Code splitting/Lazy loading. 4. Windowing/Virtualization for long lists. 5. Avoiding anonymous functions in props.
1. State changes. 2. Prop changes. 3. Parent component re-rendering. 4. Context value changes.
By using `React.memo`, `useMemo`, `useCallback`, and ensuring that props and state are updated only when necessary.
A built-in tool that measures how often a React application renders and what the 'cost' of rendering is, helping identify performance bottlenecks.
`componentWillUnmount` runs once before the component is destroyed. `useEffect` cleanup runs before every new effect execution AND when the component unmounts.
Node.js & Express40
Node.js is a JavaScript runtime built on Chrome's V8 engine. It's used for backend because it's fast, scalable, and allows developers to use JS for both frontend and backend (full-stack consistency).
It's a design pattern where the flow of the program is determined by events (e.g., a file being read, an HTTP request). Node uses an `EventEmitter` to trigger and listen for these events.
It means Node doesn't wait for I/O operations (like database queries) to complete. It initiates the request, moves to the next task, and uses a callback/promise to handle the result later.
Browser JS interacts with the DOM and window. Node JS has access to the file system, network, and OS-level APIs, but no DOM.
The mechanism that allows Node.js to perform non-blocking I/O. It offloads operations to the system kernel whenever possible.
Streams are collections of data that might not be available all at once and don't have to fit in memory (e.g., reading a massive file). They process data piece by piece.
1. Readable: From which data can be read (e.g., `fs.createReadStream`). 2. Writable: To which data can be written (e.g., `fs.createWriteStream`).
A Buffer is a raw memory allocation outside the V8 heap. It's used to handle binary data (like images or TCP streams) that JS can't handle natively.
`process.nextTick()` fires immediately after the current operation, before the event loop continues. `setImmediate()` fires in the 'Check' phase of the next event loop iteration.
Clustering allows you to create multiple child processes (workers) that share the same server port. This helps Node.js utilize multi-core CPUs, as a single Node process runs on a single core.
A module used to spawn new processes in the OS. Common methods include `exec`, `spawn`, and `fork`.
A minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications.
Middleware are functions that have access to the request (`req`), response (`res`), and the next function in the application’s request-response cycle.
1. Application-level. 2. Router-level. 3. Error-handling. 4. Built-in (e.g., `express.json`). 5. Third-party (e.g., `cors`, `helmet`).
`app.use()` applies middleware to all HTTP methods. `app.get()` only handles GET requests.
By using error-handling middleware, which is defined with four arguments instead of three: `(err, req, res, next)`.
Middleware that parses the incoming request bodies (like JSON or URL-encoded) before your handlers. It is now built into Express via `express.json()`.
Middleware used to enable Cross-Origin Resource Sharing. It's needed to allow frontend apps hosted on different domains to access the API.
A package that helps secure Express apps by setting various HTTP headers to protect against common attacks like XSS and clickjacking.
Using the built-in `express.static` middleware. Example: `app.use(express.static('public'))`.
Routing refers to how an application’s endpoints (URIs) respond to client requests (GET, POST, etc.).
1. Route params: URL segments used to capture values (e.g., `/user/:id`). 2. Query params: Key-value pairs after the `?` in the URL (e.g., `/search?q=apple`).
Typically using third-party middleware like `Multer`, which handles `multipart/form-data`.
A Node.js middleware for handling `multipart/form-data`, primarily used for uploading files.
By using sessions (cookies) or tokens (JWT). Middleware is used to check for a valid session/token before allowing access to a route.
A compact, URL-safe means of representing claims to be transferred between two parties. It consists of a header, payload, and signature.
1. Session: Stateful (stored on server). 2. Token: Stateless (stored on client, usually in localStorage or cookies).
A short-lived access token is used for requests, while a long-lived refresh token is used to get a new access token once it expires.
A library for hashing passwords. It uses a salt and a cost factor to make it resistant to brute-force attacks.
Using `bcrypt.hash()` with a 'salt' to create a secure, non-reversible string.
A built-in module that provides cryptographic functionality, including set of wrappers for OpenSSL's hash, HMAC, cipher, and decipher methods.
The practice of storing sensitive config (API keys, DB URLs) outside of source code to improve security and environment flexibility.
A zero-dependency module that loads environment variables from a `.env` file into `process.env`.
Using Callbacks, Promises, or Async/Await (modern preferred approach).
Callbacks are the legacy way; they can lead to callback hell. Promises provide a cleaner, chainable syntax.
Syntactic sugar that allows you to write asynchronous code as if it were synchronous, using `try/catch` for error handling.
By promisifying functions or using the modern async/await pattern.
Package managers for Node.js used to install, share, and manage project dependencies.
Both are similar today. Historically, Yarn was faster and more secure; NPM has since caught up in performance and features.
1. `package.json`: Contains project metadata and dependency versions. 2. `package-lock.json`: Locks the exact version of every nested dependency installed.
Databases - SQL40
A database based on the relational model, which organizes data into tables (relations) with rows and columns. Tables are linked by keys.
1. DDL: Define structure (`CREATE`). 2. DML: Manipulate data (`INSERT`, `UPDATE`). 3. DCL: Permissions (`GRANT`). 4. TCL: Transactions (`COMMIT`).
1. SQL: Structured, relational, predefined schema (MySQL, Postgres). 2. NoSQL: Unstructured/document-based, dynamic schema (MongoDB).
1. Primary: Unique identifier for a row. 2. Foreign: A link between tables that references the primary key of another table.
The process of organizing data to reduce redundancy and improve data integrity by splitting large tables into smaller ones.
Specific rules for normalization. 1NF removes duplicates; 2NF ensures functional dependence; 3NF removes transitive dependence.
The process of adding redundant data to speed up complex queries. Use it in read-heavy systems where join performance is a bottleneck.
A data structure that improves the speed of data retrieval operations at the cost of slower writes and additional storage.
B-Tree, Hash, GIST, GIN, Clustered, Non-clustered.
1. Clustered: Determines the physical order of data in the table (one per table). 2. Non-clustered: A separate structure pointing to the data.
Rules applied to columns to ensure data validity. `UNIQUE` prevents duplicates; `CHECK` enforces specific value ranges.
1. `DELETE`: Removes specific rows (can roll back). 2. `TRUNCATE`: Removes all rows (fast, cannot roll back). 3. `DROP`: Removes the entire table structure.
Used to combine rows from multiple tables. Types: Inner, Left, Right, Full, Cross.
1. Inner: Returns matches only. 2. Outer: Returns matches plus non-matches from one or both sides.
1. Left: All rows from left table + matches. 2. Right: All rows from right table + matches.
Produces a Cartesian product; every row of the first table joined with every row of the second.
A regular join where a table is joined with itself (e.g., matching employees to managers in the same table).
A query nested inside another query (e.g., inside `SELECT`, `FROM`, or `WHERE`).
`WHERE` filters rows before grouping; `HAVING` filters groups after `GROUP BY` has been applied.
Functions that perform a calculation on a set of values and return a single value.
The `GROUP BY` clause groups rows that have the same values into summary rows, like 'find the number of customers in each country'. It is almost always used with aggregate functions.
The `ORDER BY` keyword is used to sort the result-set in ascending (`ASC`) or descending (`DESC`) order. By default, it sorts in ascending order.
Window functions perform a calculation across a set of table rows that are related to the current row. Unlike aggregate functions, they do not cause rows to become grouped into a single output row (e.g., `ROW_NUMBER()`, `RANK()`, `SUM() OVER()`).
1. `UNION`: Combines result sets of two queries and removes duplicate rows. 2. `UNION ALL`: Combines result sets but keeps all duplicates, making it faster since it doesn't need to perform a distinct check.
A view is a virtual table based on the result-set of an SQL statement. It contains rows and columns just like a real table, but it doesn't store data physically; it fetches data dynamically.
A stored procedure is a prepared SQL code that you can save and reuse. It can accept parameters, perform complex logic, and be called by applications to reduce network traffic and improve security.
1. Procedure: Can perform DML operations, does not have to return a value, and can have output parameters. 2. Function: Must return a single value, cannot perform DML (read-only usually), and can be used within a `SELECT` statement.
A trigger is a special type of stored procedure that automatically runs when an event occurs in the database server, such as `INSERT`, `UPDATE`, or `DELETE` on a table.
A transaction is a single logical unit of work that contains one or more SQL statements. It follows the 'all or nothing' principle—either all changes are saved or none are.
1. Atomicity: All or nothing. 2. Consistency: Database follows rules before and after. 3. Isolation: Transactions don't interfere. 4. Durability: Once saved, it stays saved.
1. `COMMIT`: Saves all changes made during the transaction permanently. 2. `ROLLBACK`: Undoes all changes if an error occurs, returning the database to its previous state.
Locking is a mechanism used to prevent multiple users from modifying the same data simultaneously, ensuring data integrity. Types include Shared (Read) locks and Exclusive (Write) locks.
A deadlock occurs when two transactions wait for each other to release locks. Prevention: 1. Access tables in the same order. 2. Keep transactions short. 3. Use appropriate isolation levels.
Connection pooling is a cache of database connections maintained so that connections can be reused when future requests to the database are required, significantly improving performance.
PostgreSQL is an object-relational database known for advanced features, complex queries, and extensibility. MySQL is traditionally faster for simple read-heavy apps, while Postgres is better for complex data and strict compliance.
1. Better support for complex data types (JSONB, Arrays). 2. Better concurrency handling (MVCC). 3. Supports full outer joins and common table expressions (CTEs) more robustly.
1. `VARCHAR(n)`: Stores variable-length strings with a limit. 2. `TEXT`: Stores unlimited-length strings. In modern DBs like Postgres, there is no performance difference between them.
The `EXPLAIN` keyword is used to show the execution plan of a query. It tells you if the DB is using an index scan or a slow sequential (table) scan, helping you optimize the query.
1. Add indexes on columns in `WHERE` and `JOIN` clauses. 2. Avoid `SELECT *`. 3. Use `EXPLAIN` to find bottlenecks. 4. Denormalize read-heavy tables. 5. Optimize joins.
Replication is the practice of copying data from one database server (Master) to another (Slave). It provides redundancy, high availability, and allows read-heavy traffic to be offloaded from the primary server.
Databases - NoSQL & MongoDB30
MongoDB is a NoSQL, document-oriented database. It is used for its flexibility (schema-less), horizontal scalability (sharding), and high performance with hierarchical data structures (JSON/BSON).
A document is a set of key-value pairs stored in BSON (Binary JSON) format. It is the basic unit of data in MongoDB, analogous to a 'row' in SQL but much more flexible.
A collection is a group of MongoDB documents. It is the equivalent of a 'table' in relational databases, but it does not enforce a strict schema.
SQL uses structured query language (SELECT * FROM...). MongoDB uses a JavaScript-based query API (db.collection.find({})). MongoDB queries are more natural for developers working with JSON objects.
The `_id` field is a unique identifier required for every document. If not provided by the user, MongoDB automatically generates a 12-byte `ObjectId` to ensure uniqueness.
Operators are used to refine queries. 1. `$gt`: Greater than. 2. `$lt`: Less than. 3. `$in`: Matches any value in an array. 4. `$set`: Updates specific fields.
A framework for data processing and transformation. Documents enter a multi-stage pipeline that transforms them into an aggregated result (like SUM or AVG but much more powerful).
Common stages include `$match` (filtering), `$group` (summarizing), `$sort` (ordering), `$project` (selecting fields), and `$lookup` (joining collections).
Indexing makes queries faster by creating an ordered path to data. Without an index, MongoDB must perform a 'collection scan' (scanning every document), which is very slow for large datasets.
1. Single Field: Index on one key. 2. Compound: Multiple keys. 3. Multikey: Indexing arrays. 4. Text: For string searches. 5. TTL: Automatically deletes data after a set time.
Sharding is the process of storing data records across multiple machines (Horizontal Scaling). It allows MongoDB to support very large datasets and high-throughput operations by distributing the load.
Replication provides redundancy and high availability. It involves maintaining multiple copies of data on different servers (a Replica Set), so if the primary fails, a secondary is elected as primary.
A group of MongoDB processes that maintain the same data set. It consists of one Primary (handles writes) and multiple Secondaries (replicate the data).
1. Embedding: Storing related data in a single document (faster reads). 2. Referencing: Storing a reference (ID) to another document (better for frequently changing or large data).
Embed when data belongs to the parent and is usually read together ('One-to-Few'). Reference when data is large, shared across many parents, or used independently ('One-to-Many' or 'Many-to-Many').
Mongoose is an Object Data Modeling (ODM) library for MongoDB and Node.js. It provides a straight-forward, schema-based solution to model application data, including validation, types, and hooks.
1. Schema: Defines the structure of the document (fields, types, defaults). 2. Model: A constructor compiled from the schema that allows you to create and query documents.
Middleware functions that are passed control during execution of asynchronous functions. `pre` hooks run before an event (like `save`), and `post` hooks run after (like logging).
Population is the process of automatically replacing the specified paths in the document with document(s) from other collection(s). Similar to a 'JOIN' but performed at the application level.
Virtuals are document properties that you can get and set but that do not get persisted to MongoDB. They are useful for computed properties like a `fullName` derived from `firstName` and `lastName`.
Validation is defined in the Schema. You can use built-in validators (`required`, `min`, `max`, `enum`) or custom validators by providing a function that returns true or false.
1. `find()`: Returns an array of all documents that match the criteria. 2. `findOne()`: Returns only the first document that matches the criteria (as an object).
1. `updateOne()`: Simply updates the document in the DB. 2. `findOneAndUpdate()`: Updates the document and returns the original (or the updated) document to the application logic.
Multi-document transactions allow you to perform multiple operations across different documents and collections in an ACID-compliant way (introduced in MongoDB 4.0).
Redis is an in-memory key-value data store. Use it for high-speed caching, session management, real-time analytics, and as a message broker where sub-millisecond latency is required.
Redis is in-memory (volatile, extremely fast) and primarily key-value. MongoDB is disk-based (persistent, handles complex data) and document-oriented. Redis is usually used *alongside* MongoDB for caching.
Strings, Lists, Sets, Sorted Sets, Hashes, Bitmaps, and HyperLogLogs.
Caching stores frequently accessed data in a fast access layer. Redis helps by holding this data in RAM, avoiding expensive database queries and drastically reducing response times.
Apache Cassandra is a distributed NoSQL database designed to handle massive amounts of data across many servers, providing high availability with no single point of failure (Column-family store).
Amazon DynamoDB is a fully managed, serverless, key-value and document NoSQL database that delivers single-digit millisecond performance at any scale.
Authentication & Security10
A salt is a random string added to a password before hashing. It ensures that two users with the same password have different hashes and protects against Rainbow Table attacks (precomputed tables of hashes).
HTTPS is HTTP over SSL/TLS. It uses public-key cryptography to encrypt the communication between the client and server, ensuring privacy, data integrity, and authentication.
SSL (Secure Sockets Layer) and its successor TLS (Transport Layer Security) are cryptographic protocols designed to provide communications security over a computer network.
Digital certificates that authenticate a website's identity and enable an encrypted connection. They are issued by a trusted Certificate Authority (CA).
An HTTP header that allows site operators to restrict the resources (such as JavaScript, CSS, Images) that a browser is allowed to load for a given page, effectively preventing most XSS attacks.
A middleware for Express that sets various security-related HTTP headers (like X-Frame-Options, X-Content-Type-Options) to make the app more secure by default.
Headers like `Strict-Transport-Security`, `Content-Security-Policy`, and `X-Frame-Options` that instruct the browser to implement security measures.
A fundamental security model in web browsers that prevents a script loaded from one origin from getting or manipulating data from another origin.
1. Encrypt data at rest (AES-256). 2. Use a Key Management Service (KMS). 3. Never store passwords in plain text (use bcrypt). 4. Use environment variables for secrets.
The practice of keeping sensitive configurations out of the source code (using `.env` files and adding them to `.gitignore`) to prevent accidental leaks in version control.
Deployment & DevOps30
A set of practices that automate the building, testing, and deployment of code. CI focuses on integrating code frequently; CD focuses on delivering it to production automatically.
Git is a distributed version control system. It's important because it tracks changes, allows collaboration among developers, and enables easy rollbacks to previous versions.
Git is the local tool (software) used for version control. GitHub is a cloud-based hosting service for Git repositories.
A branch is a separate line of development. It allows you to work on new features or bug fixes without affecting the main codebase (`main` or `master` branch).
1. Merge: Combines branches by creating a 'merge commit'. 2. Rebase: Moves the entire feature branch to the tip of the main branch, creating a linear history without extra merge commits.
A mechanism for a developer to notify team members that they have completed a feature. It allows for code review and discussion before the code is merged into the main branch.
A popular branching model that defines a strict branching structure around project releases, using branches like `feature`, `develop`, `release`, and `hotfix`.
Docker is a platform for containerization. It is used to package an application and its dependencies into a single 'container' that runs consistently on any environment.
A standard unit of software that packages up code and all its dependencies so the application runs quickly and reliably from one computing environment to another.
1. Image: A read-only template containing the application code and dependencies (the blueprint). 2. Container: A running instance of an image.
A text document that contains all the commands a user could call on the command line to assemble an image.
A tool for defining and running multi-container Docker applications using a YAML file to configure the application's services.
1. VM: Includes a full Guest OS; heavy and slow. 2. Docker: Shares the host OS kernel; lightweight and starts in seconds.
An open-source container orchestration platform that automates the deployment, scaling, and management of containerized applications.
The smallest deployable unit in Kubernetes, which can contain one or more containers that share storage and network resources.
The automated management of the lifecycle of containers, including deployment, networking, load balancing, and scaling.
Amazon Web Services is a cloud provider. Core services: EC2 (compute), S3 (storage), RDS (database), Lambda (serverless).
Elastic Compute Cloud: Provides scalable virtual servers (instances) in the cloud.
Simple Storage Service: Object storage built to store and retrieve any amount of data from anywhere.
A serverless computing service that lets you run code without provisioning or managing servers, triggered by events.
A way to build and run applications and services without having to manage infrastructure. The cloud provider handles the scaling and execution.
1. No server management. 2. Auto-scaling. 3. Pay-per-use pricing. 4. High availability.
An AWS service for deploying and scaling web applications and services developed with Java, .NET, PHP, Node.js, Python, Ruby, etc.
Relational Database Service: Makes it easy to set up, operate, and scale a relational database in the cloud.
1. RDS: Relational (SQL), predefined schema. 2. DynamoDB: Non-relational (NoSQL), key-value store, serverless.
A content delivery network service that speeds up distribution of your static and dynamic web content to users worldwide.
A high-performance web server and reverse proxy used for load balancing, caching, and serving static content.
1. Nginx: Event-driven, handles many concurrent connections efficiently. 2. Apache: Process-based, better for complex module-based setups.
A server that sits in front of backend servers and forwards client requests to them, providing security, anonymity, and load balancing.
The process of distributing incoming network traffic across multiple servers to ensure no single server bears too much load.
Testing20
Testing the smallest possible 'units' of an application (like single functions) in isolation.
Testing how different modules or services of an application work together as a group.
Testing the entire application flow from the user's perspective, including the UI, database, and network.
Unit testing tests a function in isolation (usually mocked). Integration testing tests the interaction between real components/services.
A development process where you write the test before the actual code (Red-Green-Refactor cycle).
A popular JavaScript testing framework designed to be fast and simple, often used with React.
By using a framework like Jest to define 'test' or 'it' blocks and 'expect' assertions to verify outputs.
1. Test Case: A single test scenario. 2. Test Suite: A collection of related test cases (usually grouped by `describe`).
The process of creating a fake version of a service or module to isolate the code being tested.
1. Stub: Fixed data return. 2. Spy: Tracks how many times a function was called. 3. Mock: A complex object that verifies specific behaviors/interactions.
Code coverage is a metric that measures the percentage of your source code executed during testing. It helps identify untested parts of the application, though 100% coverage doesn't necessarily mean the code is bug-free.
While it varies by project, 80% is generally considered a good benchmark. Aiming for 100% can lead to diminishing returns where developers test trivial code rather than critical business logic.
Mocha is a feature-rich JavaScript test framework running on Node.js and in the browser. Unlike Jest, it is unopinionated and requires an external assertion library like Chai.
Chai is a BDD/TDD assertion library for Node.js and the browser that can be paired with any JS testing framework. it provides styles like `expect`, `should`, and `assert`.
Supertest is a library for testing Node.js HTTP servers. It provides a high-level abstraction for testing API endpoints and asserting on status codes, headers, and body content.
In modern frameworks, you return a Promise from the test or use `async/await`. The test runner waits for the promise to resolve or reject before marking the test as finished.
Snapshot tests are used to ensure the UI does not change unexpectedly. A 'snapshot' of the rendered component is saved and compared against the output in future test runs.
Cypress is a next-generation front-end testing tool built for the modern web. It runs directly in the browser, allowing for fast, easy, and reliable testing of anything that runs in a browser.
Selenium is a legacy automated testing framework used to validate web applications across different browsers and platforms. It uses a WebDriver to interact with the browser.
Cypress is built specifically for modern JS frameworks, runs inside the browser, and is faster/more stable. Selenium is more flexible (supports many languages) but relies on out-of-process execution which can be slower.
Performance Optimization30
Lazy loading is a design pattern that delays the initialization of an object or resource until it is actually needed (e.g., loading images only when they scroll into the viewport).
The process of splitting code into various bundles or components which can then be loaded on demand or in parallel, reducing the initial load time of the application.
A form of dead-code elimination. It relies on the static structure of ES6 modules (`import`/`export`) to remove unused code from the final bundle during the build process.
Minification removes unnecessary characters (whitespace, comments). Uglification renames variables and functions to shorter names. Both reduce file size and make code harder to read.
Bundling is the process of combining multiple files (JS, CSS, Images) into a single or a few files to reduce the number of HTTP requests a browser has to make.
Webpack is a static module bundler for modern JavaScript applications. It builds a dependency graph of your project and packages it into one or more bundles.
Webpack bundles the entire project before serving. Vite uses native ES modules in the browser for instant hot module replacement (HMR) and pre-bundles dependencies with esbuild.
Rendering the initial state of a web page on the server and sending the full HTML to the client. This improves SEO and perceived load speed.
The browser downloads a minimal HTML file and a large JS bundle, which then renders the entire UI. This results in a slower initial load but faster subsequent interactions.
SSR provides better SEO and initial load. CSR provides a smoother 'App-like' feel after the first load. Hybrid frameworks like Next.js allow you to use both.
Hydration is the process where client-side JavaScript takes over the static HTML sent by the server, attaching event listeners and making the page interactive.
Preloading is for high-priority resources needed for the current page. Prefetching is for low-priority resources that might be needed for future navigations.
Caching stores copies of data in a high-speed layer. Types: Browser caching, CDN caching, Server-side caching (Redis), and Database caching.
The browser stores assets (images, JS) locally based on HTTP headers, so it doesn't have to re-download them on every visit.
1. `Cache-Control`: Defines how long and where a resource can be cached. 2. `ETag`: A unique identifier for a version of a resource used for validation.
A distributed network of servers that delivers content to users based on their geographic location, reducing latency.
Reducing image file size without losing quality. Techniques: Compression, using modern formats (WebP), and responsive images.
A modern image format that provides superior lossless and lossy compression for images on the web, often 25-35% smaller than JPEG.
Using the `srcset` attribute to provide the browser with multiple sizes of the same image, allowing it to pick the most appropriate one for the screen size.
The process of reducing the time it takes for a database to execute a query. common steps: Indexing, avoiding `SELECT *`, and using joins efficiently.
Occurs when an application makes one query to get a list of records and then 'N' additional queries to fetch related data for each record.
Using 'Eager Loading' (SQL `JOIN`s) to fetch the related data in a single query rather than multiple individual ones.
Pagination uses numbered pages; better for finding specific items. Infinite scroll loads data as you reach the bottom; better for discovery and social feeds.
Creating an index (like a book's index) allows the database to find data without scanning every single row, significantly speeding up reads.
Maintaining a pool of open database connections to be reused, avoiding the high cost of opening and closing a connection for every request.
Storing the result of an API call so that subsequent identical requests receive the cached result instantly without hitting the database.
Redis is an in-memory data store used as a high-performance cache. It reduces the load on the primary database by storing frequently accessed data in RAM.
Caching the results of expensive function calls in the browser (e.g., `useMemo` in React) so they are only re-calculated if dependencies change.
A way to run JavaScript on a separate background thread, preventing heavy computations from blocking the UI thread and causing lag.
Techniques to limit how often a function executes during events like scrolling or typing, reducing the strain on the browser's rendering engine.
WebSockets & Real-time10
A communication protocol that provides full-duplex communication channels over a single TCP connection, allowing real-time data transfer.
HTTP is uni-directional (request/response) and stateless. WebSockets are bi-directional and persistent (stateful) until closed.
A library that enables real-time, bi-directional communication. It uses WebSockets but provides fallbacks (like long polling) for older browsers/networks.
The client emits a 'message' event to the server, and the server broadcasts that event to all other connected clients or a specific room.
Namespaces split the main connection into channels. Rooms are sub-channels within namespaces that allow broadcasting to specific groups of users.
Polling involves the client repeatedly asking the server for updates. WebSockets involve the server pushing updates to the client as they happen.
A technique where the server holds the client's request open until new data is available or a timeout occurs, simulating real-time behavior over HTTP.
A standard allowing servers to push data to web pages over HTTP. It is simpler than WebSockets but only supports one-way (server-to-client) communication.
Use WebSockets for bi-directional needs (chat, gaming). Use SSE for one-way updates (stock tickers, news feeds, push notifications).
Most libraries (like Socket.io) handle this automatically. On the backend, you must handle the logic of re-joining rooms or catching up on missed messages using timestamps.
Microservices & System Design20
A monolithic architecture is a traditional model where all components of an application (UI, business logic, data access) are bundled into a single unit and codebase. It is easy to develop and deploy initially but becomes difficult to scale and maintain as the project grows.
An architectural style that structures an application as a collection of small, autonomous services modeled around a business domain. Each service runs its own process and communicates via lightweight protocols like HTTP/REST or gRPC.
1. Scalability: Individual services can be scaled independently. 2. Technology Diversity: Different services can use different tech stacks. 3. Fault Isolation: A failure in one service doesn't necessarily bring down the whole system. 4. Faster Deployment: Smaller codebases are quicker to build and deploy.
1. Complexity: Managing many services is harder than one. 2. Data Consistency: Maintaining consistency across distributed databases is difficult (solved by Saga pattern). 3. Network Latency: Inter-service communication adds overhead. 4. Operational Overhead: Requires robust CI/CD and monitoring.
A mechanism where services automatically detect the network locations (IP/Port) of other services. Since microservice instances are dynamic (auto-scaling), a service registry (like Consul or Eureka) keeps track of available instances.
A server that acts as a single entry point for all client requests. It handles tasks like request routing, authentication, rate limiting, and protocol translation, protecting the internal microservices from direct exposure.
An asynchronous communication protocol where a 'producer' sends a message to a queue, and a 'consumer' processes it later. It helps decouple services and handle traffic spikes (e.g., RabbitMQ, Amazon SQS).
A message-broker software that implements the Advanced Message Queuing Protocol (AMQP). It provides a platform for applications to exchange data and queue messages, ensuring reliable delivery even if the receiver is offline.
A distributed event streaming platform. Unlike traditional message queues, Kafka is designed for high-throughput, real-time data feeds and persists messages on disk, allowing them to be 'replayed'.
1. RabbitMQ: Smart broker/dumb consumer; once a message is processed, it's deleted. 2. Kafka: Dumb broker/smart consumer; messages are persistent and can be re-read by different consumers at their own pace.
A pattern where the state of the system is determined by events. Instead of a service calling another directly, it emits an event (e.g., 'UserCreated'), and other services subscribe to that event to perform their own tasks.
A pattern that separates read and write operations into different models. This allows you to optimize the read model for complex queries (using a NoSQL cache) while keeping the write model strictly for data integrity (SQL).
A pattern where every change to the state of an application is captured as an immutable event in a sequence. To get the current state, you 'replay' all events from the beginning.
A microservices principle where each service manages its own private database. This prevents coupling and allows each service to use the database best suited for its needs (e.g., Graph DB for connections, SQL for transactions).
Transactions that span across multiple physical databases or services. Since standard ACID transactions don't work over a network, they are usually handled by the Saga pattern.
A sequence of local transactions. Each local transaction updates the database and triggers the next step. If one step fails, the Saga executes 'compensating transactions' to undo the changes made by the previous steps.
A design pattern used to detect failures and encapsulate the logic of preventing a failure from constantly recurring during maintenance or temporary external system failure.
A dedicated infrastructure layer for handling service-to-service communication. It provides features like traffic management, security (mTLS), and observability without changing the application code (e.g., Istio).
A popular open-source service mesh that allows you to manage traffic flows between microservices, enforce policies, and aggregate telemetry data.
1. Vertical: Adding more power (CPU/RAM) to an existing server. 2. Horizontal: Adding more servers to your pool. Microservices are built to scale horizontally.
Real-World Scenario Questions30
1. API: POST to create short URL, GET to redirect. 2. Storage: SQL for mapping (Short code -> Long URL). 3. Hashing: Use Base62 encoding on an auto-incremented ID to generate the short code. 4. Caching: Use Redis to cache popular redirects.
Use Redis with the Token Bucket or Fixed Window algorithm. For each request, check the user's IP/Token in Redis; if the count exceeds the threshold within the time window, return 429 Too Many Requests.
1. Backend: Node.js with WebSockets (Socket.io). 2. Pub/Sub: Use Redis Pub/Sub to broadcast notifications across multiple server instances. 3. Persistence: Store notifications in MongoDB so users can see history when they log in later.
1. Backend: Use cursor-based pagination (e.g., `?after=timestamp_id`). 2. Frontend: Use Intersection Observer API to detect when the user reaches the bottom. 3. Data: Append new results to the existing list in state.
1. Frontend: Use `XMLHttpRequest` or `axios` with `onUploadProgress` callback. 2. Backend: Use `Multer` to handle file chunks. 3. Storage: Upload the file to AWS S3 and store the URL in the database.
1. Frontend: Debounced input field. 2. Backend: API that queries the database with a `LIKE` or `Regex` operator. 3. Optimization: Use an indexed search engine like Elasticsearch for faster 'prefix' matching and fuzzy search.
1. Storage: Use Redis for guest carts (short-lived) and SQL for logged-in user carts. 2. Syncing: When a guest logs in, merge their Redis cart into the SQL database. 3. Concurrency: Use database transactions to check stock levels before finalizing the order.
1. Client: Use Stripe Elements to collect card info securely (PCI compliance). 2. Server: Create a PaymentIntent via Stripe API. 3. Webhooks: Listen for Stripe's 'payment_success' event to update the order status in your DB.
Three main approaches: 1. Database per tenant (Isolates data perfectly). 2. Schema per tenant. 3. Shared Database (Add a `tenant_id` to every table - most cost-effective but requires strict query filtering).
Use RBAC (Role-Based Access Control). Store roles in the DB and attach permissions to them. Use middleware in the backend to check if `user.role` has the required permission before executing an action.
1. Schema: Dynamic fields (JSONB in Postgres or MongoDB). 2. Version Control: Store history of changes for each document. 3. Access: Implement a granular permission system for editors and admins.
1. Blog: SQL table for posts. 2. Comments: SQL table with a `parent_id` for nested replies (recursive queries). 3. Sanitization: Strictly sanitize all user input to prevent XSS attacks.
Requires Operational Transformation (OT) or CRDTs (Conflict-free Replicated Data Types) to resolve conflicts when multiple people type at once. Use WebSockets for the live stream of edits.
1. On signup, generate a unique token. 2. Send an email with a link containing the token. 3. When the user clicks, verify the token in the DB and set `is_verified: true`. 4. Use a background job (Bull/Redis) to send emails asynchronously.
1. Storage: S3 for original files. 2. Encoding: Use AWS Elemental or FFmpeg to convert videos into multiple resolutions. 3. Delivery: Use a CDN (CloudFront) to stream segments using HLS or DASH protocols.
1. Content-based: Suggest items similar to what they liked. 2. Collaborative filtering: Suggest what users with similar tastes liked. Usually implemented using Python/Machine Learning and a Vector database.
1. Backend: Aggregation pipeline in MongoDB or TimescaleDB. 2. Live Feed: Push updates via WebSockets. 3. Frontend: Use a charting library like D3.js or Recharts that updates as new data arrives.
1. CSV: Stream the database results directly to the response using a library like `csv-stringify` (to avoid memory issues). 2. PDF: Use a library like `Puppeteer` to render the page as PDF on the server.
1. Concurrency: Use Pessimistic Locking on the database level to ensure two people can't book the same slot at the exact same millisecond. 2. States: Use a status field (Pending, Confirmed, Cancelled).
Use a library like Bull (Redis-based). Define a worker process that picks up tasks (like sending emails or resizing images) from the queue and executes them in the background, retrying if they fail.
Use Multipart Uploads. Split the file into small chunks (5-10MB) on the client, upload them individually to the server or directly to S3, and then have the server reassemble or finalize the upload.
Build a dynamic SQL query (or Elasticsearch query) based on the presence of query parameters in the URL (e.g., `?category=electronics&minPrice=500`). Ensure the filterable columns are indexed.
1. Use a separate set of secure routes. 2. Implement CRUD operations with audit logs. 3. Use an existing library like `React Admin` or `Refine` to speed up the development of standard tables and forms.
Create an `audit_logs` table. Every time a sensitive action occurs (e.g., 'Update Salary'), insert a record containing the `user_id`, `action`, `old_value`, `new_value`, and `timestamp`.
1. Frontend: Use `i18next` with JSON files for static text. 2. Backend: Support the `Accept-Language` header to return error messages in the correct language. 3. Database: Store content in a 'translations' table or as a JSON object per record.
Use an ETL (Extract, Transform, Load) process. 1. Extract data from the old DB. 2. Transform the format in code. 3. Load into the new DB. For large systems, use a 'Blue-Green' deployment to migrate with zero downtime.
Standardize on URL-based versioning (`/api/v1/...`). In the code, use separate router files for each version so you can maintain legacy support while developing the new version.
Add a `deleted_at` timestamp column to your tables. Instead of `DELETE` queries, use `UPDATE` to set the timestamp. In all `SELECT` queries, filter for `WHERE deleted_at IS NULL`.
Always store dates in the database as UTC. Only convert to the user's local timezone (using a library like `luxon` or `date-fns`) in the frontend just before displaying it.
1. Request email. 2. Generate signed JWT with short expiry. 3. Email user the reset link. 4. Verify JWT on the reset page. 5. Hash new password and update DB. 6. Invalidate the token.
Company-Specific: Google5
YouTube uses a two-stage neural network: 1. Candidate Generation: Filters billions of videos down to hundreds based on user history and context. 2. Ranking: Uses a deep neural network to assign a score to each video based on hundreds of features (thumbnail, watch time, user language). The top-scoring videos are presented.
1. Crawling: Use distributed spiders to index the web. 2. Indexing: Use an inverted index (mapping words to documents). 3. Sharding: Distribute the index across thousands of machines based on document ID or keyword. 4. Caching: Use a massive distributed cache for common queries.
1. Metadata: Store file info and permissions in a relational DB. 2. Storage: Use a distributed file system like GFS for binary data. 3. Consistency: Use a strong consistency model for permissions so that revoked access is reflected globally instantly. 4. Notification: Use a pub/sub system to alert users of new shares.
This relies on Operational Transformation (OT) or CRDTs. When a user types, the 'operation' is sent to a server, transformed against concurrent operations from other users, and broadcasted back. This ensures that every client eventually reaches the exact same state without conflicts.
1. Bayesian Filtering: Use machine learning to classify emails as Spam/Social/Promotions based on keywords. 2. Rule Engine: Allow users to create custom filters (IF sender=X THEN move to folder Y). 3. Scalability: Use a distributed message queue to process incoming emails in parallel.
Company-Specific: Meta5
1. Fan-out on Load: When a user views their feed, pull the latest posts from all their friends. 2. Fan-out on Write: When a user posts, push that post to the 'pre-computed' feeds of all their friends. Facebook uses a hybrid approach to balance performance for celebrities (millions of followers) vs regular users.
1. Storage: Store media in a CDN. 2. Lifecycle: Set a TTL (Time To Live) of 24 hours in the database. 3. Visibility: Use a Redis set to track which friends have active stories to show the 'circles' at the top of the app.
1. Write Path: Use an event-driven model to increment counters (likes) and insert records (comments). 2. Consistency: Use an eventually consistent model for like counts to handle high write throughput. 3. Caching: Use a write-through cache (Redis) to serve total counts instantly.
1. Connection: Use persistent WebSockets or MQTT for low-latency message delivery. 2. Routing: Use a 'User-to-Server' mapping in a distributed hash table. 3. Persistence: Store messages in a wide-column store like HBase or Cassandra that handles high write volume efficiently.
Use a distributed pub/sub architecture (Redis or Kafka). Each user is connected to a specific notification server. When an event occurs, the server identifies the user's connection and pushes the notification via a persistent socket.
Company-Specific: Amazon5
Use an inverted index (Elasticsearch) to allow for fuzzy matching and category filtering. Products are indexed with attributes (price, rating, brand). Queries are distributed across nodes, and results are aggregated using a ranking algorithm based on relevance and sales data.
1. Anonymous: Use browser cookies or a Redis store keyed by session ID. 2. Persisted: Once logged in, move items to a relational database. 3. Availability: Use a DynamoDB-style eventually consistent store to ensure the 'Add to Cart' button never fails.
1. State Machine: Define states (Placed, Shipped, Out for Delivery, Delivered). 2. Events: Every time a package is scanned, push an event to a queue. 3. API: The user app polls the API or receives a push notification when the state transitions occur.
Use Item-to-Item Collaborative Filtering. Instead of matching users, match products based on being purchased together. This is more scalable because product relationships change less frequently than user preferences.
Requires high consistency. Use a relational database with strict transactions. When a user checks out, use a Pessimistic Lock on the product row to decrement the 'stock' count, ensuring that an item is never sold twice if only one is in stock.
Company-Specific: Netflix5
1. Storage: S3 for master files. 2. Transcoding: Create thousands of versions of the same video for every device and bandwidth. 3. Open Connect: Netflix's own CDN (hardware placed inside ISP data centers) to serve the video from the nearest possible physical location.
The player sends a 'heartbeat' every few seconds to a 'Playback Service' containing the `video_id` and `timestamp`. This is stored in a high-speed write store like Cassandra. When the home screen loads, it fetches the latest timestamps for the user.
Netflix uses a hybrid model of Collaborative Filtering and Deep Learning. It also uses 'Personalized Artwork'—changing the thumbnail image based on what it thinks *you* are more likely to click (e.g., showing a romantic actor if you watch Rom-Coms).
Parallel processing. Break the video into small chunks and process them across thousands of workers in parallel (MapReduce style). Each worker transcodes a chunk into various formats (H.264, VP9) and resolutions (4K, 1080p, 480p).
Use a multi-tiered CDN strategy. Popular content is cached at the 'Edge' (closer to users), while less popular content is stored in regional caches. This reduces the 'origin fetch' and saves massive bandwidth costs.
Company-Specific: Uber5
Uses Geofencing and Google S2 Library. The map is divided into 'cells'. When a rider requests a car, the system queries the cell and neighboring cells for available drivers. It then uses a ranking algorithm based on distance and driver rating to offer the ride.
Drivers' apps send Lat/Lng every few seconds via WebSockets or gRPC. The server updates the driver's location in a geospatial index (like Redis Geo). The rider's app subscribes to these updates to see the car moving on the map.
Monitor the ratio of riders (demand) to drivers (supply) in a specific geofence. If the ratio exceeds a threshold, increase the price multiplier. This is updated in real-time and broadcasted to both riders and drivers.
1. State Update: Immediately set ride status to 'Cancelled'. 2. Notifications: Alert the other party. 3. Fee Calculation: Check if a cancellation fee applies based on time/distance. 4. Dispatch: Put the driver back into the 'Available' pool.
Fare = Base Fare + (Time * Rate) + (Distance * Rate) + Surge. This calculation happens twice: once as an estimate and once as a final calculation after the trip is completed using the recorded GPS coordinates.
Company-Specific: Airbnb5
1. Search: Elasticsearch with geospatial support. 2. Booking: Relational DB with transactions. 3. Availability: A calendar table that marks dates as 'Booked' or 'Blocked'. Use optimistic locking to prevent double booking.
Represent the calendar as a bitmask or a series of date ranges in a relational table. When a user views a listing, the app checks for overlaps between the requested dates and the 'Booked' ranges.
A 'Reviews' table linked to `listing_id` and `user_id`. Ratings are averaged. To handle millions of reviews, use a write-through cache for the 'Average Rating' so it doesn't have to be calculated on every page load.
Use a third-party processor (Stripe). Store the payment 'intent' in your DB. Use a 2-step process: 1. Authorize: Hold funds when a guest books. 2. Capture: Release funds to the host after the guest checks in (minus the service fee).
Use 'Embedding' models to find properties that 'look' like the ones you've clicked on. Also consider 'contextual' features like the time of year, current city, and your historical travel budget.
Company-Specific: Twitter5
Twitter pre-computes the 'Home Timeline' for active users. When someone you follow tweets, it is inserted into your 'timeline cache'. For users with millions of followers (Celebrities), the tweet is not pushed; instead, it's pulled only when the follower requests it.
Use a 'Sliding Window' algorithm to count hashtags over the last hour. Compare this to the 'expected' frequency. Topics with the highest surge (velocity) become 'Trending'.
Use an inverted index (Earlybird). Tweets are indexed by keywords. The search engine must be extremely low-latency to provide 'real-time' search results as news breaks.
Horizontal sharding of the 'Tweets' table based on `tweet_id`. Use a massive caching layer (Redis) for the most active tweets. Use asynchronous background jobs for tasks like link unwinding and media processing.
Instead of querying `COUNT(*)` from a DB, maintain a counter in Redis. Increment the counter on every 'Follow' event and decrement on 'Unfollow'. This allows for O(1) retrieval of follower counts.
Company-Specific: Spotify5
Uses three main models: 1. Collaborative Filtering: What similar users like. 2. Natural Language Processing: Analyzing what bloggers/critics say about tracks. 3. Audio Analysis: Analyzing the song's tempo, key, and mood directly from the wave file.
Use a relational DB to track which users have 'Edit' access to a `playlist_id`. Use WebSockets to push updates (e.g., 'X added a song') to other collaborators who have the playlist open.
The app downloads the encrypted audio file and a 'license' to the device's local storage. When offline, the app checks the license's expiration. If valid, the app decrypts and plays the file locally.
Use MPEG-DASH or HLS. The audio is cut into 5-10 second segments at different bitrates (High, Medium, Low). The app monitors the network speed and fetches the best segment possible for the next 10 seconds.
Truly random shuffle often results in several songs from the same artist in a row, which users hate. Use 'Fisher-Yates' shuffle combined with a 'dithering' algorithm that ensures artists are spaced out evenly in the queue.
Company-Specific: LinkedIn5
Uses a 'Graph Database' (like Neo4j) to find 'Second-Degree' connections. If User A knows User B, and User B knows User C, the system suggests User C to User A based on 'Mutual Friends'.
Use Elasticsearch with facets. Faceting allows the user to see the number of jobs available in each 'Location' or 'Experience Level' category while they are still refining their search.
Similar to Facebook Messenger but with a 'Professional' layer. Includes features like 'Read Receipts' (set via WebSockets) and 'Typing Indicators'. It stores messages in a distributed database that supports fast chronological queries.
A rule engine that checks for the presence of specific fields (Photo, Summary, Experience). As the user adds data, the 'Strength' score is updated in the DB and reflected in the UI.
Prioritizes 'Professional' content. Features include the number of likes/comments, the user's connection to the author, and whether the content is 'trending' in the user's industry.
Company-Specific: Stripe5
1. Request: App sends tokenized card data. 2. Validation: Check if amount/currency is valid. 3. Gateway: Send request to the bank (Acquirer). 4. Response: Record the success/failure and return to user.
Use an Exponential Backoff strategy for retrying failed API calls to the bank. For customer-facing errors (Insufficient Funds), return the specific bank error code so the app can tell the user to use a different card.
1. Plans: Defined in a table. 2. Subscriptions: Link users to plans. 3. Cron Job: A daily background task that identifies subscriptions due today and triggers a charge. 4. Webhooks: Notify the app when a subscription renews or fails.
1. Request: Admin initiates refund. 2. Check: Verify if the original charge is refundable. 3. Process: Send a 'Credit' request to the bank. 4. Update: Mark original transaction as 'Refunded' and create a new 'Refund' transaction record.
1. Rule Engine: Check for obvious red flags (10 charges in 1 minute). 2. Machine Learning: Compare transaction features (IP, device fingerprint, amount) against millions of known fraudulent transactions to assign a 'Risk Score'.
Behavioral10
Focus on the STAR method (Situation, Task, Action, Result). Explain how you used debugging tools (Profilers, Logs), your logical process to isolate the issue, and the positive impact the fix had on users or the company.
Emphasize professional communication and data-driven decisions. Discuss listening to their perspective, seeking a middle ground, and prioritizing the project's goals over personal ego.
Explain your learning strategy: reading documentation, building a small 'Hello World' project, and seeking mentorship. Highlight a specific project where you successfully delivered code in a tech stack you were new to.
Mention using the Eisenhower Matrix (Urgent vs. Important). Discuss communicating with stakeholders to understand business impact and breaking large tasks into smaller, manageable chunks.
Highlight a project where you had significant ownership. Discuss the technical challenges you overcame, the specific technologies you chose and why, and the final outcome (users, revenue, or performance gains).
Mention specific resources: newsletters (TLDR, JavaScript Weekly), podcasts, following tech leads on social media, attending conferences, and maintaining side projects or a GitHub presence.
Talk about how you identified the bottleneck (e.g., using Chrome DevTools or SQL Profiler), the specific changes you made (caching, indexing, code splitting), and the measurable result (e.g., 50% faster load time).
Acknowledge that it's inevitable. Explain your approach to documenting it, communicating the risk to product managers, and dedicating a percentage of every sprint to refactoring and debt reduction.
View it as a collaborative learning process. Mention looking for logical errors, security flaws, and architectural consistency while being respectful and providing constructive feedback to peers.
Discuss a multi-layered approach: Unit and Integration testing, using Linters and Formatters (Prettier, ESLint), conducting thorough code reviews, and using CI/CD pipelines to catch bugs early.
Related question banks5
JavaScript Questions
108 questionsComprehensive collection of the most frequently asked JavaScript interview questions covering fundamentals, ES6+, async programming, DOM manipulation, objects, arrays, functions, and advanced concepts. Each answer is concise, detailed, and interview-ready.
TypeScript Questions
50 questionsA focused collection of the most critical TypeScript interview questions covering type system internals, advanced types, and best practices for modern development.
React.js Questions
100 questionsComprehensive collection of the most frequently asked React JS interview questions covering fundamentals, hooks, routing, testing, and advanced concepts. Each answer is concise and interview-ready.
Node.js Questions
106 questionsComprehensive collection of the most frequently asked Node.js interview questions covering fundamentals, asynchronous programming, streams, clustering, security, and advanced concepts. Each answer is concise, detailed, and interview-ready.
React Native Questions
250 questionsComprehensive guide covering React Native fundamentals, Architecture, Styling, and Component Communication. Each answer is technically rigorous for professional interviews.