Most "full stack" hires are frontend developers with an ORM. Here's the 90-minute broken-repo interview that catches it, the four seams where their code quietly fails, and what 2026 rates actually look like.
Week six, 9:40am: the feature works on the developer's laptop, passed review, deployed clean — and Postgres starts answering `FATAL: sorry, too many clients already` at about forty concurrent users. Every serverless invocation had opened its own client, a hundred-odd warm instances against a `max_connections` of 100. The code was fine. The boundary between the code and the database was never anybody's job, because nothing in your hiring process ever asked a question that would have surfaced it.
"Full stack developer" once meant someone who carried a feature from schema to browser without a handoff. It now mostly means a React developer who has written a JOIN. The difference isn't framework count — it's whether they think in seams: the places where two layers meet and lie to each other about state, timing, and failure. Someone who has been paged at those seams writes different code before you ask them to. Below: where the four seams are, how to test for them in ninety minutes instead of a weekend take-home, and what the market costs.
Every CV in the pile says React, Node, Postgres, AWS, Docker, and has said it for six years. The signal is one layer down. Has this person run a migration against a four-million-row table under live traffic — and did they set `lock_timeout` first, so a blocked `ALTER TABLE` fails fast instead of queueing every read behind it and stalling the site for eleven minutes? Can they explain why adding a `NOT NULL` column with a default rewrote the whole table before Postgres 11 and doesn't after? Ask what happens to a background job that crashes after it writes the order row but before it calls Stripe. If they've lived it, they say "outbox" or "idempotency" unprompted.
Our best question isn't trivia: "tell me about a bug that took you more than two days" — then refuse the vague answer. Ask what they ruled out, and who they woke up. Operators light up: the DST bug that double-billed every February, the retry storm where their own clients DDoSed their API, the cache key missing a tenant ID that served Account A's invoices to Account B. Feature-only builders go abstract inside two sentences, because underneath there's no war story, only tutorials. Five minutes, and it sorts the pile better than any algorithm screen.
Database to application is first and most expensive. ORMs make N+1 invisible: a list page renders in 40ms against 50 seeded rows, then fires 900 queries once a real account has relations. `OFFSET 20000` makes Postgres read and discard twenty thousand rows on every request, so deep pages get slower forever until someone switches to keyset pagination on an indexed column. Pooling is its own category: PgBouncer in transaction mode in front of serverless breaks prepared statements unless you disable them — `?pgbouncer=true` for Prisma, unnamed statements for node-postgres. Candidates who've hit this ask about your deployment target before writing a data layer.
Application to browser is auth and cache. Ask where the session token lives; "localStorage" with no pause means one stored XSS — or one compromised build dependency — exfiltrates every live session. The real questions are httpOnly cookies with a `Domain` that covers your subdomains and a `SameSite` value that survives the redirect back from Stripe Checkout, refresh-token rotation that doesn't revoke the whole family and log everyone out when two tabs refresh within the same 200ms, and what the UI does when the access token expires forty minutes into an upload. Cache is the twin failure: a route that reads the logged-in user but gets cached at the CDN, so Account A's dashboard becomes Account B's. Ask what invalidates it, and who is allowed to.
The third seam is your app to everyone else's. Stripe retries a failing webhook for up to three days; delivery is at-least-once and arrival order isn't guaranteed, so any handler that isn't safe to run twice will eventually double-charge someone. Verify the signature, key on the event ID, make the write a unique-constrained upsert. The fourth seam is code to production: migrations with no reverse path, a deploy that drops a column while the previous pods are still writing to it (expand, backfill, contract — three deploys, in that order), and logs that record "payment failed" without the tenant, the record, or the upstream request ID. Anyone who can't answer "how do we roll this back at 2am" is a feature developer with a broader title.
Skip the weekend take-home. Senior people decline them, and the ones who accept optimize for the grader. Hand over a small running app instead — an API, a seeded database, a thin UI — with three planted bugs: an N+1 that only bites past 200,000 rows, a lost update where two concurrent writes clobber each other because nobody reached for `SELECT ... FOR UPDATE`, and a search endpoint missing an index so it table-scans at 1.8 seconds. Ninety minutes, paired, screen shared, with whatever AI tooling they use at work. You're hiring the person and their tools together.
Fixing all three isn't the point — two is a fine score. Watch the order of operations. Do they reproduce before they theorize? Do they turn on query logging, or start rewriting code on instinct? When they find the 1.8-second endpoint, do they add the index or hide it behind a cache, and can they defend the choice? Then close with: what would you add so this fails loudly next time? "A test" is average. "A slow-query alert at 200ms and a realistic row-count fixture in CI" is the hire. That gap — fixing bugs versus lowering the bug rate — compounds across a year of roadmap.
In 2026 a senior full-stack contractor bills roughly $90–160/hour in the US or UK, or $150k–220k salaried before benefits and payroll tax add another 25–30%. Eastern Europe runs $45–80. India and Pakistan run $25–60 for genuinely senior people, and far less from volume shops that staff you with three juniors and a coordinator who forwards messages. After years of hiring across all of these: variance inside one market dwarfs variance between markets. A strong engineer in Lahore or Bangalore beats a mediocre one in San Francisco at a third of the price, and every dollar saved moves the screening burden onto you.
What an agency sells isn't cheaper hours, it's bus factor. A solo hire is a bus factor of one: the Friday they take a better offer, your migration order, deploy script, and the reason the queue has a 30-second visibility timeout walk out with them. A working partner keeps two people fluent in the codebase, reviews each other, and writes the runbook because they're the ones carrying the pager. Hiring solo, buy that insurance yourself — architecture decisions written down with dates and tradeoffs, and an independent reviewer paid to read the first month of commits.
Point the first two weeks at one thin slice shipped end to end: one endpoint, one screen, one migration, live behind a flag. That tells you more than four interviews. Did the migration ship with a reversal, or is it a one-way door? Is there a request ID threaded from browser to log line, so the next failure is one grep? Did the why land in the PR description or only in the code? Did they ask how long a restore from backup actually takes — the restore, not the schedule — and who gets paged when the queue backs up?
Yes to most of that, and you hired a full-stack developer. Beautiful frontend and silence everywhere else, and you hired a strong frontend developer who needs someone covering the seams — a fine outcome if you plan for it in week two instead of discovering it during your first outage. Hire for the boundaries. That's where production breaks.
A software studio that ships and maintains its own products — KeepChats, Gwora and MoveProof — and builds the same way for clients. Founded and led by codewithumar.
Talk to the studio →We build software worth keeping — for clients, and for ourselves.
Founded & led by codewithumar