Backend interview essentials
Build from language fundamentals to APIs, data correctness, and production reasoning.
JavaScript & TypeScript
Explore topicScope, closures, async behavior, object identity, and the type system.
What is an execution context and call stack?
An execution context is the information JavaScript uses while running a piece of code, including its variables, scope and this value. The call stack tracks which function is currently running and where execution should return. Each function call adds a context, and returning removes it.
What is scope? What does lexical mean?
Scope is the part of a program where a variable can be accessed. JavaScript uses lexical scope, which means the available outer variables depend on where a function was defined, not where it is later called. The engine searches outward through surrounding scopes when a name is not found locally.
What is the difference between var, let and const?
var, let and const declare variables, but they have different scope and initialization rules. let and const are block-scoped, making it easier to keep a variable inside the code that needs it. const prevents reassignment of the binding; it does not make an object immutable.
What are hoisting and the TDZ (Temporal Dead Zone)?
Hoisting is JavaScript's behavior of processing declarations before executing the code in a scope. Because of this, a function declaration can usually be called before its line appears, while variables behave differently depending on how they are declared.
Are objects passed by reference?
JavaScript passes every argument by value. For an object, the copied value is a reference to that object, so the caller and function can still reach the same underlying object. This explains why changing a property affects the caller, but assigning a new object to the parameter does not.
What is the difference between == and ===?
== is loose equality: it may convert values to compatible types before comparing them. === is strict equality: it compares without that conversion. Strict equality usually makes application checks easier to understand because strings, numbers and booleans are not silently treated as the same value.
What are null, undefined and NaN?
undefined usually means a value has not been supplied, while null is commonly used to mark an intentionally empty value. NaN means a numeric calculation or conversion did not produce a valid number. These are different cases, so an API should not treat them as interchangeable without a clear rule.
What is a closure?
A closure is a function together with access to the variables in the scope where it was created. That access remains available even after the outer function has finished running. Closures are useful for private state, callbacks and functions configured with some remembered value.
How does async JavaScript run?
Asynchronous JavaScript lets a program start work that may finish later without waiting synchronously for the result. A promise represents eventual completion, and async/await provides a readable way to work with promises. The runtime queues continuations and runs them when the current synchronous work has finished and the relevant checkpoints are reached.
Which Promise method should I use?
Promise combinators combine several promises into one result. The correct method depends on whether you need every success, every outcome, the first outcome or the first success. They observe promises; they do not automatically cancel ongoing operations when the combined result settles.
Why does forEach with async cause problems?
forEach calls a callback for each array item but ignores the values returned by those callbacks. An async callback returns a promise, so forEach does not wait for its completion or collect its rejection. Choose a loop or a promise combinator based on whether the operations depend on each other.
What causes a race condition?
A race condition happens when the result depends on the timing of operations that access shared state. JavaScript can have races even on one execution thread because asynchronous work pauses and lets other requests run between a read and a write. Databases and other processes can also update the same data concurrently.
Node.js, Express & HTTP
Explore topicTrace requests, understand the runtime, and build reliable APIs.
Browse interview questionsNestJS
Explore topicDependency injection, request lifecycle, validation, and database integration.
How does dependency injection work?
Dependency injection means a class receives the objects it needs instead of constructing them itself. Nest's container uses registered provider tokens to build and connect these dependencies. This centralizes construction and lets tests or configuration replace an implementation without rewriting its consumers.
What is the Nest request lifecycle?
The request lifecycle is the order in which Nest processes an incoming request and produces a response. Different extension points handle different concerns, such as access checks, input conversion and response wrapping. Knowing the order helps explain why code in one stage cannot rely on work that happens later.
How do global, controller and route handlers interact?
Nest can attach request handlers at global, controller and route scopes. Scope determines which requests a handler applies to, while handler type determines execution order. Interceptors wrap inner work and unwind on the response path; exception filters select a matching handler rather than form a normal middleware chain.
Guard vs pipe vs interceptor vs filter?
Guards, pipes, interceptors and filters are separate request extension points with different jobs. A guard decides whether work may proceed; a pipe validates or transforms arguments; an interceptor wraps execution; a filter handles uncaught errors. Choosing the correct point avoids mixing authentication, validation and formatting into business methods.
How should a TypeORM transaction work?
A transaction groups database changes so they can commit together or roll back together. In TypeORM, the transaction callback receives a manager tied to that transaction's connection. Queries issued through an unrelated global repository may not participate, even if they appear inside the same JavaScript callback.
MongoDB & Mongoose
Explore topicDocument modeling, aggregation, indexes, and consistency.
How do indexes help, and what do they cost?
An index is an extra data structure that helps the database find matching records without inspecting every document. Reads can become much faster, but inserts, updates and deletes must maintain the relevant indexes. Indexes are most useful when their fields and order match important query patterns.
What index types should I know?
MongoDB offers different index types because equality lookup, array search, text search, uniqueness and expiry have different needs. A compound index orders several fields together, while a partial index includes only documents matching a condition. TTL indexes support eventual cleanup rather than precise scheduling.
When do I need a transaction?
A transaction makes several database operations commit or roll back as a unit. MongoDB already makes single-document writes atomic, so a transaction is mainly needed when one business rule spans multiple documents. A session supplies transaction context; every participating operation must use that context.
SQL & PostgreSQL
Explore topicJoins, window functions, transactions, and query optimization.
What does ACID mean?
ACID describes four properties used to reason about reliable transactions: atomicity, consistency, isolation and durability. Together they address partial changes, preserved rules, concurrent work and persistence after commit. They do not automatically supply correct business rules or the strongest isolation level.
What are isolation levels and read anomalies?
Isolation defines how one transaction can observe and interfere with concurrent transactions. Different levels allow different anomalies to balance correctness, concurrency and retry cost. PostgreSQL uses snapshots under MVCC, but even a stable snapshot does not automatically make every business decision safe against concurrent writes.
Optimistic vs pessimistic locking?
Optimistic locking checks whether data changed before committing an update, often by comparing a version number. Pessimistic locking acquires a database lock before performing a critical change. The first avoids waiting when conflicts are rare; the second coordinates competing writers but can increase waits and deadlocks.
What is a deadlock, and how do I handle it?
A deadlock is a cycle of waiting transactions: each holds a lock another needs to continue. The database detects the cycle and cancels a participant so the others can proceed. Applications must treat that cancellation as a failed transaction and decide whether to retry it.
Which indexes should I know?
An index is a separately maintained structure that makes suitable lookups, joins or ordering operations cheaper. B-tree is a common general-purpose choice, while composite, partial and unique indexes describe field arrangement, row selection and data rules. An index helps only when the planner estimates its use is worthwhile for the query and data.
Is an index scan always faster than a sequential scan?
An index scan follows an index to locate matching rows, while a sequential scan reads the table directly. If a query needs much of a table, following many scattered row locations can cost more than scanning it. PostgreSQL's planner weighs expected row count, I/O and other costs rather than always preferring indexes.
System design
Explore topicArchitecture decisions, distributed systems, and ten design scenarios.
Performance & security
Explore topicInvestigate production incidents and protect application boundaries.
API latency jumps from 200ms to 5s. What do I do?
A jump from 200ms to 5s indicates that requests are doing more work, waiting longer, or both. The first task is to establish scope and timing so the incident is not mistaken for one user's network issue. Then use measured stages to separate a recent regression from traffic or dependency saturation.
PostgreSQL CPU becomes very high. What do I check?
High PostgreSQL CPU means the database is spending substantial time processing work rather than simply waiting for requests. Causes include expensive queries, poor plans, repeated query volume or maintenance work. CPU alone does not tell you whether an index, query rewrite or traffic reduction is the right fix.
MongoDB aggregation becomes slow. What do I check?
A slow aggregation often processes a much larger intermediate dataset than its final output suggests. Joins, unwinds, sorts and groups can expand work or exceed useful memory limits. Inspecting the pipeline stage by stage reveals where the expensive growth occurs.
Node memory keeps growing. How do I investigate?
Growing Node memory can be normal temporary allocation, retained JavaScript objects, native buffers or another process-level resource. A leak is suggested when unnecessary retained memory continues to grow across comparable workloads and garbage-collection cycles. Heap size and total process memory are related but not identical measurements.
The event loop is blocked. What do I do?
An event-loop block happens when synchronous JavaScript occupies the thread long enough to delay other callbacks. Requests can appear to hang even when their own logic is simple because they share that scheduling thread. Measuring loop delay and CPU profiles connects the symptom to a specific workload.
The database connection pool is exhausted. What do I do?
A connection pool has a limited number of database connections and queues callers when all are busy. Exhaustion can come from too much parallel work, slow queries, long transactions or connections that are never released. Increasing the limit may overload the database instead of fixing the cause.
Authentication tokens are being abused. What do I do?
Abused credentials create an active access-control incident, not just a validation bug. The response must stop unauthorized use, establish how credentials were obtained and restore the affected authentication boundary. The right revocation action depends on whether a single session, many refresh tokens or signing credentials were compromised.
A third-party API starts timing out. What do I do?
A third-party timeout means your service did not receive an answer within its waiting budget. It does not prove that the remote operation was never performed. Timeouts need bounded waiting, controlled concurrency and a strategy for uncertain results, especially for actions with side effects.
Duplicate workflow jobs are processed. How do I fix this?
Duplicate jobs can occur when a producer resends work or a consumer crashes before acknowledging a completed action. Many reliable delivery systems intentionally allow redelivery to avoid losing work. Correct processing therefore identifies the logical operation and makes repeated attempts safe.
A deployment causes intermittent 500s. What do I check?
Intermittent failures after deployment often mean only some instances, requests or data shapes are incompatible with the change. A rolling deployment can briefly run old and new versions together. Grouping errors by instance and version reveals whether the issue is configuration, code, readiness or schema compatibility.
Testing & delivery
Explore topicTesting, Git, containers, CI/CD, and cloud fundamentals.
Browse interview questions