cswork / libraryOpen practice workspace

Interview guides · Cartesia

Cartesia Software Engineer Interview Guide

Cartesia Software Engineer interview guide: the three reported rounds, reported coding, database and design questions, a 7-day plan and behavioral prep.

The 60-second brief

Candidate reports place the Cartesia Software Engineer role on data infrastructure and the products built on top of it. The listed work includes data processing, system architecture and integrating new technologies, alongside code reviews, debugging and performance work, and design input on systems that need to scale. Reports also mention regular contact with product managers, designers and operations teams. Nothing more specific about the product is reported, so spend your time on the engineering fundamentals the reports describe rather than on guesses about what Cartesia ships.

This guide is for engineers preparing for the Cartesia Software Engineer loop. It covers the three reported rounds (Initial Phone Screen, Technical Interviews, Final Conversation), every question candidates report across technical knowledge, problem solving, coding, system design and behavioral topics, and a seven-day plan. The stack candidates describe for the role includes Python, Java and JavaScript, PostgreSQL and MongoDB, React or Angular on the front end, Git, and optionally AWS or Azure and CI/CD.

Candidates report three rounds over roughly three to five weeks: an Initial Phone Screen, a set of Technical Interviews, and a Final Conversation with senior leadership.

Focus areas

  • React
  • Data Infrastructure
  • Databases

Overview

The reported questions fall into five groups. Technical knowledge questions ask you to explain concepts: SQL versus NoSQL databases, RESTful APIs, Java garbage collection, design patterns and web application security. Problem-solving questions cover optimizing a slow database query, designing for high concurrency and diagnosing a performance issue in a web application. The coding questions are reversing a linked list, implementing binary search and the two-sum problem, and candidates say coding is typically done in a live environment. The design questions are a URL shortening service and a scalable chat application.

That mix rewards breadth with depth in the middle. Every concept question has a version that sounds like a definition and a version that shows you have used the thing: for SQL versus NoSQL, tie the choice to access patterns, consistency and schema change, and name a PostgreSQL and a MongoDB example from your own work. For performance questions, rehearse a fixed sequence (measure, locate the bottleneck, change one thing, measure again) so you are never guessing aloud. The three coding problems are short, so the bar is clean, correct code in your chosen language with edge cases handled and complexity stated.

The topic breakdown candidates see lists React, Data Infrastructure, Databases, CSS and Tailwind CSS, and the requirements mention React or Angular as a plus. If your background is back end, be ready to say how you would reason about a browser-side performance problem even if you do not write much front-end code. If it is front end, expect the database and API questions to matter just as much.

The final stage is reported as a conversation with senior leadership about collaboration and cultural alignment, and the reported behavioral questions are about resolving a team conflict, prioritizing across projects and leading a successful project. Prepare two or three real stories that can answer all of them, with your own decisions and a measured result in each.

The Cartesia interview process

Candidates describe three stages, in this order. The stages are summarised from candidate reports, not from a published process.

Initial Phone Screen

Candidates describe the Initial Phone Screen as a preliminary call about your background and how well it fits the role. No specific questions are reported for it, so treat it as the place to present your experience clearly and to learn what the remaining stages cover. Have a short walk through your last two or three projects ready, with the stack you used, since the role lists Python, Java or JavaScript, web frameworks and databases.

What to demonstrate

  • Whether your background lines up with the role's listed requirements: a programming language, data structures and algorithms, web frameworks and databases
  • How clearly you describe the projects you delivered and your own part in them
  • Your reasons for wanting this role

How to prepare

  • Write a two-minute summary of your career that names the languages, databases and frameworks you used, picking out the ones the role lists
  • Pick one project where you touched data infrastructure or a database and be ready to give its scale, your decisions and the result
  • Prepare questions about the technical stage, such as what languages are allowed in the coding questions and whether the format is live
  • Keep your availability and logistics answers ready so the call stays on your experience

Technical Interviews

The Technical Interviews are reported as several interviews on technical expertise and problem solving. Candidates report concept questions (SQL versus NoSQL, RESTful APIs, Java garbage collection, design patterns, web security), problem-solving questions (slow query, high concurrency, web performance diagnosis), coding problems typically in a live environment (reverse a linked list, binary search, two-sum) and design questions (a URL shortener, a scalable chat application). Which of these appear in which interview is not reported, so prepare every type.

What to demonstrate

  • Working code under live conditions: correct, tested against edge cases, with complexity stated
  • Command of data structures and algorithms plus web, database and API fundamentals
  • The way you break a vague problem such as a performance issue into steps and narrate it
  • Design reasoning for scalable systems: components, data model, bottlenecks and trade-offs

How to prepare

  • Write the linked-list reversal, binary search and two-sum solutions from scratch in your preferred language until they come out without a bug on the first run
  • Prepare a spoken comparison of SQL and NoSQL that uses PostgreSQL and MongoDB as concrete examples
  • Rehearse the sequence for diagnosing a slow query and a slow web page, and a design outline for a URL shortener and a chat application
  • Be able to explain generational garbage collection in Java, REST constraints and two design patterns you have actually used

Final Conversation

The Final Conversation is reported as a discussion with senior leadership that looks at cultural alignment and collaboration. The reported behavioral questions are about resolving a team conflict, prioritizing across several projects and giving an example of a successful project you led. Treat it as a story round: pick real examples where you made a decision, worked with other people and can state the result.

What to demonstrate

  • How you work with colleagues and handle disagreement
  • How you decide what comes first when several things compete for your time
  • Whether you can describe the projects you led, including your own role and outcome

How to prepare

  • Write three stories in situation, action, result form: a conflict, a prioritization call and a project you led
  • Check every story for first-person singular actions, so your own contribution is clear
  • Have one number or concrete outcome ready for each story
  • Prepare questions for a senior leader about how engineering teams work with product and operations

Where candidates lose points

Answering SQL versus NoSQL with two lists of definitions

Anchor the comparison to a workload. Say when you would pick PostgreSQL (relational integrity, joins, transactions) and when MongoDB (document-shaped data, flexible schema, horizontal scaling), and name the trade-off you accept in each case.

Optimizing a slow query by guessing at an index

Start from the query plan. Read the scan types and row estimates, find the step that costs the most, check that the index matches the filter and sort columns, and confirm the change with the plan again.

Shipping the linked-list, binary search or two-sum code without testing the edge cases

After writing, run an empty list, a single node, a target outside the array, duplicates and a pair that would reuse one element. Say the time and space complexity aloud.

Starting the URL shortener or chat design by naming technologies

Begin with requirements and rough load, then the read and write paths, the data model and how ids or messages are generated, and only then pick storage and caching, naming what breaks first at ten times the traffic.

Giving behavioral answers in the plural, so the senior conversation never learns what you did

For every story, write down the three decisions that were yours, and tell the story in first person singular with a measured result.

Questions & practice

Describe how garbage collection works in Java.

Medium · Technical / Domain Questions

Approach

  1. Start from reachability. Objects reachable from GC roots (local variables on thread stacks, static fields, JNI references) are live and everything else can be reclaimed. Java traces from those roots and does not count references, so unreachable cycles get collected.
  2. Explain the generational heap. Most objects die young, so the young generation (Eden plus two survivor spaces) is collected often by copying the live objects. Objects that survive enough minor collections are promoted to the old generation, which is collected less often with mark-sweep-compact.
  3. Name the collectors and their trade-offs. Serial is single-threaded. Parallel maximises throughput. G1 has been the default since JDK 9: it is region-based and takes a pause goal through -XX:MaxGCPauseMillis. ZGC and Shenandoah do most of their work concurrently to keep pauses short. Explain what a stop-the-world pause means for request latency.
  4. Say why leaks still happen: references kept by accident in static collections, caches with no eviction, listeners that are never removed, or ThreadLocals on pooled threads. Also cover the limits: System.gc() is only a hint and finalize() is deprecated.
  5. Give a diagnosis routine: enable GC logs (-Xlog:gc* on JDK 9+), capture a heap dump with jmap or -XX:+HeapDumpOnOutOfMemoryError, find the dominating retainers in a tool such as Eclipse MAT, and only then tune -Xms/-Xmx or the collector.

Follow-up

  • A service has long pauses every few minutes. How would you confirm old-generation pressure is the cause, and what would you change?
  • What is the difference between weak, soft and phantom references, and when is a WeakHashMap appropriate?
  • If the collector frees unreachable objects, how can a Java service still run out of memory?

Write a function to reverse a linked list.

Medium · Coding / Algorithms

Approach

  1. Use the iterative three-pointer reversal. Start with prev = null and curr = head. Then loop: save next = curr.next, set curr.next = prev, advance prev = curr and curr = next. Return prev as the new head. This is O(n) time and O(1) extra space.
  2. Handle the edge cases out loud: an empty list returns null, a single node returns itself, and two nodes is the smallest case that tests the pointer swap. Confirm the old head's next ends up null so the result has no cycle.
  3. Give the recursive version as an alternative. Reverse the rest, then set head.next.next = head and head.next = null, and return the new head from the deepest call. It is O(n) time but also O(n) call-stack space, so a long list can overflow the stack (CPython's default recursion limit is 1000).
  4. Test by printing the values of the reversed list for lengths 0, 1, 2 and 5. Note that a doubly linked list only needs prev and next swapped on each node.

Follow-up

  • Reverse only the nodes between positions m and n in a single pass.
  • Reverse the list in groups of k nodes, leaving any final partial group as it is.
  • Check whether a linked list is a palindrome in O(1) extra space.

Implement a binary search algorithm in your preferred language.

Medium · Coding / Algorithms

Approach

  1. State the precondition: the array is sorted, or more generally the predicate is monotonic. Set lo = 0 and hi = n - 1. While lo <= hi, compute mid = lo + (hi - lo) / 2, return mid on a match, and otherwise set lo = mid + 1 or hi = mid - 1. Return -1 when the loop ends. This is O(log n) time and O(1) space.
  2. Explain the midpoint formula: in Java or C++, (lo + hi) / 2 can overflow int on very large arrays, while lo + (hi - lo) / 2 cannot. Python integers have arbitrary precision, so the issue does not arise there.
  3. Know the half-open lower-bound version. Set lo = 0 and hi = n, and while lo < hi: if a[mid] < target then lo = mid + 1, otherwise hi = mid. It returns the first index whose value is >= target, which handles duplicates and gives the insertion point. Setting lo = mid in this loop, with mid rounded down, can loop forever.
  4. Test the edge cases: an empty array, one element, a target below the minimum or above the maximum, and runs of duplicates. Know the library behaviour: Java's Arrays.binarySearch returns -(insertion point) - 1 when the value is absent and does not say which duplicate it finds, and Python's bisect_left and bisect_right return the boundaries.
  5. Extend the idea to binary search on the answer: integer square root, or the minimum capacity to ship packages within D days, where you search the answer space with a monotonic feasibility check.

Follow-up

  • Find the first and last positions of a target in a sorted array that contains duplicates.
  • Search for a target in a sorted array that has been rotated at an unknown pivot.
  • How would you search a sorted sequence whose length you do not know?

How would you approach solving the "two-sum" problem?

Medium · Coding / Algorithms

Approach

  1. Clarify the problem first. Should it return indices or values? Is there exactly one answer? Can one element be used twice (normally not)? Can the input contain duplicates or negatives, and is it sorted?
  2. Name the brute force: check every pair in O(n^2) time and O(1) space.
  3. Give the one-pass hash map. For each index i with value x, if target - x is already in the map, return [map[target - x], i]; otherwise store map[x] = i. Checking before inserting stops an element pairing with itself and still handles [3, 3] with target 6. This is O(n) expected time and O(n) space.
  4. If the input is sorted, or values are enough, use two pointers from both ends: move the left pointer up when the sum is too small and the right pointer down when it is too large. That is O(n) on sorted input, or O(n log n) if you sort first, and to keep original indices you sort (value, index) pairs.
  5. Mention the common variants: all unique pairs (skip repeated values while moving the pointers), 3Sum in O(n^2) by fixing one element and running two pointers, and a streaming add/find structure, where you choose which operation gets the O(1) cost.

Follow-up

  • Return every unique pair of values that sums to the target.
  • Extend the problem to three numbers that sum to zero. What is the complexity?
  • The input is already sorted and memory is tight. Which approach do you use and why?

What are the differences between SQL and NoSQL databases?

Medium · Technical / Domain Questions

Approach

  1. Contrast the data models first: relational engines such as PostgreSQL store rows in tables with a declared schema and join them at query time, while NoSQL covers document (MongoDB), key-value, wide-column and graph stores, each shaped around a known access pattern.
  2. Compare guarantees: relational databases give multi-row ACID transactions and constraints (foreign keys, unique). Many NoSQL stores scope atomicity to one key or document and offer tunable or eventual consistency. MongoDB has supported multi-document transactions since 4.0, so avoid absolute claims.
  3. Compare scaling: a relational database usually scales up and adds read replicas, and sharding it is hard because cross-shard joins and transactions are expensive. Most NoSQL stores partition by key from day one, which makes any query that does not use the partition key costly.
  4. Compare querying: SQL supports ad hoc filters, joins and aggregation. In a NoSQL store you model the data around the queries you already know, often denormalising and duplicating data, and every new access pattern can mean a new table or index.
  5. Close with a concrete choice: orders and payments that need integrity go in PostgreSQL. A high-write event log or session store keyed by id suits a key-value or wide-column store. A PostgreSQL JSONB column covers semi-structured fields without adding a second database.

Follow-up

  • How would you model a user's orders in a document store, and what breaks when you later need every order containing a given product?
  • Under eventual consistency, what does a user see when they read right after writing, and how would you guarantee read-your-writes?
  • When would you keep PostgreSQL with a JSONB column instead of adding MongoDB?

How would you approach optimizing a slow database query?

Medium · Problem-Solving / Case Studies

Approach

  1. Measure before changing anything. Get the exact statement and its parameters from the slow-query log or pg_stat_statements, then run EXPLAIN (ANALYZE, BUFFERS) in PostgreSQL to see actual versus estimated rows, the scan and join types, and where the time goes.
  2. Read the plan for the cause. A sequential scan with a selective filter on a large table points to a missing index. Estimates far from the actual row counts point to stale statistics (run ANALYZE). A nested loop over many outer rows points to a missing index on the join key.
  3. Design the index to fit the query. In a composite index, put the equality columns first and the range or ORDER BY column last, and add INCLUDE columns when an index-only scan is possible. Know what makes an index unusable: a function on the column (lower(email) needs an expression index), LIKE with a leading wildcard, or an implicit type cast. Every index also slows writes.
  4. Rewrite the query where needed. Select only the columns you use, replace large OFFSET pagination with keyset pagination (WHERE id > last_id ORDER BY id LIMIT n), remove N+1 query patterns coming from the ORM, filter before joining or aggregating, and turn correlated subqueries into joins.
  5. Look beyond the statement: lock waits, connection-pool exhaustion and table bloat (VACUUM). Then consider caching, a materialised view or a read replica. Confirm the fix with a second EXPLAIN ANALYZE and before-and-after timings.

Follow-up

  • You added an index and the planner still does not use it. What are the possible reasons?
  • How would you speed up a page that runs OFFSET 100000 LIMIT 20?
  • The query is fast when run alone but slow in production at peak. What do you check next?

Explain the concept of RESTful APIs.

Medium · Technical / Domain Questions

Approach

  1. Define the core constraints. Resources are identified by URIs that name nouns (/users/42/orders), clients act on them with standard HTTP methods, and the server keeps no client session state between requests. Responses declare whether they can be cached.
  2. Get method semantics exactly right. GET is safe and idempotent. PUT and DELETE are idempotent. POST is not idempotent. PATCH is not guaranteed to be idempotent. Then explain why this matters for retries and caches.
  3. Use status codes precisely: 201 with a Location header for a create, 204 for an empty success, 400 for bad input, 401 when the client is not authenticated versus 403 when it is not allowed, 404, 409 for a conflict, 429 for rate limiting and 5xx for server faults. Return one consistent error body.
  4. Cover practical design: cursor or offset pagination, filtering and sorting through query parameters, versioning in the path or a header, ETag with If-None-Match returning 304, and an Idempotency-Key header so retried POSTs are safe.
  5. Name the trade-offs against alternatives. Fixed REST endpoints can over-fetch or under-fetch, GraphQL lets the client pick fields, and gRPC suits typed service-to-service calls. Say that HATEOAS is the formal constraint most real APIs skip.

Follow-up

  • How would you make a POST that charges a card safe for the client to retry after a timeout?
  • Would you use cursor or offset pagination for a feed that changes while the client pages through it, and why?
  • When would you pick GraphQL or gRPC over REST for a new service?

What is the purpose of using design patterns in software development?

Medium · Technical / Domain Questions

Approach

  1. Define the purpose. Patterns are named, reusable solutions to recurring design problems, and they give a team a shared vocabulary. Group the classic catalogue: creational (Factory Method, Builder, Singleton), structural (Adapter, Decorator, Facade) and behavioural (Strategy, Observer, Command).
  2. Tie every pattern you name to the problem it removes. Strategy replaces a growing if/else over interchangeable algorithms. Adapter wraps a third-party client behind your own interface. Observer decouples event producers from consumers. Builder handles objects with many optional fields.
  3. Connect patterns to principles: program to an interface, prefer composition over inheritance, and keep code open for extension but closed for modification. Show how this makes code testable, for example by injecting a Strategy and passing a fake in tests.
  4. State the costs. Applying a pattern too early adds indirection. Singleton hides global state and makes tests order-dependent. In a language with first-class functions, a Strategy can often be a plain lambda.
  5. End with one example from your own code: the pattern, what the code looked like before, and what changed afterwards (fewer branches, easier tests, a vendor swapped without touching callers).

Follow-up

  • Why is Singleton often called an anti-pattern, and what would you use instead?
  • How does Decorator compare with subclassing when you add retries or caching to an HTTP client?
  • Where would you apply Strategy in a notification or pricing module, and how would you test it?

How do you ensure the security of a web application?

Medium · Technical / Domain Questions

Approach

  1. Organise the answer by attack class, using the OWASP Top 10 as a frame. For injection, use parameterised queries with bind parameters and never build SQL from strings. For XSS, encode output for its context and add a Content-Security-Policy; React escapes text by default, but dangerouslySetInnerHTML bypasses that. For CSRF, use SameSite cookies plus CSRF tokens on state-changing requests.
  2. Cover authentication. Hash passwords with bcrypt, scrypt or Argon2, never a bare fast hash. Mark session cookies HttpOnly, Secure and SameSite. Add MFA, rate-limit login attempts, and keep tokens short-lived with refresh rotation.
  3. Cover authorisation, which is where many real breaches happen. Check ownership on every object access on the server (one user requesting /orders/123 that belongs to someone else), and give database and cloud roles least privilege.
  4. Cover transport and configuration: TLS everywhere with HSTS, secrets kept in a secret manager rather than the repo, a CORS allowlist instead of a wildcard, security headers, and dependency scanning with prompt patching.
  5. Cover process: threat-model new features, validate input at trust boundaries, log and alert on authentication and authorisation failures, and run static and dynamic scans in CI.

Follow-up

  • Walk through how a stored XSS attack works and the two defences that stop it.
  • What are the trade-offs between keeping a JWT in localStorage and keeping it in an HttpOnly cookie?
  • How would you find and fix an endpoint that lets one user read another user's records?

Given a set of requirements, design a system that can handle high concurrency.

Medium · Problem-Solving / Case Studies

Approach

  1. Turn the requirements into numbers and invariants: peak requests per second, read/write ratio, latency target, and the shared state that must never go wrong (for example, never sell more units than are in stock).
  2. Lay out the baseline. A stateless application tier behind a load balancer scales horizontally. Add connection pooling to the database, a cache such as Redis for hot reads, and a queue (Kafka, SQS) that absorbs bursts and moves slow work off the request path.
  3. Handle contention on shared state explicitly. Options are optimistic concurrency with a version column (UPDATE ... WHERE id = ? AND version = ?), short pessimistic locks with SELECT ... FOR UPDATE, or atomic conditional updates (UPDATE stock SET qty = qty - 1 WHERE qty > 0) or Redis DECR. Use idempotency keys so client retries do not apply twice.
  4. Protect the system under overload with token-bucket rate limiting, bounded thread and connection pools, timeouts, retries with jittered backoff, circuit breakers and backpressure on queues, and say which features you degrade first.
  5. Scale the data layer. Read replicas trade freshness for read capacity, and sharding needs a key that spreads load evenly. Validate with a load test while watching p99 latency, error rate and queue depth.

Follow-up

  • Two users try to buy the last unit at the same moment. Walk through how your design prevents overselling.
  • One key receives most of the traffic. How do you handle that hot spot?
  • What happens to the queue and its consumers when a downstream dependency slows down?

How would you diagnose a performance issue in a web application?

Medium · Problem-Solving / Case Studies

Approach

  1. Scope the problem first. Ask which pages or endpoints are slow, for all users or a subset, and since when, and line that up with deploys, traffic and data growth. Pick the metric that matters: p95/p99 rather than the average, time to first byte, or Core Web Vitals such as LCP and INP.
  2. Split frontend from backend. A high time to first byte means the server. A fast time to first byte with a slow LCP points at the client: large bundles, render-blocking scripts or CSS, unoptimised images, request waterfalls, or expensive React re-renders (use the browser Performance panel, Lighthouse and the React Profiler).
  3. On the backend, use tracing or APM to find which span dominates. The usual suspects are database queries (N+1 patterns, missing indexes, confirmed with EXPLAIN), slow external calls, lock waits, CPU hot paths (a profiler flame graph), GC pauses, exhausted connection pools and a falling cache hit rate.
  4. Work from hypotheses. Reproduce under a load test, change one variable at a time, and compare the same percentile before and after so you know the fix worked.
  5. Match each fix to its cause and name its cost: a CDN and compression, code splitting and lazy loading, pagination, an index, caching (and its invalidation), or moving work onto a queue. Then add an alert so the regression is caught next time.

Follow-up

  • After a deploy, p50 latency is flat but p99 has doubled. Where do you look?
  • How would you spot an N+1 query problem from traces or logs?
  • A React page lags on every keystroke in a search box. How do you diagnose and fix it?

Design a URL shortening service. What components would you include?

Medium · System Design / Architecture

Approach

  1. Pin down the requirements: create a short link, redirect, optional custom alias and expiry, and click analytics. Redirects far outnumber creates, so the read path gets the latency budget. State your traffic and storage assumptions explicitly before sizing anything.
  2. Define the API. POST /urls takes long_url plus an optional alias and expires_at and returns a code. GET /{code} redirects. A 301 is cached by browsers, which cuts load but hides repeat clicks from analytics, while a 302 sends every click through the service.
  3. Choose how codes are generated and say what each option costs. Base62-encoding a unique numeric id, with id ranges handed out to each server, never collides. Hashing the long URL and truncating it needs a collision check. Random codes need a uniqueness check on insert. Seven base62 characters give 62^7, about 3.5 trillion codes.
  4. Storage is a code-to-URL lookup. A relational table with a unique index on code works at moderate scale, and a key-value store partitioned by code scales further. Put hot codes in Redis or at a CDN, and publish click events to a queue instead of writing them on the redirect path.
  5. Cover the edge cases: the same long URL submitted twice (dedupe or issue a new code), malicious destinations, rate limiting on creation, alias conflicts, and expiry handled through a TTL or a background cleanup job.

Follow-up

  • How do you guarantee that two servers never issue the same short code?
  • How would you add per-link click analytics without slowing the redirect?
  • How do you handle expired links, and would you ever reuse their codes?

How would you architect a scalable chat application?

Medium · System Design / Architecture

Approach

  1. Scope the features: one-to-one and group chat, message history, delivery and read receipts, online presence, and push notifications for offline users. State the ordering guarantee you need: order within a conversation, not a global order.
  2. Connection layer: clients hold persistent WebSocket connections to gateway servers, which makes those servers stateful. A registry such as Redis maps each user to their current gateway, and the load balancer must support long-lived connections. Long polling is the fallback.
  3. Message flow: the client sends a message with a client-generated id so retries can be deduplicated. The chat service assigns a per-conversation sequence number, persists the message, and then fans it out through pub/sub or a queue to the recipients' gateways. Offline users get a push notification and, on reconnect, fetch everything after their last seen sequence number.
  4. Storage: partition messages by conversation_id and cluster them by sequence number. A wide-column store such as Cassandra fits this append-heavy workload that reads ranges per conversation. Keep user and group metadata in a separate store, and page through history with a cursor.
  5. Trade-offs: in large groups, writing a copy to every member's inbox gets expensive, so very large groups read from the conversation instead. Presence uses heartbeats with a TTL, and status changes are batched or throttled so they do not flood every contact.

Follow-up

  • Two members of a group send a message at the same moment. How do you keep the order consistent for everyone?
  • A gateway server crashes while holding many live connections. What happens to in-flight messages, and how do clients recover?
  • How would you add search across a user's message history?

Listing latency scales with page size, not with filters

Easy · n+1 · latency · query batching

The tenant listing endpoint reads resource filtered by tenant_id and status, ordered by updated_at DESC, and returns each row plus the owner's display name from app_user and the actor of that resource's latest resource_revision. p99 is 55 ms at 10 rows per page and 1.4 s at 200. Database telemetry shows 401 statements per request, each under 1 ms, and nothing in the slow-query log. Diagnose the cause and give the fix, stating the statement count per request and the p99 you expect afterwards.

Approach

  1. Read the counters before forming a theory. 401 statements for 200 rows is one driver query plus two per row, and sub-millisecond execution with an empty slow-query log rules out a bad plan. The time is round trips, which is why it is invisible in every per-query metric and scales with rows returned rather than with filter selectivity.
  2. Name the two per-row statements from their normalised text: a single-row app_user lookup by user_id, and a resource_revision lookup by resource_id ordered by version DESC LIMIT 1. Confirm by dropping those two response fields and watching the statement count fall to one. That locates the calls in the serialisation layer, not the repository.
  3. Check that the arithmetic accounts for the whole gap. Measure one round trip to the replica in isolation; 400 trips at roughly 3 ms of network plus 0.2 ms of execution is about 1.3 s on top of a 55 ms baseline, which matches. If the multiplication had fallen short, the N+1 would only be part of the story and you would keep looking.
  4. Batch both lookups. Collect owner_user_ids and resource_ids from the driver query, then issue WHERE tenant_id = $1 AND user_id = ANY($2) for the users, and PostgreSQL's SELECT DISTINCT ON (resource_id) ... WHERE resource_id = ANY($2) ORDER BY resource_id, version DESC for the latest revision, which the UNIQUE (resource_id, version) index serves directly. On an engine without DISTINCT ON, use a lateral join or a row_number window. Three statements per request at any page size.

Follow-up

  • The page size is capped at 200 today. What breaks first if it is raised to 2,000, and is it still this bug?
  • How do you stop the next N+1 from reaching production, given that no individual query is slow and the endpoint's tests pass?

Suggested practice checklist

The plan starts with the reported loop and stack, then works through coding, databases, web fundamentals, performance and concurrency, system design and finally the behavioral stories for the Final Conversation.

Day 1 — Map the loop and the stack

  • Write the three reported rounds and list the five reported question groups under them, marking the group you are weakest in
  • Choose the language you will use for live coding (Python, Java or JavaScript) and write one small function in it with no editor help
  • Write your two-minute background summary that names the languages, databases and frameworks you have used

Deliverable: A one-page loop map with your weakest group marked, plus the language choice and the background summary.

Day 2 — Core coding problems

  • Write the iterative linked-list reversal with three pointers and test an empty list, one node and many nodes
  • Write binary search with an inclusive-low, inclusive-high loop, avoiding the off-by-one and overflow of the midpoint, and test a missing target
  • Solve two-sum with a hash map storing seen values, then explain why sorting plus two pointers is the alternative if you must not use extra space

Deliverable: Three tested solutions with complexity written beside each and a list of the edge cases you ran.

Day 3 — Databases and query tuning

  • Write a two-minute spoken answer on SQL versus NoSQL, using PostgreSQL and MongoDB as examples and naming consistency and schema trade-offs
  • Take a slow PostgreSQL query, read the EXPLAIN output, add or change an index and compare the plans
  • Write the rule you would use to decide between a composite index and two single-column indexes

Deliverable: A spoken SQL versus NoSQL answer plus a before and after query plan with a note on what changed.

Day 4 — Web and language fundamentals

  • Explain RESTful APIs aloud: resources, verbs, status codes, statelessness, idempotency of PUT and DELETE, and pagination
  • Explain Java garbage collection: reachability from roots, generational heap, young and old collections and what causes long pauses
  • Write short answers on what design patterns are for, using two you have applied, and a security checklist covering injection, XSS, CSRF, authentication, authorization and secrets

Deliverable: Four written answers that you can each say aloud without notes.

Day 5 — Performance and concurrency

  • Write a diagnosis sequence for a slow web application: reproduce, check client and network time, server time, database time, then change one thing and measure
  • Outline a high-concurrency design: stateless service tier, connection pooling, caching, queueing writes and back-pressure

Deliverable: A written diagnosis checklist, a solved debugging exercise and a one-page high-concurrency outline.

Day 6 — System design

  • Design a URL shortener: id generation (counter or hashed key), a key-value store, redirect path, caching and a plan for collisions and expiry
  • Design a scalable chat application: connections held by gateways, a message store partitioned by conversation, delivery and read state, and ordering within a conversation
  • Add rough numbers to each design and name what breaks first when traffic grows ten times

Deliverable: Two one-page designs with component diagrams, data models and a bottleneck list.

Day 7 — Behavioral stories and a full rehearsal

  • Write three stories (a team conflict, a prioritization decision, a project you led) in situation, action, result form with a measured result in each
  • Say each story aloud and cut anything that does not show your own decision
  • Do a full rehearsal: one coding problem, one design outline and one story, in that order

Deliverable: Three finished stories and one recorded full rehearsal with notes on what to fix.

Stories for the Final Conversation

The Final Conversation is reported as a talk with senior leadership about collaboration and cultural alignment, and the three reported questions are about conflict, prioritization and leading a project. These prompts reward specific stories in first person singular: what you decided, how you dealt with other people and what changed as a result.

  1. Tell me about a time you changed your mind after a code review or a design discussion.
  2. Describe a time you worked with a product manager or designer who wanted something different from you.

Describe a time when you had to resolve a conflict within your team.

Medium · Behavioral / Leadership

Approach

  1. Choose a conflict about a real technical or process decision, such as an API design, a review disagreement or a scope trade-off, where you were a party to it rather than an observer.
  2. Spend the first part on the other person's position in their terms, then on what you did to understand it: a one-to-one conversation, a short prototype or a benchmark that turned opinion into evidence.
  3. Show the resolution mechanism, whether that was a data-based choice, a compromise or an agreed decision-maker, and say what you personally gave up or changed.
  4. Finish with the result and the working relationship afterwards, for example that the same person reviewed your next change without friction.
  5. The mistake that sinks it is a story where the other person is simply wrong, or one where you escalated to a manager at once without trying to resolve it directly.

Follow-up

  • What would the other person say about how you handled it?
  • What would you have done if there was no data that could settle it?
  • Did you ever need to escalate, and what made you decide?

How do you prioritize tasks when working on multiple projects?

Medium · Behavioral / Leadership

Approach

  1. Open with the method, then prove it with a real case: list what is competing, estimate the impact of each item, the deadline and the cost of delay, and check dependencies on other people.
  2. Use a specific episode with two or three real commitments, such as a production bug, a feature deadline and a review backlog, and say which you did first and why.
  3. Name what you deferred or declined and how you told the affected person, since the message to stakeholders is the part most answers leave out.
  4. Show how you re-planned when something changed: an urgent incident arriving mid-week, or an estimate that turned out wrong.
  5. The mistake that sinks it is a generic answer such as keeping a task list and working hardest first, with no decision, trade-off or consequence in it.

Follow-up

  • What do you do when two stakeholders both say their request is the urgent one?
  • Tell me about something you decided not to do and how it landed.
  • How do you handle a priority change halfway through a piece of work?

Can you give an example of a successful project you led?

Medium · Behavioral / Leadership

Approach

  1. Pick a project where you were the lead in a real sense: you set the scope, broke down the work, made the design calls and were accountable for the delivery, even if you had no formal title.
  2. Give the context in two sentences, then say what you decided: the architecture, the sequencing, who did what, and the main risk you identified and handled.
  3. Define success with a measurable outcome, for example a latency drop, a migration finished with no downtime or a feature adopted, and say how you measured it.
  4. Describe how you led other people: how you split the work, handled a blocker or a disagreement, and kept the team informed.
  5. The mistake that sinks it is describing what the team did throughout, so your own contribution is unclear, or claiming success without any measurement.

Follow-up

  • What was the biggest risk and how did you handle it?
  • What would you change if you ran the project again?
  • How did you handle a teammate who disagreed with your plan or fell behind?