Cheat sheet · Full-Stack Interview Questions for 4+ Years

Full-Stack Questions cheat sheet

The facts a 4+ year full-stack interview probes: current versions, comparison tables, traps and short model answers. Versions used in the lessons: Tailwind 4, TypeScript 7, React 19, Next.js 16, Express 5, Prisma 7.

Read the full series →

blogs · jp-blogs.vercel.app/cheatsheets/series/fullstack-qa

HTML and CSSLesson 1 →

AttributeBehaviour
deferParallel download, runs after parsing, in order
asyncRuns on arrival, no fixed order (analytics)
preload / preconnectFetch a known file now / open the connection early
fetchpriority="high"Eager hint for the one LCP image
  • Cascade: importance and layers, then specificity (IDs, classes, types), then order. Unlayered CSS beats layers.
  • :where() scores zero; :is() takes its strongest argument. border-box makes width include padding and border.
  • Flex item overflows: min-width: 0. Margin collapse is vertical only; display: flow-root stops it.

Watch out: z-index only works inside a stacking context, and opacity or transform on a parent traps it. Sticky fails under overflow: hidden.

Tailwind CSS v4Lesson 2 →

v3 habitv4
@tailwind base; ...@import "tailwindcss";
tailwind.config.js and content@theme { } in CSS; automatic detection
darkMode: 'class'@custom-variant dark (...)
bg-[--brand]bg-(--brand)
shadow-sm, outline-none, ringshadow-xs, outline-hidden, ring-3
  • Tailwind reads files as plain text: write full class names. bg-${color}-500 is never generated.
  • cn() = clsx (join, skip falsy) + twMerge (last conflicting class wins). cva builds variant props.
  • @theme inline when a token points at another variable. hover: only fires on hover-capable devices.

TypeScript 6 and 7Lesson 3 →

Old beliefNow
strict is off by defaultOn by default
@types/* load automaticallytypes is empty: add "types": ["node"]
baseUrl with pathsbaseUrl removed; put the prefix in paths
moduleResolution: nodeRemoved: bundler or nodenext
noUncheckedIndexedAccess
arr[0] is T | undefined
exactOptionalPropertyTypes
x?: T means missing, not undefined
verbatimModuleSyntax
Needs import type (error TS1484)
erasableSyntaxOnly
No enum or parameter properties

Tip: unknown = check before use, any = skip checks, never = impossible. Prefer an as const object plus union over enum.

React 19 reviewsLesson 4 →

useEffect(() => setX(f(y)), [y])
Derived state: compute during render
fetch in effect, no cleanup
Race: AbortController or a data library
Context value `{{ a, b }}` inline
New object every render: memoize or split
`key={i}` on a changing list
State moves to the wrong row: stable id
`{n && <A/>}` with `n = 0`
Renders 0: use n > 0 &&
`items.sort()` on state
Mutates: [...items].sort() or toSorted()
FeatureVersion
use, Actions, useActionState, useOptimistic19.0
ref as a prop; Context as its own provider19.0
Activity, useEffectEvent19.2

Watch out: useFormStatus only sees a parent form element. Actions reset uncontrolled fields: return the submitted values.

Next.js 16Lesson 5 →

  • Server Components by default. A Client Component also runs on the server when prerendering.
  • params, searchParams, cookies() are Promises: await them. middleware.ts is now proxy.ts (Node runtime).
  • Turbopack is the default. Caching is opt-in with use cache; fetch is not cached by default.
FunctionUse
updateTag(t)Server Actions only. Expire now (read your own writes)
revalidateTag(t, "max")Mark stale; serve old while rebuilding
revalidatePath(p)One route, less precise
refresh()Re-fetch the current route payload
export async function getProducts() {
  "use cache";
  cacheLife("hours");
  cacheTag("products");
  return db.product.findMany();
}

Watch out: A Server Action is a public POST. Authenticate, validate, and authorize inside it. NEXT_PUBLIC_ values are frozen at build.

Node.js and Express 5Lesson 6 →

  • Order: sync code, nextTick, promises, timers, I/O, setImmediate. In ES modules, promises run before nextTick.
  • The libuv pool has 4 threads by default (fs, dns.lookup, zlib, some crypto). Network I/O does not use it.
  • Respect write() returning false, or use pipeline().
ToolUse it for
worker_threadsCPU-heavy work in one process
clusterAll cores on one machine, shared port
child_processOther programs (ffmpeg, Python)
Express 4Express 5
Async errors need .catch(next)Rejections reach the error handler
/*/*splat (array in req.params)
req.body is {} without parserundefined

MongoDBLesson 7 →

Embed whenReference when
Read together, small, bounded listChild read alone, or shared by many parents
Child changes only with the parentChild changes often; list can grow forever
  • One document is always atomic. Limit is 16 MiB, so unbounded arrays are the top anti-pattern.
  • Compound index order: Equality, Sort, Range. TTL index needs a date; it runs about every 60 s.
  • Only one text index per collection. Multikey: at most one array field per compound index.
  • ObjectId is 12 bytes (time, random, counter). Never compare it with a plain string.

Tip: Use w: "majority" for important writes. Transactions are for multi-document work, not one order with embedded items.

Prisma 7 and SQL trapsLesson 8 →

CommandWhere
migrate devLocal only; shadow database
migrate deployCI and production; never resets
db pushPrototypes; no migration file
migrate resolveFix history without running SQL
  • In v7, migrate dev no longer runs generate or seed. The URL lives in prisma.config.ts.
  • Sequential $transaction([...]) vs interactive async (tx): only the second can use earlier results.
  • include runs 2 queries by default; relationJoins makes it 1.
  • Use tagged $queryRaw. $queryRawUnsafe with joined strings is an injection hole.

Watch out: SQL traps: NOT IN with NULL, LEFT JOIN plus WHERE, join fan-out, window frames. Set a pool timeout.

GraphQL and HasuraLesson 9 →

AspectHasura v2Hasura v3 (DDN)
EngineHaskell, talks to the DBRust, via data connectors
ConfigMetadata, hasura CLIOpenDD, ddn CLI
SchemaOne per roleOne built schema, role annotations
  • Hasura compiles GraphQL to one SQL statement, so DB relations avoid N+1. Index your columns.
  • Permissions per role, table and operation use session variables (JWT claims or webhook).
  • Event triggers are at least once; retries are off by default. Make handlers idempotent.
  • Plain GraphQL: per-request DataLoader, ! bubbles to the nearest nullable parent, cursors beat offset on deep pages.

Watch out: Community Edition (v2) has no API limits, @cached or per-role introspection control.

LLMs, agents and RAGLesson 10 →

Workflow
Code decides the path (chain, route, parallel, evaluator)
Agent
Model uses tools in a loop with a stop rule
MCP tools
Model calls them (get_order)
MCP resources
App reads them (URI)
MCP prompts
User picks them (slash command)
RAG symptomFix
Right doc exists, not retrievedHybrid search, better chunks, reranker
Model ignores good contextFewer, better chunks; rerank
Confident with no sourceScore threshold and a refuse path
Leaks private dataFilter by ACL inside the query

Tip: Prompt first, RAG for your changing data, fine-tune for style. Measure recall@k, MRR, faithfulness. AI SDK: set stopWhen or the loop stops after one step.

Redis cachingLesson 18 →

PatternWrite path
Cache-asideWrite the DB, then delete the key
Write-throughCache and DB together; both agree
Write-behindCache first, DB later; can lose writes
Hash
A session or user's fields
Sorted set
Leaderboard, delayed jobs, rate window
Stream
Reliable queue with consumer groups
HyperLogLog
Approximate unique count
  • Stampede: single-flight, SET k v NX PX, early refresh, or serve stale. Always a TTL with jitter.
  • RDB = snapshot; AOF = log (everysec loses about 1 s). Neither is a backup.
  • Default eviction is noeviction. Caches want allkeys-lru or allkeys-lfu.

Queues and webhooksLesson 19 →

DeliveryMeaning
At-most-onceMay be lost, never repeated
At-least-onceNever lost, may repeat
Exactly-onceOnly special closed setups
  • Build at-least-once plus idempotent handlers. Retries: attempts, backoff with jitter, dead-letter queue.
  • Outbox: event row and business row in one transaction, then a relay publishes.
  • Webhooks: raw body, HMAC with constant-time compare, timestamp check, fast 2xx, dedupe by event id.
TraitRabbitMQKafkaSQS
ReplayNoYes (offset)No
OrderPer queuePer partitionFIFO group

Auth: OAuth, OIDC, sessionsLesson 22 →

TokenPurposeKeep it
AccessCall an API; minutesServer side
RefreshGet new access tokensServer only
ID (JWT)Who logged in; read onceNot stored
`state`
Stops login CSRF
PKCE verifier
Stops code theft
`nonce`
Stops ID token replay
  • OAuth = what may this app do; OIDC = who is this user. Use code flow with PKCE; no implicit or password grant.
  • Database sessions revoke at once. JWT sessions cannot before expiry.
  • Link accounts only on a verified email. Passkeys are phishing-resistant; TOTP is phishable.

Watch out: proxy.ts is an optimistic check only. Check again in the data layer, every action, and inside the query.

TestingLesson 21 →

DoubleReal code?Use
StubNoFixed answer
SpyYesCheck a call happened
MockNoCheck how it was called
FakeSimple versionReplace a database or queue
getBy...
Throws if missing: must be there
queryBy...
Returns null: assert it is absent
findBy...
Waits: it appears soon
  • Vitest globals are off; vi.mock is hoisted (vi.hoisted). MSW fakes the network, not fetch.
  • Playwright: use retrying expect, never waitForTimeout. Test the DB with the real engine.
  • Coverage shows untested code, not tested behaviour.

Deploy, Docker and opsLesson 26 →

StrategyTrade-off
RollingCheap; old and new run together
Blue-greenInstant rollback; double capacity
CanaryFew users hurt; needs metrics
RecreateSimple; downtime
  • Dockerfile: multi-stage, copy the lockfile first, npm ci, .dockerignore, non-root USER, start node directly.
  • Migrations: expand then contract. Never drop or rename in the same release.
  • Logs say what, metrics say that something is wrong, traces say where.
SLODowntime in 30 days
99.9%43.2 minutes
99.99%4.3 minutes

Interview one-linersLesson 24 →

QuestionShort answer
Merge vs rebase?Merge keeps history. Rebase rewrites it. Never rebase shared commits.
reset vs revert?reset moves the branch. revert adds an undo commit (safe if pushed).
Safe force push?--force-with-lease, plus --force-if-includes.
Trunk-based vs Gitflow?Trunk with flags for web apps. Gitflow for parallel versions.
^1.2.3 vs ~1.2.3?<2.0.0 vs <1.3.0. The lockfile is the truth; use npm ci.
Password hashing?Argon2id (OWASP e.g. m=19456, t=2, p=1). bcrypt cuts input at 72 bytes.
SSRF defence?Allow http(s), check resolved IPs, no redirects, isolate.
SSE or WebSocket?SSE server to browser; WebSocket two-way. Add heartbeat.

A cheat sheet is a reminder, not a teacher. Each card links to the lesson that explains it step by step.