Skip to main content

Interview questions

Full-stack engineer interview questions

Full-stack engineers ship end-to-end web product features. They are fluent in TypeScript, React, Node or another backend runtime, and the database underneath. Strong full-stack engineers move smoothly between UI work, API design, and operational concerns without a handoff.

Seniorities
juniormidseniorstaffprincipal

Most reported

Top full-stack engineer interview questions

6 questions

Sorted by reported frequency. Click any question for the sample outline, follow-ups, and reference implementation.

As asked

Explain when React Server Components are the right tool and when they are not. What changes in your mental model versus traditional React?

Sample answer outline

RSCs run on the server, never ship to the client, and can directly read from the database or filesystem. Good fit: pages that compose lots of data and want zero client JS for that composition (dashboards, content sites, lists). Not a fit: highly interactive UI (charts you can drag, editors, live forms) which still needs client components. The mental model shift: split your tree into server and client boundaries, pass data down as props (serialisable only), avoid mixing concerns. Pitfalls: passing event handlers across the boundary, accidental waterfalls, and the suspense story for streaming.

Expect these follow-ups

  • What is the hydration story for a page that mixes RSC and client components?
  • When does RSC make a page slower, not faster?
  • How does this change with Partial Prerendering?
reactrscnext-js

As asked

Tell me about a feature you owned from problem framing through to production rollout. Walk through the technical and the non-technical decisions.

Sample answer outline

Pick a feature with measurable impact. Cover: how the problem was framed (and how you sharpened the brief), the technical decisions you made (database changes, API shape, UI architecture, rollout plan), the collaborations (design, product, data), and the rollout (canary, metrics watched, incidents during launch). Land on the outcome and what you would do differently. Strong full-stack candidates make non-glamorous decisions sound load-bearing: schema migration ordering, the cache invalidation that you almost missed.

Expect these follow-ups

  • What is the part of the feature you are least proud of?
  • How did you decide what to build vs what to defer?
  • Did the metric actually move?
ownershipdeliverycross-functional

As asked

Implement cursor-based pagination for a feed API in TypeScript. Explain why cursor beats offset for this case.

Sample answer outline

Offset pagination is O(offset) per page on the database (the query still scans the skipped rows) and breaks when items are inserted or deleted mid-paging. Cursor pagination uses an opaque token encoding the last-seen sort key (e.g. created_at + id for uniqueness). The next query is WHERE (created_at, id) < (last_created_at, last_id) ORDER BY created_at DESC, id DESC LIMIT N. Constant time per page, stable under inserts. Encode the cursor as base64 of a small JSON object so clients treat it as opaque. Discuss edge cases: ties on the sort key, bidirectional paging.

Reference implementation (typescript)

TypeScript
type Cursor = { createdAt: string; id: string };

export function decodeCursor(token: string | null): Cursor | null {
  if (!token) return null;
  return JSON.parse(Buffer.from(token, "base64url").toString());
}

export function encodeCursor(c: Cursor): string {
  return Buffer.from(JSON.stringify(c)).toString("base64url");
}

export async function fetchFeed(after: string | null, limit = 20) {
  const cursor = decodeCursor(after);
  const rows = await db.query(
    `SELECT id, created_at, body FROM posts
     WHERE ($1::timestamptz IS NULL OR (created_at, id) < ($1, $2))
     ORDER BY created_at DESC, id DESC LIMIT $3`,
    [cursor?.createdAt ?? null, cursor?.id ?? null, limit],
  );
  const last = rows[rows.length - 1];
  return {
    items: rows,
    nextCursor: last ? encodeCursor({ createdAt: last.created_at, id: last.id }) : null,
  };
}

Expect these follow-ups

  • How do you implement bidirectional pagination (back and forth)?
  • What if the sort field is a non-unique field like score?
  • When is offset still the right choice?
paginationapi-designsql

As asked

A page loads in 4 seconds. The database shows 200 queries per page load. You suspect an ORM N+1. Walk me through how you would fix it.

Sample answer outline

Confirm the diagnosis: turn on query logging, look at the call site that generates the chatty queries. Usually a loop that accesses a lazy-loaded relation. Fix with the ORM's eager loading primitive (include, with, populate, prefetch_related). Alternatively, batch the lookup with a single IN query. After the fix, verify the page is one or two queries. Watch for the second-order N+1 where the eagerly loaded set itself has a lazy relation. For React/Node: use a dataloader to batch requests inside a request scope.

Reference implementation (typescript)

TypeScript
// Bad: N+1 (one query per post for its author)
const posts = await prisma.post.findMany({ where: { feed: feedId } });
for (const post of posts) {
  const author = await prisma.user.findUnique({ where: { id: post.authorId } });
  // ...
}

// Good: eager load in a single query
const posts = await prisma.post.findMany({
  where: { feed: feedId },
  include: { author: true },
});

// Alternative: batch with DataLoader inside a request scope
const userLoader = new DataLoader<string, User>(async (ids) => {
  const users = await prisma.user.findMany({ where: { id: { in: [...ids] } } });
  const byId = new Map(users.map((u) => [u.id, u]));
  return ids.map((id) => byId.get(id)!);
});

Expect these follow-ups

  • Why does an ORM lazy-load by default?
  • When is a JOIN slower than two queries?
  • How would you catch an N+1 in CI before it ships?
ormn-plus-oneperformance

As asked

Walk me through what happens when a user loads a page in an app you own end to end. I want you to cover both the server side, where your backend generates the response, and the client side, where the browser turns it into pixels, and the choices that span both.

Sample answer outline

A full-stack engineer should narrate both halves and the seam between them. Server side: the request hits your application, which may run middleware, query the database, render markup or serialise data, and set caching and security headers. The response then travels back, and the browser parses HTML into the DOM, builds the CSSOM, runs JavaScript, and lays out and paints. The interesting decisions span both: what you render on the server versus hydrate on the client, how cache headers and a CDN change the second visit, how the payload shape avoids client over-fetching, and where authentication is checked. The strong answer shows you reason about the whole round trip rather than treating frontend and backend as separate worlds.

Expect these follow-ups

  • Which work do you keep on the server and which do you defer to the client?
  • How do cache headers and a CDN change the second page load?
  • Where in this flow do you enforce authentication?
browser-internalsfull-stackssrcaching

As asked

As a full-stack engineer, how do React Server Components change how you connect the UI to your backend and database? Walk me through the data access pattern, what stays on the server, and the mistakes you would guard against.

Sample answer outline

From a full-stack perspective, server components collapse part of the API layer: a server component can query the database or call an internal service directly, so for read paths you often do not need a separate client-side fetch and an endpoint to back it. Keep secrets, database clients, and heavy data access strictly on the server side of the boundary, and pass only the plain data the client needs down as props. For writes, use server actions or API routes, and keep the client component thin. The mistakes to guard against are leaking server-only modules or credentials into client code, creating accidental waterfalls by chaining dependent server queries, and over-fetching by sending whole records to the client when a slice would do. The full-stack signal is owning the data path from database to rendered UI and deciding deliberately what crosses the network.

Expect these follow-ups

  • When do you still need a separate API endpoint with server components?
  • How do you keep database credentials from leaking into the client bundle?
  • Where do server actions fit for write operations?
reactrscfull-stackdata-fetching

Also known as

product engineer - software engineer - web engineer