cswork / libraryOpen practice workspace

Interview guides · Campfire

Campfire Software Engineer Interview Guide

Campfire Software Engineer interview guide: reported rounds, coding, system design and behavioral questions, answer outlines and a 7-day prep plan.

The 60-second brief

Candidate write-ups describe Campfire as a company whose products are a platform that users engage with, and they describe the engineering work as spanning backend services and user interfaces, with real-time data processing and user-centric design named as areas of work. They report nothing more specific about products, customers or team structure, so this guide does not guess at them. The responsibilities candidates list for the role are building and maintaining software, turning requirements from product managers and designers into technical specifications, reviewing code, debugging, and working with continuous integration and deployment.

This guide is for engineers preparing for the Software Engineer loop at Campfire. Candidates describe requirements that include JavaScript, Python or Java, React or Node.js, SQL or MongoDB, and around three years of experience, with cloud platforms, CI/CD and agile practice as extras. It covers every round candidates name, outlines for the reported behavioral questions, and a plan that also points at the coding, design and debugging questions reported alongside them.

Candidates report four rounds spread over about 3-5 weeks: Initial Screening Call, Technical Evaluations, In-Depth Discussions and On-Site Interviews. The reported questions are a mix of classic coding problems, engineering fundamentals, system design, production debugging and behavioral prompts.

Focus areas

  • Full-Stack Development
  • Software Engineering Fundamentals
  • Technical Screening

Overview

The role candidates describe sits across the stack. Reported day-to-day work includes building and maintaining applications, reading and writing code reviews, tracing bugs in running software, and shipping through CI/CD, alongside product managers and designers. The topics extracted from candidate reports are Full-Stack Development, Software Engineering Fundamentals, Technical Screening, Frontend Development and Backend Development. For preparation, that means breadth: you need fluent basics in every layer rather than deep specialism in one.

The reported questions fall into five groups. Fundamentals: version control, REST versus GraphQL, object-oriented principles, code quality. System design: a URL shortening service, real-time notifications, SQL versus NoSQL, microservices, load balancing. Case studies: debugging in production, designing from a set of requirements, deciding with incomplete information. Coding: reversing a linked list, binary search, the longest substring without repeating characters, anagrams, and discussing time complexity. Behavioral: conflict, prioritisation, influence, motivation and feedback. Candidates also quote merging two sorted arrays and optimizing a slow SQL query as example scenarios.

Because the groups are broad and the coding problems are well-known ones, speed and clarity matter more than novelty. Pick one language from the stack candidates report and write the five coding problems in it until the pointer and index handling is automatic. Prepare two real projects in enough detail to serve several questions: the challenging technical problem, the recent feature and its impact, the real-world problem, and the incomplete-information decision can all come from the same two stories if you know their numbers, trade-offs and mistakes.

The Campfire interview process

Candidates report four rounds over about 3-5 weeks. The round names below are what candidates describe, and the content can differ by team, so confirm the format of each stage with your recruiter.

Initial Screening Call

Candidates describe this first call as a conversation about your background and your fit for the role, and they mention phone interviews with recruiters early in the process. Use it to compress your experience into a clear story and to learn how the later rounds run for your team, since candidates say the format can vary by team.

What to demonstrate

  • How clearly you summarise your background and the projects you have shipped
  • Whether your experience matches the role as it is described to you

How to prepare

  • Write a short career summary that ends on your most full-stack project, naming what you built in the frontend, the backend and the database.
  • Compare your experience with the stack candidates report (JavaScript, Python or Java; React or Node.js; SQL or MongoDB) and be ready to say where you are strong and where you are still learning.
  • Ask what the next stages involve, whether the technical stage is live coding or an assessment, and whether the on-site stage is in person for your team.

Technical Evaluations

Candidates describe technical assessments of engineering skill, with some reports of engineering leads running them, and they say coding on the spot is possible. A stage like this is where the reported coding questions are practised: reversing a linked list, binary search, the longest substring without repeating characters, anagrams and merging two sorted arrays, followed by a discussion of time complexity. Say your approach before you write, then test your code on small inputs.

What to demonstrate

  • Working code that you write and explain aloud
  • Command of algorithms and data structures, including the complexity of your solution
  • Engineering fundamentals of the kind candidates report in the technical question group, such as REST versus GraphQL and object-oriented principles

How to prepare

  • Write the five reported coding problems by hand in one language, each with its brute-force version, its better version and its complexity stated in a sentence.
  • Prepare a spoken comparison of REST and GraphQL (over-fetching, endpoint shape, caching, versioning) and a one-minute explanation of encapsulation, abstraction, inheritance and polymorphism with a concrete example.
  • Practise explaining how you would find and fix a slow SQL query: read the query plan, check the indexes, and look for functions that stop an index from being used.

In-Depth Discussions

Candidates describe discussions with team members aimed at collaboration and cultural fit. The evaluation themes they report are collaboration and communication (cross-functional work, conflict, feedback) and adaptability and learning. Prepare concrete stories in which you made a decision and can say what it cost, rather than general statements about teamwork.

What to demonstrate

  • Collaboration with colleagues across product, design and engineering
  • How you handle disagreement and feedback
  • How you learn new technologies and adapt when requirements change

How to prepare

  • Build a story bank of five or six incidents covering conflict, influence, prioritisation, feedback and learning something new, each with the situation, your decision, the outcome and what you would change.
  • Be ready to discuss code quality and version control as team habits: review practice, branching, testing and how you keep a codebase maintainable.
  • Choose one project whose design trade-offs you can defend, such as the database you picked and why, so a discussion about your past work has depth.

On-Site Interviews

Candidates describe the final stage as case studies and problem-solving exercises, and they associate it with on-site interviews. The reported case-study material includes debugging in production, designing a solution from a set of requirements and deciding with incomplete information. Prepare to think aloud in a repeatable structure so a long problem does not lose its thread.

What to demonstrate

  • Structured reasoning on an open-ended problem
  • Design decisions with their trade-offs stated
  • A methodical approach to diagnosing a fault in a running system

How to prepare

  • Rehearse the reported design prompts aloud: a URL shortening service and a real-time notification system, each with requirements, data model, read and write paths and failure handling.
  • Write a production-debugging sequence you can recite: scope the impact, find what changed, check logs and metrics, form a hypothesis, mitigate first and then fix the cause.
  • Practise starting a design from requirements: list the functional and non-functional needs, state your assumptions, and only then choose components.

Where candidates lose points

Reversing a linked list and losing the rest of the list because the next pointer is overwritten, or crashing on an empty or single-node list

Keep three references (previous, current, next), save current.next before you relink, and walk through an empty list, a one-node list and a two-node list before you say you are done. Mention the recursive version and its stack depth only after the iterative one works.

Writing binary search or the longest-substring window with an off-by-one error or a pointer that moves backwards

State the invariant first (for binary search, the target lies in lo..hi; for the window, the substring between left and right has no repeats). Use mid = lo + (hi - lo) // 2 and, in the window, move left to the larger of its current value and the character's last index plus one. Test an absent target, first and last elements, and a string like abba.

Answering the complexity discussion with a single label and no reasoning, or missing the space cost

Count the loops and the work inside them, say what the dictionary or set costs in memory, and give both time and space. Compare the brute force with the improved version, for example the nested scan against a single pass for the longest substring.

Naming components in a URL shortener or real-time notification design without saying why, or choosing SQL or NoSQL on preference

Start from requirements and access patterns: reads versus writes, how keys are generated and collisions handled, how notifications are pushed to connected clients and what happens when a client is offline. Then give the trade-off for each choice and the first thing that breaks as traffic grows.

Jumping to a fix when asked about a production problem, or telling a team story that says 'we' throughout with no result

For debugging, describe scope, recent changes, logs and metrics, then mitigation before root cause. For behavioral answers, use 'I' for your own decisions, name the outcome with a number where you can, and say what you would do differently.

Questions & practice

Write a function to reverse a linked list.

Medium · Coding / Algorithms

Approach

  1. Iterative three-pointer version: prev = null and curr = head. In a loop, save next = curr.next, set curr.next = prev, then move prev = curr and curr = next. Return prev as the new head. This is O(n) time and O(1) extra space.
  2. Recursive version: reverse the rest of the list, then set head.next.next = head and head.next = null. It is O(n) time but uses O(n) call stack, so a long list can overflow the stack (CPython's default recursion limit is 1000).
  3. Edge cases to state and test: an empty list returns null, a single node returns itself, and a two-node list catches pointer-order bugs. Losing the reference to curr.next before rewiring is the classic mistake.
  4. Dry-run 1 -> 2 -> 3 aloud, showing the pointers after each iteration, before calling it done.
  5. For a doubly linked list, swap each node's prev and next and return the old tail.

Follow-up

  • Reverse only the nodes between positions m and n.
  • Reverse the list in groups of k nodes.
  • What happens if the list contains a cycle, and how would you detect one first?

How would you implement a binary search algorithm?

Medium · Coding / Algorithms

Approach

  1. Precondition: the array is sorted, or more generally the predicate you search on is monotonic. Iterative form: lo = 0 and hi = n - 1; while lo <= hi, set mid = lo + (hi - lo) / 2 and move lo = mid + 1 or hi = mid - 1. This is O(log n) time and O(1) space.
  2. Writing mid = lo + (hi - lo) / 2 avoids integer overflow in fixed-width languages such as Java or C++, where (lo + hi) can overflow on very large indices.
  3. Lower bound (the first index whose value is >= target) uses a half-open range: lo = 0 and hi = n; while lo < hi, if a[mid] < target then lo = mid + 1, else hi = mid. Pick one invariant and keep it, or the loop can stall when lo = mid.
  4. Edge cases: an empty array, a target below the first or above the last element, duplicates (first or last occurrence) and a single element.
  5. Library equivalents: Python's bisect_left and bisect_right return insertion points. Java's Arrays.binarySearch returns -(insertion point) - 1 when the key is absent, and makes no promise about which duplicate it finds.

Follow-up

  • Find the first and last positions of a target in an array with duplicates.
  • Search a rotated sorted array.
  • How would you binary search on the answer, for example the minimum capacity needed to ship packages within D days?

Explain how you would find the longest substring without repeating characters.

Medium · Coding / Algorithms

Approach

  1. Brute force checks every substring for uniqueness: O(n^3), or O(n^2) with a set that grows from each start. Say it, then improve on it.
  2. Sliding window with a map from character to last-seen index. For each right index, if s[right] was seen at an index >= left, move left to that index + 1. Then record the index and update best = max(best, right - left + 1).
  3. Use left = max(left, last[c] + 1). Without the max, left can jump backwards to a stale index outside the current window, which is the most common bug here.
  4. Complexity: O(n) time, because each pointer only moves forward. Space is O(min(n, alphabet size)). For a fixed ASCII alphabet an int array of 128 entries works instead of a hash map.
  5. Edge cases: the empty string gives 0, all identical characters give 1, all distinct characters give n, and so do spaces and digits. Ask whether input is ASCII or Unicode, since that changes the container.

Follow-up

  • Return the substring itself, not just its length.
  • Find the longest substring with at most k distinct characters.
  • How would this work on a stream of characters you cannot store?

Write a function that checks if two strings are anagrams.

Medium · Coding / Algorithms

Approach

  1. Clarify the rules first: case sensitivity, whether spaces and punctuation count, and ASCII vs Unicode. Different lengths after normalization means the answer is false immediately.
  2. Counting approach: increment a count for each character of the first string, decrement for each character of the second, and check that every count is zero. That is O(n) time. Space is O(1) with a fixed 26-entry array for lowercase letters, or O(k) distinct characters with a hash map (Counter in Python).
  3. Sorting approach: sort both strings and compare. It is O(n log n) time and simple, and fine when n is small.
  4. Unicode edge case: the same visible character can be one code point or a base letter plus a combining mark, so normalize (NFC) before counting if the input is user text.
  5. Test with empty strings, equal strings, same letters with different counts ('aab' vs 'abb'), and mixed case.

Follow-up

  • Group a list of words into anagram sets. What do you use as the key?
  • Find every start index in s where an anagram of p begins.
  • How would you compare two very large inputs that do not fit in memory?

Discuss the time complexity of your solution.

Medium · Coding / Algorithms

Approach

  1. State complexity in terms of named inputs (n for array length, m for a second string, k for alphabet size), and give time and space separately. Space includes the recursion stack and any copies, but usually not the output.
  2. Count the dominant work. Nested loops over the same input are O(n^2). A loop that halves the range is O(log n). Two pointers that each move forward at most n times are O(n) overall, not O(n^2), which is why sliding window solutions are linear.
  3. Know common costs: hash map lookups and inserts are O(1) average and O(n) worst case, dynamic array append is O(1) amortized, comparison sorts are O(n log n), and a membership test on a list is O(n).
  4. For recursion, write the recurrence. T(n) = 2T(n/2) + O(n) gives O(n log n) (merge sort), and T(n) = T(n/2) + O(1) gives O(log n) (binary search).
  5. Watch for hidden costs: Python slicing copies (s[1:] is O(n)), and repeated Java String concatenation in a loop is O(n^2) total, so use a StringBuilder.

Follow-up

  • What is the space complexity once you count the call stack?
  • When does the hash map's O(1) average case break down?
  • Can you do better than this bound, and what lower bound applies?

Discuss trade-offs between SQL and NoSQL databases for a project.

Medium · System Design / Architecture

Approach

  1. Frame the choice around access patterns and integrity needs rather than labels. Relational databases give a fixed schema, joins, ad hoc queries, secondary indexes and ACID transactions across tables.
  2. Name the NoSQL families, because they differ: document (MongoDB, one of the databases listed for this role), key-value (Redis, DynamoDB), wide-column (Cassandra) and graph. Each is modelled around known queries, often by denormalizing data.
  3. Scaling and consistency: relational systems scale up and add read replicas, while sharding is usually manual work. Many NoSQL stores partition horizontally by design and offer tunable or eventual consistency. Note that MongoDB has supported multi-document transactions since 4.0, so 'NoSQL has no transactions' is too broad.
  4. Match examples to choices. Payments, orders and inventory need constraints and multi-row transactions, so SQL. High-volume append-only events with known keys suit wide-column stores. Nested content whose shape keeps changing suits a document store, or Postgres JSONB as a middle ground.
  5. Mention costs on both sides: schema migrations in SQL; duplicated data, application-side joins and hard-to-change access patterns in NoSQL.

Follow-up

  • How would you model a many-to-many relationship in a document store?
  • What happens to a query that has to span several shards?
  • How do schema changes differ between the two in practice?

Replace offset paging on the resource feed with keyset

Easy · keyset pagination · composite index · sort order

resource holds resource_id, tenant_id, owner_user_id, title, body_ref, version, status ('draft','active','archived','deleted'), created_at, updated_at, deleted_at, with an index on (tenant_id, status, updated_at DESC, resource_id DESC). The listing endpoint returns active resources for one tenant, newest update first, 50 per page, today with LIMIT 50 OFFSET n. Tenants reach page 400 and rows are created while they read. Write the keyset query, define what the cursor carries and how it is encoded, and say which part of the index each predicate uses. Assume PostgreSQL 16.

Approach

  1. Name the two failures separately. OFFSET 20000 makes the server produce and discard 20,000 rows, so page cost grows with depth rather than with page size. Independently, any write that changes how many rows sort above the offset moves the window between two fetches, and the direction decides which anomaly you get: an insert lands at the head of updated_at DESC and pushes already-returned rows down past the boundary, so they are returned a second time; a delete above the offset, or a row whose updated_at is bumped above the cursor, pulls rows up and one is never returned at all. Nothing in the response reveals either.
  2. Write the seek: WHERE tenant_id = $1 AND status = 'active' AND (updated_at, resource_id) < ($2, $3) ORDER BY updated_at DESC, resource_id DESC LIMIT 50. The row-value comparison is one index range rather than a disjunction, and both columns are NOT NULL, which is what makes that comparison well defined.
  3. Map each predicate onto the index: tenant_id and status are equality on the leading columns, (updated_at, resource_id) is the range, and the ORDER BY matches the index order so no Sort node appears and the scan stops after 50 rows. The DESC in the definition only matters for mixed directions — a plain ascending btree on the same columns is read backwards for this query.
  4. Put both sort columns in the cursor and nothing the client can tamper with into another tenant: base64 of (updated_at, resource_id), validated server-side, with tenant_id taken from the principal.

Follow-up

  • The client asks for 'jump to page 400'. What do you offer instead, and what does the honest version cost?
  • Sort order becomes user-selectable across four columns. How many indexes is that, and which would you refuse to add?

Can you explain the differences between REST and GraphQL?

Medium · Technical / Domain Questions

Approach

  1. Start with the model. REST exposes resources at URLs and uses HTTP verbs and status codes. GraphQL exposes one typed schema, usually behind a single POST endpoint, and the client picks exactly the fields it needs, nested ones included, in one round trip.
  2. Over- and under-fetching: a REST screen that needs a user, their posts and comment counts may take several calls or get bloated payloads. GraphQL removes that, but the server then needs batching (DataLoader-style) to avoid N+1 resolver queries against the database.
  3. Caching: a REST GET is cacheable by URL with Cache-Control and ETag at browsers and CDNs. GraphQL POSTs to one URL are not, so you need persisted queries sent as GET, or a normalized client cache such as Apollo or Relay.
  4. Errors and evolution: GraphQL usually returns HTTP 200 with an errors array and possibly partial data, so clients must check both. REST versions by URL or header. GraphQL adds fields and marks old ones @deprecated instead of versioning.
  5. Close with a choice. REST suits public APIs, simple CRUD, file uploads and edge caching. GraphQL suits several clients (web, mobile) with different data needs, or a layer aggregating several backends. Subscriptions cover real-time updates.

Follow-up

  • How would you stop a client from sending a deeply nested query that overloads the server?
  • How do you fix the N+1 problem in GraphQL resolvers?
  • How would you cache GraphQL responses at a CDN?

What are the principles of object-oriented programming?

Medium · Technical / Domain Questions

Approach

  1. Name the four principles and give a one-line example of each. Encapsulation: state is changed only through methods that keep invariants, like a BankAccount whose balance moves only via deposit and withdraw. Abstraction: callers depend on an interface such as PaymentGateway, not its implementation. Inheritance: a subclass reuses and extends a parent. Polymorphism: one call dispatches to different implementations at runtime.
  2. Separate the kinds of polymorphism: subtype polymorphism (virtual dispatch through an interface), ad hoc polymorphism (method overloading) and parametric polymorphism (generics, as in List<T>).
  3. Explain why to prefer composition over inheritance. Deep hierarchies couple subclasses to parent internals (the fragile base class problem), while composing small objects behind interfaces keeps them swappable and testable.
  4. Connect to SOLID, especially Liskov substitution. A Square that subclasses a mutable Rectangle breaks callers that set the width and height independently.
  5. Note language differences for the listed stack. JavaScript classes are syntax over prototypes. Python relies on duck typing and has only conventional privacy (a leading underscore, plus name mangling for a double underscore). Java enforces access modifiers and interfaces at compile time.

Follow-up

  • When is inheritance the wrong tool, and what would you use instead?
  • What is the difference between an interface and an abstract class, and when do you pick each?
  • Give an example of a Liskov substitution violation you have seen or could imagine.

Describe a challenging technical problem you solved recently.

Medium · Technical / Domain Questions

Approach

  1. Choose a problem where you did the technical work and can give real numbers: the system, its scale and the symptom or constraint, such as p99 latency rising from 200 ms to 2 s, or a job missing its window.
  2. Say why it was hard. Name the obvious fix you tried first, or the constraint that ruled it out, so the listener sees the hard part rather than a routine task.
  3. Walk through your diagnosis as hypotheses and evidence: what you measured (profiles, query plans, traces, logs), what each result ruled out, and the finding that pointed to the cause.
  4. Give the fix and its trade-off, for example adding a composite index that sped up reads at some cost to write throughput, or caching with a stated staleness window. Then give the measured result against the baseline.
  5. End with what you changed so it would not happen again, such as a regression test, an alert or a design note. Avoid stories where a teammate solved it or there is no measurable outcome.

Follow-up

  • Which alternative did you reject, and why?
  • How did you confirm your change caused the improvement rather than something else?
  • What would you do differently if you met the same problem today?

How do you ensure code quality and maintainability?

Medium · Technical / Domain Questions

Approach

  1. Build the answer in layers, from automated to human. Formatters and linters (Prettier and ESLint, Black or Ruff) end style debates. Type checking (TypeScript, mypy) catches whole classes of bugs before runtime.
  2. Tests follow a pyramid: many fast unit tests, fewer integration tests against real dependencies such as a test database, and a few end-to-end tests on critical user flows. All of them run in CI as a merge gate on every pull request.
  3. Code review: keep pull requests small and single-purpose. Review for correctness, naming, error handling and test coverage of edge cases, and leave style to the tools.
  4. Maintainability in design: clear module boundaries, functions that do one thing, and no premature abstraction (duplicate twice, abstract on the third case). Write down the reason behind non-obvious decisions.
  5. Track whether it works with numbers such as change failure rate, flaky-test rate and the time from merge to deploy. Refactor behind tests rather than in large rewrites.

Follow-up

  • How would you add tests to a legacy module that has none? (Characterization tests first.)
  • What would you block a pull request for, and what would you leave as a non-blocking comment?
  • How do you deal with flaky tests in CI?

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

Medium · System Design / Architecture

Approach

  1. Requirements: create a short code for a long URL, redirect from code to URL, and optionally support custom aliases, expiry and click analytics. Reads far outnumber writes, so size the system with rough numbers for writes per second, redirects per second and storage over several years.
  2. Key generation, with trade-offs: base62-encode a unique counter (62^7 is about 3.5 trillion codes) and hand out ID ranges to each app server so a single counter is not a bottleneck. Or use random codes guarded by a unique constraint that retries on collision. A truncated hash of the URL needs collision handling too.
  3. Storage: a key-value lookup of code -> long_url, created_at, expires_at and owner, with a unique index on code. The store is easy to shard by code, because every redirect reads by key.
  4. Redirect path: put a cache (Redis or the CDN) in front of the store, since popular links are hot. A 301 lets browsers cache the redirect but hides repeat clicks from analytics. A 302 sends every click to the service.
  5. Write analytics asynchronously through a queue so the redirect never waits on them. Add rate limiting and malicious-URL checks on creation, and handle expired or deleted codes with a 404 or 410.

Follow-up

  • Should the same long URL submitted twice get the same code? What does that cost?
  • How do you handle a custom alias that collides with a generated code?
  • What happens when one link suddenly gets a huge share of traffic?

How would you design a system to handle real-time notifications?

Medium · System Design / Architecture

Approach

  1. Clarify channels and guarantees: in-app real-time, mobile push (APNs/FCM) and email. Settle whether duplicates or losses are worse, and whether order matters per user.
  2. Pipeline: producers publish events to a durable log or queue (Kafka, SQS). A notification service applies user preferences, mute rules and deduplication, then routes to channel workers. Partitioning the log by user_id keeps one user's notifications in order.
  3. In-app delivery: clients hold WebSocket or SSE connections to gateway servers, and a registry (Redis) maps user -> gateway node, so the service can forward a message to the right node.
  4. Offline users and reliability: write every notification to a per-user inbox table first. On reconnect the client fetches everything after its last-seen ID. Delivery is at-least-once with an idempotency key, so clients drop duplicates.
  5. Scale and abuse: decide fan-out on write vs on read for very large audiences. Batch low-priority events into digests and rate-limit per user. Sync read state across devices through the inbox.

Follow-up

  • What happens to connected users when a gateway node crashes?
  • How would you send one notification to a million followers without overloading the system?
  • How do you make sure a user never sees the same notification twice?

What considerations do you take into account when designing a microservices architecture?

Medium · System Design / Architecture

Approach

  1. Draw service boundaries by business capability, and give each service its own data. A shared database couples deploys and schemas, which removes most of the benefit.
  2. Communication: synchronous REST or gRPC when the caller needs an answer now, asynchronous events through a broker when it does not. Every remote call needs a timeout, retries with exponential backoff and jitter, idempotent handlers and a circuit breaker.
  3. Consistency across services: replace distributed transactions with sagas (local transactions plus compensating actions). Use the transactional outbox pattern so a database write and its event cannot diverge.
  4. Operations: distributed tracing with propagated correlation IDs (OpenTelemetry), centralized logs and per-service metrics. Add service discovery, an API gateway, independent CI/CD pipelines and contract tests so one team cannot break another's consumers.
  5. Name the cost. Network failures, debugging across services and operational overhead are real, so a modular monolith is often the better start for a small team. Split it out with the strangler-fig pattern.

Follow-up

  • How would you split an existing monolith safely?
  • Service A commits an order but the event to service B is lost. How do you prevent or repair that?
  • When would you merge two services back together?

Explain how you would approach load balancing in a web application.

Medium · System Design / Architecture

Approach

  1. Place the load balancer in the request path and pick the layer. L4 balancers route TCP connections fast without reading content. L7 balancers read HTTP, so they can terminate TLS, route by path or header and retry idempotent requests.
  2. Algorithms and when each fits: round robin or weighted round robin for uniform requests, least connections for uneven or long-lived requests such as WebSockets, and consistent hashing when you want affinity for cache locality.
  3. Health: active health checks plus passive outlier ejection remove bad backends. Connection draining lets a deploy finish in-flight requests before an instance leaves.
  4. Keep app servers stateless (sessions in Redis or a signed token) so sticky sessions are unnecessary and instances can scale out or be replaced freely.
  5. Remove the balancer as a single point of failure with a redundant pair or a managed load balancer. Across regions, use DNS or GeoDNS or anycast, and remember that DNS TTLs slow failover.

Follow-up

  • What happens to in-flight requests when a backend is taken out of rotation?
  • How would you balance a fleet of long-lived WebSocket connections after adding new servers?
  • How do you spread database reads across replicas, and what does replication lag break?

Walk us through your thought process in solving a real-world problem you encountered.

Medium · Problem-Solving / Case Studies

Approach

  1. Pick one real problem and state it as a goal with a measure, for example cutting a checkout error rate from 3% to under 0.5%, along with the constraints (deadline, people, systems you could not change).
  2. Show how you gathered evidence before acting: reproducing the issue, reading the data or logs, talking to the affected users or teams. Say what that ruled out.
  3. Lay out two or three options and compare them on explicit criteria such as risk, effort, reversibility and impact. Explain why you picked one.
  4. Describe how you delivered it in steps (a flag, a small first release) and how you checked the result against the original measure.
  5. Finish with the lesson and what you would change. Do not narrate only the happy path: the reasoning at each fork is the content of the answer.

Follow-up

  • Which option did you reject, and what would have made it the right choice?
  • What data would have changed your decision?
  • How did you know the problem was actually solved?

Analyze a recent feature you implemented and discuss its impact.

Medium · Problem-Solving / Case Studies

Approach

  1. Open with the user problem and the success metric you defined before building, with its baseline. Without a baseline, any impact claim is weak.
  2. State your part and the key technical decisions: what you built, the main trade-off (for example client-side vs server-side rendering, or sync vs async processing) and why.
  3. Describe the rollout: feature flag, staged percentage or an A/B test with a control group. Name the guardrail metrics you watched, such as latency, error rate and support tickets.
  4. Give the measured result as numbers against the baseline. Be honest about what did not move or what surprised you, and how you attributed the change to the feature rather than seasonality or other launches.
  5. Close with the next iteration, or what you would cut or change knowing the results.

Follow-up

  • How did you separate the feature's effect from everything else that changed that month?
  • Which metric moved the wrong way, and what did you do about it?
  • If you rebuilt it, what would you leave out?

If given a set of requirements, how would you design a solution from scratch?

Medium · Problem-Solving / Case Studies

Approach

  1. Split the requirements into functional ones (what users can do) and non-functional ones (scale, latency targets, availability, consistency, security). Ask which matter most, and write down your assumptions.
  2. Run rough estimates (users, requests per second, read/write ratio, storage growth) to find which parts actually need scaling.
  3. Define the API and the data model next, then a simple high-level design: clients, a stateless service layer, the datastore, plus a cache or queue only where the estimates justify them.
  4. Deep-dive on the one or two bottlenecks or risky parts. For each, state the trade-off (consistency vs availability, cost vs latency) and the failure modes: what happens when a component is down.
  5. Plan delivery in stages: a minimal version first, the scaling steps after it, and how you would test that the design meets its targets (load tests, metrics).

Follow-up

  • A key requirement changes halfway through. What in your design has to change?
  • Which component would you build first, and why?
  • How would you show the design meets its latency target before launch?

Discuss a time you had to make a decision with incomplete information.

Medium · Problem-Solving / Case Studies

Approach

  1. Set up what was unknown, why you could not wait for it, and what delay would have cost (a missed release, a growing incident, a blocked team).
  2. Show how you framed the risk. Was the decision reversible or one-way? What was the worst plausible outcome? What partial evidence did you gather quickly (a time-boxed spike, a small sample, an expert you asked)?
  3. Explain how you limited the downside: a feature flag, a rollback plan, a small first rollout, or a checkpoint at which you would revisit the decision.
  4. Give the outcome honestly, including what the missing information turned out to be, and what you would do the same or differently.
  5. The weak version of this story is a guess that happened to work. Make sure yours shows deliberate reasoning about the risk.

Follow-up

  • What information would have changed your decision?
  • How did you explain the uncertainty to your manager or stakeholders?
  • What would you have done if the decision had turned out wrong?

How would you approach debugging a critical issue in production?

Medium · Problem-Solving / Case Studies

Approach

  1. Mitigate before diagnosing. Gauge the blast radius (error rate, affected users and endpoints), open an incident channel with one owner, and if a recent deploy or config change lines up with the start, roll it back or switch off the feature flag.
  2. Build a timeline of what changed: deploys, config, traffic shape, dependency status, data migrations. Line it up against when the symptom began.
  3. Narrow it down with metrics, then logs, then traces. Split by endpoint, host, region, version and customer segment to find what the failing requests have in common. Check that the dashboard itself is not wrong.
  4. Form one hypothesis at a time and test it with the smallest safe experiment, ideally reproducing it outside production with production-like data. Avoid risky live changes made only to gather information.
  5. Fix with a regression test that fails before the change. Then write a blameless postmortem with concrete actions (an alert, a guardrail, a deploy check), so the trigger and the underlying cause are both handled.

Follow-up

  • The rollback did not fix it. What do you do next?
  • The issue hits about 1% of requests, intermittently. How do you find it?
  • How would you tell the cause apart from a coincidence in the timeline?

Suggested practice checklist

The plan follows the reported loop: a baseline on day one, coding on days two and three, fundamentals and data on day four, system design on day five, case studies on day six and a behavioral story bank on day seven. Candidates report preparing for two to four weeks, so stretch the days if you have the time.

Day 1 — Map the four rounds and set a baseline

  • Write the four reported rounds in order and mark which one you feel least ready for.
  • Answer the version control question aloud, recorded, and note the gaps: branching model, rebase versus merge, recovery commands.
  • List the stack from the reported requirements (JavaScript, Python or Java; React or Node.js; SQL or MongoDB) and pick the language you will use for all coding practice.

Deliverable: A one-page round map with the weakest round marked, a recorded version control answer with its gaps listed, and the language you chose.

Day 2 — Coding I: linked list, binary search, anagrams

  • Write the linked-list reversal iteratively, then recursively, and test it on empty, one-node and two-node lists.
  • Write binary search with an explicit invariant and test absent, first, last and single-element cases.
  • Write the anagram check twice, once by sorting and once with a character count, and state the time and space of each.

Deliverable: Three working functions in your chosen language, each with its edge-case tests and a one-line complexity statement.

Day 3 — Coding II: sliding window, merging, complexity

  • Write the longest substring without repeating characters with a brute force first, then a sliding window using a dictionary of last positions; test abba and an empty string.
  • Write the merge of two sorted arrays with two pointers and handle unequal lengths and duplicates.
  • Explain the time and space complexity of all five coding solutions from days two and three aloud, comparing each with its brute force.

Deliverable: Two more working functions with tests, plus a five-row table giving the brute-force and final complexity of every coding solution.

Day 4 — Fundamentals and data

  • Write a REST versus GraphQL comparison covering over-fetching, endpoint shape, caching, error handling and versioning, and a four-pillar explanation of object-oriented programming with one code example.
  • Write a code quality checklist covering review practice, tests, linting, small changes and refactoring habits, and turn it into a spoken answer.
  • Write a SQL versus NoSQL decision for a concrete project, such as an order system against a document store, naming schema, joins, consistency and scaling.

Deliverable: A REST versus GraphQL page, an object-oriented example, a code quality checklist, a SQL versus NoSQL decision with trade-offs and a completed paging exercise.

Day 5 — System design drills

  • Design a URL shortening service: requirements, key generation and collision handling, data model, read-heavy caching and redirect path.
  • Design a real-time notification system: delivery over a persistent connection or push service, a queue between producer and sender, retries and offline users.
  • List the considerations for splitting a monolith into microservices (boundaries, data ownership, failure handling, deployment cost) and sketch load balancing for a web application, including health checks and session handling.

Deliverable: Two component diagrams with a short trade-off list each, plus a microservices checklist and a load balancing sketch.

Day 6 — Case studies and past work

  • Write a production-debugging sequence and rehearse it against an invented outage: scope, recent changes, logs and metrics, hypothesis, mitigation, root cause and follow-up.
  • Practise starting a design from a short set of requirements, stating assumptions and non-functional needs before choosing components.
  • Write up two real projects covering the challenging technical problem, the real-world problem, a recent feature and its impact, and a decision made with incomplete information, each with numbers and a mistake.

Deliverable: A debugging script, one worked design from requirements and two project write-ups that each answer four of the reported case-study questions.

Day 7 — Behavioral story bank and full run

  • Write one story each for conflict, prioritisation, influencing a decision, feedback received and what motivates you, in situation, action and result form.
  • Rehearse each aloud and cut anything that does not carry the decision or the result.
  • Run a mixed final session: one coding problem, one design prompt and two behavioral answers, back to back and recorded.

Deliverable: Five written stories, each rehearsed aloud, plus a recorded mixed session with the weakest answer marked for a final fix.

Collaboration, feedback and ownership stories

Candidates describe a stage of discussions with team members, and the evaluation themes they report are collaboration and communication, conflict and feedback, and adaptability and learning. For an engineer on a team that works with product managers and designers, that means stories in which you made a decision, dealt with disagreement, took feedback and learned something new. Prepare each as situation, your action and a result.

  1. Describe a new technology you learned recently and how you applied it.

How do you handle version control in your projects?

Medium · Technical / Domain Questions

Approach

  1. Describe your real workflow in order: branch from an up-to-date main, commit in small logical units with messages that say why, open a pull request, pass review and CI, then merge. Name the model you use, such as short-lived feature branches or trunk-based development with feature flags, instead of listing commands.
  2. State when you rebase and when you merge: rebase your own unshared branch to keep history linear, merge or squash when integrating into main, and never rewrite history that others have pulled. After a rebase, push with --force-with-lease rather than --force.
  3. Cover recovery: git revert undoes a commit already on main without rewriting history, git reflog finds commits that seem lost, git bisect locates the commit that introduced a regression, and a secret committed by mistake must be rotated, not just deleted.
  4. Describe team conventions: a protected main branch, required reviews and status checks, small pull requests, tags for releases and a hotfix path from the release tag. Tie it to CI/CD, which candidates list among the practices for this role.
  5. Close with one real moment, such as a merge conflict in a shared file that you resolved by talking to the other author first. A story shows judgment where a command list does not.

Follow-up

  • When would you squash-merge rather than keep a merge commit, and what do you lose by squashing?
  • A bad commit is already on main and deployed. What do you do, step by step?
  • Two people changed the same function. How do you resolve the conflict and confirm the behaviour is still correct?

Describe a time when you had a conflict with a team member. How did you resolve it?

Medium · Behavioral / Leadership

Approach

  1. Choose a real disagreement with a peer about something that mattered, such as an API shape, a deadline or how to review a change. Avoid a trivial one, and avoid a story in which the other person was simply unreasonable.
  2. Use situation, task, action, result, and spend most of the time on your actions: you asked them to explain their reasoning, found what you agreed on, and brought evidence such as a benchmark, a prototype or a customer constraint rather than opinion.
  3. Show the resolution and the relationship afterwards: what was decided, whether it was your option, theirs or a third, and how you worked together after. If you were wrong, say so and what you learned.
  4. The mistake that sinks this answer is describing winning. Show that you listened first, kept the discussion on the problem and not the person, and escalated only when the disagreement was blocking delivery.

Follow-up

  • What if the other person had still disagreed at the end? What would you have done?
  • Looking back, what would you do differently at the start of that conflict?
  • How did you work with that person on the next project?

How do you prioritize tasks when working on multiple projects?

Medium · Behavioral / Leadership

Approach

  1. Give your method before the story: list everything in flight, then rank by user or business impact, deadline, and what blocks other people. Name the tools you use, such as a written backlog, and say how you keep it visible to others.
  2. Use one concrete case with three or four competing items, for example a feature deadline, a code review someone is waiting on and a production bug. Say what you did first, what you delayed and why.
  3. Show that you negotiated rather than silently absorbing the load: you told the product manager or designer what would slip, offered a reduced scope or a new date, and agreed the change in writing.
  4. Explain how you re-prioritise when something urgent arrives, such as an outage. Say how you hand off or pause the earlier work so it does not get lost.
  5. Weak answers say 'I make a to-do list' and stop. Finish with the outcome: what shipped, what moved and whether the people affected were told before they discovered it.

Follow-up

  • Two stakeholders each say their request is the top priority. How do you decide?
  • Tell me about a time you got the priority wrong. What happened?
  • How do you protect time for code reviews and technical debt when feature work is pressing?

Can you provide an example of how you influenced a decision in a team?

Medium · Behavioral / Leadership

Approach

  1. Pick a decision where you had no authority to dictate the outcome, such as choosing a library, changing a testing approach or reshaping an API, and state the position you wanted at the start.
  2. Describe how you built the case: you learned each person's objection first, then brought evidence such as a small spike, a benchmark, an error rate or a comparison of options, so the discussion moved from preference to data.
  3. Show that the influence was collaborative. You adjusted your proposal after hearing concerns, you made it easy to try (a pilot on one service, say), and you agreed how to tell whether it worked.
  4. State the result with something measurable, such as build time, incident count or review turnaround, and say whether the team adopted the idea fully, partly or not at all. A partly adopted idea described honestly is a strong answer.
  5. The mistake that sinks it is a story that was really an instruction from a position of authority, or one in which you persuaded people by being louder than they were.

Follow-up

  • What would you have done if the team had rejected your idea?
  • Who disagreed most strongly, and what changed their mind?
  • How did you check afterwards that the decision was right?

What motivates you to succeed in your role?

Medium · Behavioral / Leadership

Approach

  1. Answer with specifics instead of a slogan. Name two or three things that actually drive you, such as shipping something users touch, solving a hard debugging problem, or learning across the stack, and attach each to something you did.
  2. Link the motivation to this role as candidates describe it: working with product managers and designers on features, owning a feature through review and deployment, and seeing how the change affects users. Do not claim to know the company's values.
  3. Back it with behaviour: a time you stayed to fix a flaky test suite, wrote documentation nobody required, or took a feature end to end because you wanted to see its effect.
  4. Be honest about what drains you and how you handle it, such as unclear requirements, which you respond to by asking questions early. Motivation that survives a bad week is more convincing than enthusiasm.
  5. Avoid answers about salary or title alone, and avoid generic claims such as 'I love challenges' with no example.

Follow-up

  • Tell me about a time your motivation dropped. What did you do?
  • What kind of work would you not want to do for a long time?
  • How do you stay motivated when a project is mostly maintenance?

How do you handle feedback and criticism?

Medium · Behavioral / Leadership

Approach

  1. Pick a real piece of critical feedback, preferably from a code review or a project retrospective, not a disguised strength such as 'I work too hard'. Say who gave it and what exactly it was.
  2. Describe your first reaction honestly, then your actions: you asked clarifying questions, separated what was accurate from what was not, made a concrete change and told the person what you changed.
  3. Show the behaviour change with evidence. For example, if reviewers kept finding missing tests, say you added a test checklist before opening pull requests and review comments on that point stopped.
  4. Cover the other direction briefly: how you give feedback, such as being specific about the code, explaining the reason and offering an alternative, so the answer shows you can work in a two-way review culture.
  5. The mistake that sinks it is defensiveness, blaming the person who gave the feedback, or a story where nothing changed afterwards.

Follow-up

  • What do you do when you disagree with the feedback you have been given?
  • Give me an example of feedback you gave a colleague and how they responded.
  • Which piece of feedback has changed how you work the most?