Full-Stack Developer interview prep
A spaced-repetition deck of 716+ Full-Stack Developer interview questions — organised by topic and difficulty, and resurfaced right before you'd forget. Preview a few cards below, then choose access to study the whole track on an Anki-style SM-2 schedule.
7 days free on monthly or yearly · every feature included.
What's covered
Every topic in this track, grouped the way you'd study it.
Python
122 cardsDatabases
104 cardsBackend
169 cardsFrontend
146 cardsCS Fundamentals
76 cardsDevOps & Infra
35 cardsSystem Design
29 cardsBehavioral
35 cardsSample questions
A few cards from the deck — reveal each answer, then choose access to study the full set on a schedule.
What's the difference between mutable and immutable types?
What's the difference between mutable and immutable types?
Short answer: Mutable objects can be changed in place without creating a new object (list, dict, set, bytearray); immutable ones cannot (int, float, str, bytes, tuple, frozenset, bool, None). Any "change" to an immutable object creates a new object.
In depth: Mutability is about whether an object can change its contents while keeping the same id() (its address in memory).
# Immutable: the operation creates a NEW object
s = "hello"
print(id(s))
s += " world" # a new string is created
print(id(s)) # id changed — it's a different object
# Mutable: the same object is changed
lst = [1, 2, 3]
print(id(lst))
lst.append(4) # change in place
print(id(lst)) # same id
Why it matters:
- Hashability. Only objects that are immutable (by content) can be used as
dictkeys orsetelements. If a key could change, its hash would drift and it couldn't be found. - Safety when sharing. An immutable object can be safely shared across threads/functions — no one can corrupt it.
- Function arguments. Python passes a reference to the same object: a function can mutate a mutable argument's contents, but rebinding the local parameter does not rebind the caller's variable.
⚠️ Gotcha: A tuple is immutable, but if it holds a list, that list can still be changed:
t = ([1, 2], 3)
t[0].append(99) # OK! the list inside is mutable
print(t) # ([1, 2, 99], 3)
# t[0] = [...] # THIS is a TypeError — you can't reassign an element
Also, hash(([1,2], 3)) will fail — a tuple is unhashable if it contains an unhashable element.
What does SELECT do, and in what order do the parts of a query execute?
What does SELECT do, and in what order do the parts of a query execute?
Short answer: SELECT retrieves rows from tables. The logical execution order does NOT match the written order: first FROM, then WHERE, GROUP BY, HAVING, SELECT, DISTINCT, ORDER BY, LIMIT.
In depth:
Written (syntactic) order:
SELECT DISTINCT col1, agg(col2)
FROM t
WHERE cond
GROUP BY col1
HAVING agg_cond
ORDER BY col1
LIMIT 10 OFFSET 20;
Logical execution order:
1. FROM / JOIN -- which tables, how to join
2. WHERE -- row filter BEFORE grouping
3. GROUP BY -- grouping
4. HAVING -- group filter AFTER aggregation
5. SELECT -- evaluate expressions, aliases
6. DISTINCT -- remove duplicates
7. ORDER BY -- sorting
8. LIMIT / OFFSET -- slice
⚠️ Gotcha: an alias from SELECT cannot be used in WHERE (since WHERE runs before SELECT), but it can be used in ORDER BY and often in GROUP BY (depends on the DBMS). Example of the error:
SELECT salary * 12 AS annual FROM emp WHERE annual > 100000; -- ERROR
SELECT salary * 12 AS annual FROM emp ORDER BY annual; -- OK
- What is HTTP and how does the request-response cycle work?
- What is HTTP and how does the request-response cycle work?
Short answer: HTTP (HyperText Transfer Protocol) is a text-based application-layer client-server protocol on top of TCP (in HTTP/3 — on top of QUIC/UDP). The client sends a request, the server returns a response; the connection holds no state between requests (stateless).
In depth:
A request consists of a start line (method + path + version), headers, and an optional body:
POST /api/v1/users HTTP/1.1
Host: api.example.com
Content-Type: application/json
Accept: application/json
Content-Length: 38
{"name": "Anna", "email": "a@ex.com"}
A response consists of a status line (version + code + reason phrase), headers, and a body:
HTTP/1.1 201 Created
Content-Type: application/json
Location: /api/v1/users/42
{"id": 42, "name": "Anna", "email": "a@ex.com"}
⚠️ Gotcha: "HTTP only works over TCP" is incorrect for HTTP/3, which uses QUIC over UDP. And the reason phrase ("OK", "Created") is purely informational — clients should rely on the numeric code, not the text.
- Data types: primitives vs objects?
- Data types: primitives vs objects?
Short answer: JS has 7 primitive types (string, number, boolean, null, undefined, symbol, bigint) and one reference type — the object (including arrays, functions, dates). Primitives are immutable and copied by value; objects are copied by reference.
In depth:
// Primitives — copied by value
let a = 10;
let b = a;
b = 20;
console.log(a); // 10 — a is unchanged
// Objects — copied by reference
let obj1 = { x: 1 };
let obj2 = obj1;
obj2.x = 99;
console.log(obj1.x); // 99 — both variables point to the same object
// Primitives are immutable: you can't "change" a string, only create a new one
let str = "hello";
str[0] = "H";
console.log(str); // "hello" — unchanged
// bigint — for integers larger than 2^53 - 1
const big = 9007199254740993n;
console.log(big + 1n); // 9007199254740994n
// symbol — a unique identifier
const id = Symbol("id");
Primitives store the value directly. They "have methods" thanks to autoboxing: "abc".toUpperCase() temporarily wraps the string in a String wrapper object.
⚠️ Gotcha: typeof function(){} returns 'function', even though a function is an object. And typeof [] is 'object', so for arrays use Array.isArray([]).
What is Big O notation?
What is Big O notation?
Short answer: Big O describes how an algorithm's running time or memory usage grows as the input size n increases, dropping constants and lower-order terms. It's an upper bound on the growth rate.
In detail:
Big O answers the question "what happens when n becomes very large?". We're not interested in the exact number of operations, only the nature of the growth. That's why O(2n + 100) simplifies to O(n), and O(3n² + n) — to O(n²).
The main growth classes (from best to worst):
# O(1) — constant: doesn't depend on n
def first(arr):
return arr[0] if arr else None
# O(log n) — logarithmic: each step halves the problem (binary search)
def binary_search(arr, target):
lo, hi = 0, len(arr) - 1
while lo <= hi:
mid = (lo + hi) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
lo = mid + 1
else:
hi = mid - 1
return -1
# O(n) — linear: a single pass
def total(arr):
s = 0
for x in arr: # n iterations
s += x
return s
# O(n log n) — efficient sorts (merge, quick, Timsort)
def sort_it(arr):
return sorted(arr)
# O(n^2) — quadratic: a nested loop
def has_dup_naive(arr):
for i in range(len(arr)):
for j in range(i + 1, len(arr)):
if arr[i] == arr[j]:
return True
return False
# O(2^n) — exponential: naive Fibonacci, enumerating subsets
def fib_naive(n):
if n < 2:
return n
return fib_naive(n - 1) + fib_naive(n - 2)
A rough guide to growth at n = 1,000,000: O(1) — 1 operation, O(log n) — ~20, O(n) — a million, O(n log n) — ~20 million, O(n²) — a trillion (already too much), O(2^n) — infeasible even at n = 50.
⚠️ Gotcha: Big O is about asymptotics (behavior at large n), not about actual time. An O(n) algorithm can be slower than an O(n²) one on small data because of large constants. People also confuse: Big O (upper bound), Ω (lower bound), Θ (tight bound); in interviews "O" usually means Θ.
What is Docker and what problem does it solve?
What is Docker and what problem does it solve?
Short answer: Docker is a containerization platform that packages an application together with all its dependencies, libraries, and configuration into an isolated, portable image. It solves the "works on my machine, but not on the server" problem.
In depth:
The classic pain: a developer wrote code on their laptop (Python 3.11, a specific version of libpq, environment variables), but the server has a different OS version, doesn't have the other libraries, and the variables aren't set — the application crashes. Docker pins the whole environment into an image, and that image runs identically locally, in CI, and in production.
What Docker gives you:
- Reproducibility — the same image everywhere. The environment is described as code (a Dockerfile) and can be versioned in git.
- Isolation — containers don't interfere with each other (dependencies, ports, processes).
- Portability — the image runs on any machine with Docker, regardless of the host OS.
- Fast startup — a container comes up in seconds (unlike a VM).
# Build an image from the Dockerfile in the current directory
docker build -t myapp:1.0 .
# Run a container from the image, publish a port, in the background
docker run -d -p 8000:8000 --name myapp myapp:1.0
# List running containers
docker ps
# Get a shell inside a running container
docker exec -it myapp bash
# Container logs
docker logs -f myapp
⚠️ Gotcha: Docker doesn't "virtualize hardware" and doesn't run a full OS. Containers use the host's kernel. So a Linux image won't run natively on the Windows kernel — on Windows/macOS a lightweight Linux VM runs under the hood (via WSL2 or a hypervisor), and the containers run inside it.
Ready to make it stick?
Start your first session in under a minute. Your future self, mid-interview, will thank you.
Questions about this track
How should I prepare for a Full-Stack Developer interview?
Study the concepts you'll be asked to explain, not just the ones you can code. RecallDeck's Full-Stack Developer track gives you 716+ curated interview questions and resurfaces each one with an Anki-style SM-2 schedule right before you'd forget it — so the answers are still there under pressure on interview day.
What topics does the Full-Stack Developer track cover?
The Full-Stack Developer track is organised into the core areas Full-Stack Developer interviews actually test, grouped by topic and by difficulty (Concept, Junior, Middle, Senior). You can preview the full outline and sample questions above before signing in.
Is spaced repetition effective for Full-Stack Developer interview prep?
Yes. Actively recalling an answer and grading yourself honestly builds far more durable memory than re-reading notes. RecallDeck schedules each Full-Stack Developer card to reappear at the moment you're about to forget it, so your daily reviews shrink while your recall holds.
Can I try the Full-Stack Developer track before paying?
Yes. Monthly and yearly access include a seven-day trial of the complete Full-Stack Developer track, the full SM-2 scheduler, statistics, flexible pacing, and cram mode. You can cancel online before the first charge.