cswork / libraryOpen practice workspace

Interview guides · Carfax

Carfax Software Engineer Interview Guide

Carfax Software Engineer interview guide: the three reported rounds, OOP, REST, SQL and pair-programming questions, plus a seven-day prep plan.

The 60-second brief

Carfax publishes Carfax Vehicle History Reports, which are assembled from large volumes of vehicle data for car buyers and sellers. Candidates describe the Software Engineer role as work on RESTful services, integrations with external APIs, cloud infrastructure, front-end interfaces and backend data pipelines, inside cross-functional teams. Day to day, the reported duties are turning requirements into features with test-driven code, taking part in code reviews, tuning SQL queries behind report generation and building front-end components. The vehicle, make and manufacturer examples in the reported questions come straight from that data-heavy, service-oriented work.

This guide is for candidates interviewing for a Software Engineer position at Carfax. It covers the three reported rounds, the thirteen reported questions (object-oriented fundamentals, data and API design, and behavioral prompts) and the stack candidates list for the role: Java, C# or JavaScript as example languages, SQL and relational databases, RESTful APIs, React on the front end, and Azure or AWS and CI/CD as nice-to-haves. It also includes a seven-day plan and behavioral stories to rehearse.

Candidates report three rounds over roughly 3-5 weeks: a Technical Screening, a Live Coding Exercise done as pair programming, and a Panel Discussion with peers and management.

Focus areas

  • Object-Oriented Programming (OOP)
  • ReactJS (Frontend Development)
  • SQL

Overview

The reported questions cluster around a small, concrete domain: a Vehicle with an ID and VIN, a Make with an ID and name, a REST service that does CRUD on them, a schema that stores them, and a SQL query that filters vehicles by manufacturer. Before anything else, build that mini-system yourself in the language you will interview in. Write the two tables with keys and constraints, the endpoints with status codes, and the join query. Having built it once, the schema, REST and SQL questions become a walk through code you know.

Alongside the domain questions sits a group of object-oriented fundamentals: interface versus abstract class, polymorphism with a real-world example, exception handling in a large Java application, and experience with design patterns. These reward answers anchored in code. For each one, keep a short example from a domain like vehicle types or report formats, be ready to sketch the class skeleton, and be ready to state the deciding rule, such as when shared state and partial implementation justify an abstract class and when a pure contract fits an interface.

Candidates describe the technical stages as practical rather than puzzle-driven: fixing code so that failing unit tests pass, writing unit tests, manipulating basic data structures and debugging HTTP requests and API responses, often as pair programming. Practise that loop directly. Take a small failing test suite, read each failure, make the smallest change, rerun everything, then refactor. Learn the standard test framework for your language, and say your reasoning out loud while you type, because the pairing format is built around a shared conversation.

The behavioral prompts are about your hardest programming project and your own contribution, a coworker who is not meeting expectations, your ideal work environment and giving and receiving feedback while pairing. Candidates also describe the teams as collaborative and self-governing. Prepare specific stories with a clear "I", and review every technology on your resume, since candidates report being asked for practical and conceptual depth on anything listed.

The Carfax interview process

Candidates describe three stages in this order, from screening to the final panel. The team you interview with may shift the emphasis to match its current projects.

Technical Screening

Candidates describe the Technical Screening as an initial check of technical skill through coding exercises. The reported topic areas for the loop include OOP, SQL, code assessments and unit testing, and candidates also report that anything listed on a resume can be probed for practical and conceptual detail. Approach it as a working-code stage: pick one language, write clean and simple solutions, handle edge cases and add a few unit tests without being asked.

What to demonstrate

  • Working code on small coding exercises, including basic data structure manipulation
  • Command of the language you chose, since candidates report resume technologies are fair game for conceptual and practical questions
  • Readable logic with edge cases handled and tests alongside

How to prepare

  • Choose Java, C# or JavaScript and write three small exercises (group records by a key, de-duplicate with a map, sort by two fields), each with a handful of unit tests in the standard framework for that language
  • Rehearse the object-oriented fundamentals out loud with a code sketch: interface versus abstract class, polymorphism, and exception handling in a large Java application
  • For each technology on your resume, write one deep detail you could explain, and remove anything you cannot defend

Live Coding Exercise

The Live Coding Exercise is reported as a coding session done with a pair programming approach. Candidates also report that technical rounds often involve fixing existing code so failing tests pass, writing unit tests and debugging HTTP requests and API responses. Treat it as a conversation at a keyboard: read the failing output aloud, state what you expect to change, make the smallest edit that works, rerun, and only then tidy the structure.

What to demonstrate

  • Working code produced live, including unit tests and edge-case handling
  • Debugging of failing tests and of HTTP requests and responses
  • How you share ideas and handle a technical disagreement with a partner, which candidates report is observed in pairing

How to prepare

  • Take a small buggy function with four failing tests and practise the loop of read failure, reproduce, minimal fix, rerun the whole suite, refactor
  • Practise debugging an API call by checking method, URL, headers, request body, status code and response body one at a time, using curl or a REST client
  • Prepare your answer on giving and receiving feedback while pairing, and rehearse narrating your thinking while typing

Panel Discussion

Candidates report the Panel Discussion as a conversation with both peers and management to assess fit, and describe it as more conversational than the coding stages. Expect to talk through your resume projects, your own contribution to them, how you work with teammates and what you want from a team. Walk in with stories that name your specific actions, and with questions of your own about the team's current challenges, which is a tip candidates share.

What to demonstrate

  • Your ability to work in a team and explain your reasoning to several people at once
  • Depth on the projects and technologies you list
  • Whether your working style matches what candidates describe: collaborative, self-governing teams that share knowledge

How to prepare

  • Write four stories with a clear "I": the hardest programming project, a coworker not meeting expectations, a disagreement over a technical choice, and a time feedback changed your code
  • Write a two-minute answer on your ideal work environment, backed by one example from a past team
  • Prepare two questions about the team's current challenges and how work is shared, and be ready to talk through a design such as REST services plus schema normalization trade-offs

Where candidates lose points

Answering interface versus abstract class and polymorphism with textbook definitions only

For each OOP question, hold one code example from a domain such as vehicle types or report formats. State the deciding rule: an interface defines a contract that unrelated classes can share, while an abstract class fits when subclasses share state or a partial implementation. Show that a call through the base type picks the right override at runtime.

Going silent while pair programming, or taking over the keyboard

Narrate before you type: what you read in the failure, what you expect to change, why. Invite your partner's view on ambiguous choices, and treat their feedback as input to test rather than an argument to win.

Making failing tests pass by editing the tests, hard-coding the expected values or special-casing the input

Reproduce the failure, find the cause, make the smallest real fix, rerun the whole suite, then refactor. Add a test for any edge case you spotted (empty input, null, duplicates) so the fix is visible.

Describing the vehicle and make CRUD service as a list of endpoints with no schema, constraints or error handling

Sketch both tables first: primary keys, a unique constraint on VIN, a foreign key from vehicle to make and an index on that key. Then give each endpoint its verb, path and status codes (201 on create, 404 when missing, 409 on a duplicate VIN, 400 on bad input) and mention validation and pagination for the list.

Listing technologies on your resume that you cannot discuss in depth, or telling behavioral stories without a clear "I"

Cut the resume to what you can defend and write one deep detail for each item. For every story, state your own decision and action in the first person, and keep team credit separate.

Questions & practice

Find overlapping job attempts and peak concurrency from lease records

Medium · sweep line · intervals · leases

A day of job_run history yields about 50,000,000 attempt records: (job_run_id, job_type, attempt, started_at, finished_at which is NULL when the worker died, lease_expires_at). Leases expire on a clock, so a job that outran its lease ran twice. Produce (a) every job_run_id whose attempts overlapped in wall-clock time and (b) the peak number of simultaneously running attempts per job_type with the minute it occurred. Target O(n log n). State how you treat a NULL finished_at and what clock skew does to your answer.

Approach

  1. Define the interval before sorting anything: an attempt occupies [started_at, COALESCE(finished_at, lease_expires_at)). finished_at is observed and lease_expires_at is only a promise, so every attempt without a finish contributes an estimate and the whole result is a lower bound on overlap rather than an exact count.
  2. For peak concurrency, sweep: emit 2n endpoints, sort by (timestamp, kind) with ends ordered before starts at equal timestamps, then walk the sequence maintaining a counter per job_type and record each type's maximum with its timestamp. O(n log n) dominated by the sort, O(n) space, or O(1) extra if the sort is external and the walk streams.
  3. For overlap detection, do not compare attempts pairwise. A single global sort by (job_run_id, started_at) gives both the grouping and the order; within a group, keep the maximum end seen so far and report an overlap exactly when the next start is less than that running maximum, which is one linear pass after the sort.
  4. Half-open intervals matter and are easy to get wrong: with closed intervals an attempt ending at the same millisecond another begins reads as concurrency two, and across 50,000,000 records that artefact swamps the real signal.

Follow-up

  • A handler is not idempotent and you have found 400 overlapping jobs. Which of them actually caused damage, and what would you query to find out?
  • Peak concurrency for one job_type is 4 against a configured cap of 4. Is the cap working, or is the data hiding attempts that never started?

Merge partitioned event streams into one ordered feed with bounded lateness

Hard · k-way merge · watermarks · out-of-order streams

The read-model service consumes 64 log partitions carrying about 4,000 events per second in total. Each partition is ordered within itself, but partitions drift by up to 30 seconds, and the activity feed must present a tenant's events in occurred_at order. Produce the merge. State its complexity, the buffer it requires in events and in bytes, what happens when one partition is idle, and what you do with an event that arrives after you have already emitted its position. Payloads average 1 KB.

Approach

  1. Merge with a min-heap over the 64 partition heads keyed on (occurred_at, event_id): O(log P) per event and O(n log P) overall. The tie-break on event_id is what makes the output deterministic when two partitions carry the same millisecond, which matters because the feed is paginated and a non-deterministic order reorders pages under the reader.
  2. Emitting the heap head is only correct once every partition has produced everything up to that timestamp, so the emit condition is a watermark: the minimum across partitions of the highest occurred_at seen, less the allowed lateness. Events are held until the watermark passes them, which is what turns individually ordered streams into a jointly ordered one.
  3. Size the buffer from the lateness rather than guessing: 4,000 events per second times 30 seconds is 120,000 buffered events, and at 1 KB each about 120 MB of heap. That number is the real price of the ordering guarantee and belongs in front of whoever asked for it.
  4. Handle the idle partition explicitly, because it fails the feed rather than corrupting it: a partition with no traffic never advances its own maximum, so the watermark freezes and output stops entirely. Either every partition emits a periodic idle marker carrying the broker's current time, or the watermark falls back to wall clock for a partition silent beyond a threshold.

Follow-up

  • The lateness budget is raised to five minutes. What is the new buffer, and what besides memory changes?
  • The consumer restarts. Where does it resume from, and what does the feed look like for the first 30 seconds?

Identify the heaviest tenants in a five-minute window under memory pressure

Medium · top-k · heavy hitters · streaming

The edge service handles about 3,000 requests per second across roughly 50,000 tenants, peaking near 9,000. Expose the 50 heaviest tenants by request count over the trailing five minutes so limits can be tightened before one tenant's backfill starves the fleet. You may not retain five minutes of raw records. Give the exact solution and its memory, then the bounded-memory approximation with its error stated as a formula, and say which you would ship and at what tenant cardinality that choice changes.

Approach

  1. Do the exact version first, because it is affordable at this cardinality: a ring of 300 one-second counters per tenant, advanced lazily, is 1,200 bytes of counters per tenant and roughly 60 to 90 MB for 50,000 tenants with overhead. Carry a running total and subtract the bucket you overwrite so a window read is O(1) rather than 300 adds.
  2. Extract the top 50 with a size-k min-heap over the tenant sums: O(d log k) for d tenants, against O(d log d) to sort them all. Maintaining the heap continuously instead of on query requires a tenant-to-heap-index map, because incrementing a count already inside the heap means sifting from a known position, and without that map you rebuild the heap on every request.
  3. State the approximation precisely rather than gesturing at sketches. Misra-Gries with m counters retains every item whose true count exceeds N/(m+1), and each retained count underestimates the truth by at most N/(m+1). With m = 1,000 and N = 900,000 requests in the window the error is roughly 900 requests, which is fine for spotting a tenant sending 50,000 and useless for ranking two tenants 200 apart.
  4. Say what breaks when the window slides: Misra-Gries and Space-Saving are insert-only and cannot be decremented as records age out. The workable construction is one summary per sub-window, say ten seconds, with 30 summaries merged at query time, and the merged error is the sum of the per-summary errors, so the bound degrades linearly in the number of sub-windows.

Follow-up

  • The heaviest tenant is heavy because of one export job rather than user traffic. Should the limiter treat those as the same tenant?
  • Two tenants sit tied at the boundary of the top 50. Does your answer flap, and does the flapping matter?

What are the advantages and disadvantages of normalizing a database?

Medium · Technical Foundations & OOPS

Approach

  1. Anchor the definitions briefly: 1NF means atomic columns and no repeating groups, 2NF removes partial dependencies on part of a composite key, 3NF removes transitive dependencies (a non-key column depending on another non-key column).
  2. Advantages, with an example: if each vehicle row stores the make name as text, renaming a make means updating every matching row (update anomaly), and a make cannot exist until some vehicle uses it (insert anomaly). A separate make table referenced by foreign key stores each fact once, keeps writes small and lets the database enforce integrity.
  3. Disadvantages: reads need more joins, queries get longer, and read-heavy or reporting paths can slow down as joins multiply across large tables.
  4. Give the trade-off you would actually make: normalise the system of record to 3NF, then denormalise deliberately for hot read paths with a materialised view, a reporting table or a cache, and state how that copy is kept in sync and how stale it may be.

Follow-up

  • When would you deliberately store a denormalised column, and how would you keep it consistent?
  • What is the difference between 3NF and BCNF? Can you give a case where they differ?
  • How do indexes change the read cost of a normalised schema?

How would you represent these entities in a database schema?

Medium · Data & API Design

Approach

  1. Write the two tables: make(id primary key, name varchar not null unique) and vehicle(id primary key, vin char(17) not null unique, make_id not null references make(id)). This is a many-to-one relationship: many vehicles per make.
  2. Justify the keys: VIN is a natural unique identifier, but a surrogate integer id keeps foreign keys small and survives a corrected VIN; keep the UNIQUE constraint on vin so the database still rejects duplicates.
  3. Index the foreign key: PostgreSQL does not create an index on vehicle.make_id automatically (MySQL InnoDB does), and without one, joins and filters by make and the FK check on deleting a make scan the vehicle table.
  4. Choose the delete rule explicitly: ON DELETE RESTRICT (the default NO ACTION behaves similarly) to block deleting a make that still has vehicles, rather than CASCADE, which would silently remove vehicle rows.
  5. Mention edge cases: case-insensitive uniqueness of make names (a unique index on lower(name)) and how the schema would extend, for example a model table between make and vehicle, or a one-to-many history table keyed by vehicle_id.

Follow-up

  • Should VIN be the primary key instead of a surrogate id? Argue both sides.
  • How would you add model and model year without duplicating make data?
  • How would you store a timeline of events for each vehicle, and which index supports reading it in date order?

Describe how you would use SQL to query specific data sets, such as filtering vehicles by manufacturer.

Medium · Data & API Design

Approach

  1. Write the base query: SELECT v.id, v.vin FROM vehicle v JOIN make m ON m.id = v.make_id WHERE m.name = ? ORDER BY v.id; run it through a prepared statement with a bind parameter, never string concatenation, to prevent SQL injection.
  2. Name the indexes it relies on: the unique index on make.name for the lookup and an index on vehicle.make_id for the join, then say you would confirm the plan with EXPLAIN (or EXPLAIN ANALYZE) instead of guessing.
  3. Handle the variants: several manufacturers with WHERE m.name IN (...); a count per make with LEFT JOIN and GROUP BY m.id, m.name using COUNT(v.id), because COUNT(*) would report 1 for a make with no vehicles.
  4. Call out traps: wrapping the column in a function, as in WHERE lower(m.name) = lower(?), stops a plain index on name from being used unless you add an expression index; large result sets need pagination, and keyset pagination (WHERE v.id > ? ORDER BY v.id LIMIT n) stays fast where a large OFFSET has to skip rows.

Follow-up

  • How would you list makes that have no vehicles at all?
  • How would you return the top five makes by vehicle count, and how do you handle ties?
  • The filter is slow on a large table: what do you check first?

Describe the difference between an interface and an abstract class. When would you use each?

Medium · Technical Foundations & OOPS

Approach

  1. Start with the mechanical differences in Java: a class can implement many interfaces but extend only one class; an abstract class can hold instance fields, constructors and protected or private members, while an interface holds only public static final constants plus abstract, default, static and (since Java 9) private methods.
  2. Then give the design rule: use an interface to declare a capability that unrelated types can share (Comparable, a VinValidator, a Repository), and an abstract class when closely related subclasses share state and a fixed skeleton of behaviour.
  3. Show the template-method case for an abstract class: a base importer with a final run() that calls abstract parse() and validate() steps, so every subclass gets the same order and error handling.
  4. Note what Java 8 default methods changed: interfaces can now evolve without breaking implementers, but they still cannot hold per-instance state, so shared fields remain the deciding reason to pick an abstract class.
  5. If you work in C#, say the equivalent: C# 8 added default interface members, and C# also allows one base class and many interfaces, so the same reasoning carries over.

Follow-up

  • What happens when a class implements two interfaces that both provide a default method with the same signature, and how do you resolve it?
  • Would you put a constructor-injected dependency in an abstract base class or pass it to each subclass, and why?
  • How do sealed interfaces or classes in Java 17 change when you would reach for either one?

Explain the concept of polymorphism with a real-world example.

Medium · Technical Foundations & OOPS

Approach

  1. Define it in one line: one interface, many implementations, with the call resolved to the right implementation for the actual object type. Then separate the kinds: subtype polymorphism (overriding, resolved at runtime by dynamic dispatch), ad-hoc polymorphism (overloading, resolved at compile time from the static argument types) and parametric polymorphism (generics such as List<T>).
  2. Give a concrete example and show the code shape: an interface ReportSection with render(), implemented by AccidentSection, ServiceRecordSection and OwnershipSection; the report loops over a List<ReportSection> and calls render() without any instanceof checks.
  3. Explain the payoff: adding a new section type means adding a class, not editing a switch statement in every caller (open/closed principle), and each implementation can be unit tested on its own.
  4. Mention the Liskov substitution principle as the constraint: a subclass must honour the contract of the type it replaces, or polymorphic callers break in ways the compiler cannot catch.

Follow-up

  • What is the difference between overloading and overriding, and which one is decided at compile time?
  • Are static methods or fields polymorphic in Java? What happens if a subclass declares a static method with the same signature?
  • When would you replace a chain of if/else type checks with polymorphism, and when is the switch actually clearer?

How would you handle exception handling in a large-scale Java application?

Medium · Technical Foundations & OOPS

Approach

  1. Lay out the layering rule first: catch an exception only where you can handle it (retry, fall back, or translate it); otherwise let it propagate. At each layer boundary, translate low-level exceptions into domain ones (for example SQLException into VehicleNotFoundException or a DataAccessException) and always pass the original as the cause.
  2. Describe a small exception hierarchy: a base application exception, with client errors (validation, not found, conflict) kept separate from server and infrastructure errors, so one central handler can map them to HTTP 400, 404, 409 or 500. In Spring this is a @ControllerAdvice with @ExceptionHandler methods.
  3. Cover the code-level rules: use try-with-resources for anything AutoCloseable; never swallow an exception with an empty catch; never catch Throwable or Error to keep going; when catching InterruptedException, restore the flag with Thread.currentThread().interrupt().
  4. Logging: log once, at the boundary that handles the exception, with a correlation or request id. Logging and rethrowing at every layer gives duplicate stack traces. Return a stable error body to clients and never a stack trace.
  5. For transient failures (timeouts, connection resets) retry with bounded exponential backoff only when the operation is idempotent, and say how you would test each path with unit tests that assert the right exception type and message.

Follow-up

  • Checked or unchecked exceptions for your domain errors: which do you choose and why?
  • What happens to the original exception if the finally block, or the close() in try-with-resources, also throws?
  • How would you make sure a failure deep inside a background job is not silently lost?

You have a vehicle with an ID and VIN, and a Make with an ID and name. Describe how you would implement a REST

Medium · Data & API Design

You have a vehicle with an ID and VIN, and a Make with an ID and name. Describe how you would implement a RESTful service to perform CRUD operations.

Approach

  1. Model the resources and verbs: /makes and /makes/{id}, /vehicles and /vehicles/{id}, plus /makes/{id}/vehicles for the relationship. POST creates and returns 201 with a Location header; GET returns 200 or 404; PUT replaces the whole resource and PATCH updates part of it; DELETE returns 204.
  2. State the semantics: GET, PUT and DELETE are idempotent while POST is not, so a retried POST can create a duplicate unless a unique constraint or an idempotency key prevents it. Here the unique VIN does that job, and a duplicate VIN returns 409 Conflict.
  3. Validate input at the edge: a modern VIN is 17 characters and excludes the letters I, O and Q; make_id must reference an existing make. Return 400 (or 422) with a field-level error body, not a stack trace.
  4. Structure the code in layers: controller (HTTP mapping and DTOs), service (rules such as what happens when a make with vehicles is deleted), repository (SQL or ORM). Keep DTOs separate from database entities so the API contract can stay stable while the schema changes.
  5. Add list pagination (limit plus a cursor or page), then name the tests: unit tests for the service rules, and an integration test per endpoint covering the happy path, 404, 409 and validation failures.

Follow-up

  • What should DELETE /makes/{id} do when vehicles still reference that make?
  • How would a client look up a vehicle by VIN rather than by id, and why that URL shape?
  • Two clients update the same vehicle at once: how do you stop the second from silently overwriting the first?

What steps would you take to ensure an API is secure and performant?

Medium · Data & API Design

Approach

  1. Security basics first: TLS everywhere; authentication (OAuth 2.0 or JWT bearer tokens, or API keys for service callers); and authorisation on every object, checking that the caller may access this specific vehicle id, so changing an id in the URL exposes nothing (IDOR).
  2. Input and data safety: validate request bodies against a schema, use parameterised queries, give the service a least-privilege database user, keep secrets out of code and config files, and return generic error bodies with no stack traces.
  3. Abuse control: rate limit per client, for example with a token bucket kept in a shared store, return 429 with Retry-After, and cap page sizes so one request cannot pull a whole table.
  4. Performance: measure p95 and p99 latency before changing anything, then fix the common causes: N+1 queries (join or batch fetch), missing indexes, unbounded lists (pagination), and repeated reads (HTTP caching with Cache-Control and ETag returning 304, or a server cache with a clear invalidation rule).
  5. Infrastructure: database connection pooling, response compression, and moving slow work such as report generation off the request path to a queue, returning 202 Accepted with a status URL.

Follow-up

  • How would you spot an N+1 query problem in an existing endpoint?
  • With JWTs, how do you revoke access for a compromised token before it expires?
  • How would you rate limit across several instances of the same service?

Edge instances grow 400 MB per hour until the nightly restart

Hard · memory leak · heap analysis · metric cardinality

Edge API instances start at 700 MB resident and grow about 400 MB/hour; a nightly rolling restart has hidden it for weeks. Growth continues unchanged when request rate halves overnight, p99 degrades in the last hours before an instance is recycled, and heap used immediately after a forced full GC rises monotonically. The service holds no product state. Name the discriminating measurement that separates the plausible causes, give the most likely cause, and give the fix and how you would verify it.

Approach

  1. Separate resident memory from live heap first, because they fail differently. Resident size can grow from fragmentation, native buffers or thread stacks while the heap is flat; heap used after a full GC rising monotonically is the measurement that says objects are reachable and not being released. You already have it, so this is retention, not fragmentation, and that closes off half the candidate list.
  2. Use the rate's independence from traffic as the discriminator. Growth that continues at half the request rate rules out per-request objects that are merely slow to collect and points at a structure that grows with distinct values observed rather than with call volume. Write the candidates that have that property: a metrics registry keyed on a high-cardinality label, an unevicted cache, an interner, a per-key lock map.
  3. Take two heap snapshots an hour apart and diff by retained size, reading the dominator tree, not by allocation count or instance count. Expect one root holding a map with millions of entries, then follow the reference chain to the code that inserts and never removes. Allocation profilers point at churn, which is the wrong signal here.
  4. The candidate that fits this service is an observability label carrying an identifier, such as a request path recorded before templating so that /v1/resources/48213 becomes its own metric series. That grows with distinct ids seen, is independent of rate, and explains the late p99 degradation, since GC cost rises with the size of the live set.

Follow-up

  • Post-GC heap is now flat but resident size still creeps. What are you looking at, and does it matter?
  • How would you have detected this before an OOM, given the nightly restart masked the trend?

Suggested practice checklist

Each day is built around the reported rounds, the reported OOP, API, schema, SQL and behavioral questions, and the Java, C#, JavaScript, SQL, REST and React stack. The week ends with a pair-programming style session and a panel-style rehearsal.

Day 1 — Pick your language and map the loop

  • Choose Java, C# or JavaScript and commit to it for coding rounds, then set up the standard unit test framework for that language and run one passing test.
  • List every technology on your resume and write one deep technical detail for each; delete the ones you cannot defend.
  • Write the three reported rounds (Technical Screening, Live Coding Exercise, Panel Discussion) and mark the one you are least ready for.

Deliverable: A working test project in your chosen language, a resume list with one deep detail per technology, and a three-round map with the weakest marked.

Day 2 — OOP fundamentals and exception handling

  • Write the same small hierarchy twice (for example vehicle types or report renderers): once behind an interface and once with an abstract base class, and show a polymorphic call over a list of them.
  • Write out an exception strategy for a large Java service: checked versus unchecked, a small custom exception hierarchy, never swallowing exceptions, logging once at the boundary and translating to an HTTP error at the API edge.
  • Answer all three questions aloud, using your code as the example.

Deliverable: Two short code files (interface version and abstract-class version), a one-page exception strategy, and recorded spoken answers to the three OOP questions.

Day 3 — Design patterns you can code

  • Write a Strategy with two implementations, a Factory that picks one by input, and an Adapter that wraps a fake external API client.
  • Add unit tests for each using a fake or stub in place of the real collaborator.
  • Prepare a two-minute answer on your own pattern experience: two real examples, the cost of each and one case where you skipped a pattern.

Deliverable: Three pattern skeletons with tests and a written two-minute answer on your design pattern experience.

Day 4 — Vehicle and Make: schema, REST and SQL

  • Write the schema for Vehicle(id, VIN) and Make(id, name): primary keys, a unique VIN, a foreign key from vehicle to make and an index on that key.
  • Write the CRUD endpoints with verbs, paths, request and response bodies and status codes (201, 404, 409, 400), and the SQL that joins vehicle to make to filter by manufacturer name using a bind parameter.
  • List the advantages and disadvantages of normalizing this data, including when a read-heavy report might justify denormalizing, and answer the four questions aloud.

Deliverable: A schema file, an endpoint table, the filtering query, and a half-page on normalization trade-offs, plus spoken answers to the four questions.

Day 5 — API security, performance and a React front end

  • Write an API hardening checklist for your vehicle service: authentication and authorization, input validation, parameterized queries, rate limiting, pagination, caching headers, indexes and avoiding N+1 queries; answer the question on securing and speeding up an API aloud.
  • Debug three broken requests in curl or a REST client (wrong method, missing header, malformed body) and write what each response told you.
  • Build a small React component that fetches the vehicle list and filters by make, with one test using a mocked fetch.

Deliverable: An API checklist, notes on three debugged requests, and a tested React component, plus a spoken answer on API security and performance.

Day 6 — Pair-programming rehearsal

  • With a friend or a recording, work a failing test suite that you have not seen: narrate, make the smallest fix, rerun, then refactor.
  • Practise giving and receiving feedback aloud: a must-fix comment, a style preference and one disagreement you settle by writing a test; rehearse your answer on pairing feedback.

Deliverable: A recorded pairing session, a tested solution to the practice question, and a written answer on giving and receiving feedback while pairing.

Day 7 — Behavioral stories and panel rehearsal

  • Write each story (hardest project, coworker not meeting expectations, ideal work environment) with a clear "I", the concrete actions you took and what you would change.
  • Run a full mock panel with a friend who interrupts, covering your resume projects, one design discussion and your stories.
  • Write two questions for the panel about the team's current challenges and how work is shared.

Deliverable: Three written behavioral stories, a mock panel recording and two questions to ask the panel.

Behavioral and pair-programming preparation

Candidates report the pair-programming session and the Panel Discussion with peers and management as the places where teamwork and communication come up, and they describe the teams as collaborative and self-governing. Prepare specific stories for the reported prompts: your hardest programming project, a coworker not meeting expectations, your ideal work environment, and feedback while pairing. Keep your own actions in the first person and be ready for technical follow-ups on the project you choose.

  1. Tell me about a time you wrote tests for code you did not write.

Describe your experience with Object-Oriented Programming (OOP) design patterns.

Medium · Technical Foundations & OOPS

Approach

  1. Choose two or three patterns you have actually used and tell each as problem, pattern, result. For example: a switch over report types kept growing, so I introduced a Strategy interface with one class per type, and adding a type no longer meant editing existing code.
  2. Name the cost of each pattern: more classes, more indirection, harder navigation. Include one case where you decided a pattern was overkill and kept the plain code.
  3. Tie the patterns to testing and integration work. Dependency injection of a strategy lets a unit test supply a fake; an Adapter around an external API client keeps vendor types out of the domain code; a Factory centralizes construction when the concrete class depends on input.
  4. Only mention patterns you can sketch in your language: be ready to write the interface, two implementations and the calling code. Name-dropping Singleton or Observer without being able to code it hurts more than it helps.

Follow-up

  • Write the Strategy interface and two implementations for report formatting in your language.
  • What is the difference between Factory Method and Abstract Factory, or between Strategy and State?
  • When did a pattern make code worse, and how did you undo it?

Tell us about the most difficult programming project you have worked on. What was your specific contribution?

Medium · Behavioral & Culture Fit

Approach

  1. Pick a project whose difficulty was technical and nameable (a slow query, a legacy migration, a consistency bug, an integration with a flaky external API), not one that was hard only because of a deadline.
  2. Separate your contribution from the team's. Say what you designed, wrote or decided with "I", and what others did with "the team", so the listener never has to guess your part.
  3. Structure it as context in two sentences, the specific constraint that made it hard, the options you weighed and why you picked one, what you built and how you verified it (tests, a measurement, monitoring). Use only numbers you really know.
  4. Include one mistake or dead end and what you changed afterwards, and be ready to sketch the data model, class design or failing test on request. A story that collapses under a technical follow-up is the common failure.

Follow-up

  • What would you do differently if you started again?
  • How did you test that the solution actually worked?
  • Which part of the design did someone on the team disagree with, and how was it settled?

How do you handle a situation where a coworker is not meeting expectations?

Medium · Behavioral & Culture Fit

Approach

  1. Open with a private, direct conversation to understand the cause before judging: unclear requirements, overload, a skill gap or something outside work. Name what was actually observed, such as late tickets, repeated review comments or tests left failing.
  2. Describe the impact on shared work in concrete terms, then what you offered: pairing on the hard part, smaller tasks, clearer acceptance criteria, an agreed checkpoint a few days out.
  3. Escalate only after trying directly, and say how you did it: you told the coworker you would raise it, you brought facts rather than opinions, and you asked the lead for help rather than a verdict. In a self-governing team, mention using the team's own working agreements or retro.
  4. Close with the outcome and what it taught you, including if it only partly worked. Mistakes that sink the answer are complaining about the person, going around them without notice, or quietly doing their work for them.

Follow-up

  • What if they ignored your feedback?
  • When did you involve your manager and what exactly did you tell them?
  • How did you keep the working relationship afterward?

Describe your ideal work environment.

Medium · Behavioral & Culture Fit

Approach

  1. This is a preference question, not a story, so keep it short and organized in three parts: how you like to collaborate, how you like to learn, and how you like decisions to be made.
  2. Back each preference with a past example so it does not sound like a wish list. For instance, say pairing on a gnarly bug got a fix reviewed and understood in one sitting, and name the team and what happened.
  3. Candidates describe collaborative, self-governing teams that share knowledge and set aside time for learning new technologies, and pair programming appears in the loop. If those match your real preferences, say so with an example; do not echo them for effect.
  4. Show the trade-offs you can live with, such as ambiguous requirements, legacy code or shifting priorities, so the answer reads as realistic. Avoid replies that clash with a team format, like wanting to work alone with no interruptions, unless you explain how you still collaborate.

Follow-up

  • Tell me about a time you worked somewhere that was far from ideal and what you did.
  • How do you do your best work when requirements are unclear?
  • What do you need from a manager or team lead to do your best work?

How do you approach giving and receiving technical feedback during a pair programming session?

Medium · Behavioral & Culture Fit

Approach

  1. Describe the mechanics first: driver and navigator roles, switching often, the navigator keeping the larger goal in view while the driver types, and both saying their intent out loud before acting.
  2. Giving feedback: keep it small, timely and about the code. Phrase observations as questions tied to behavior ("what happens if the list is empty?") and separate must-fix issues, such as a bug or a failing test, from preferences like naming or style, where the driver decides.
  3. Receiving feedback: restate the suggestion, try it if it is cheap, and if you disagree, give a reason backed by evidence. Write a quick test or run the code rather than arguing; if it is still open, time-box it, pick one, and note it for the team to revisit.
  4. Have one concrete example of a disagreement settled in a pairing session, for instance two designs resolved by writing the failing test that exposed an edge case. The failure modes to avoid are silence, grabbing the keyboard and defensiveness.

Follow-up

  • How do you pair with someone much more or much less experienced than you?
  • Tell me about a disagreement in a pairing session that you could not resolve.
  • How do you stay useful as the navigator when you are not typing?