cswork / libraryOpen practice workspace

Interview guides · AdeptID

AdeptID Software Engineer Interview Guide

AdeptID Software Engineer interview guide: six reported rounds, matching-service design, SQL, testing and behavioral questions, plus a 7-day prep plan.

The 60-second brief

AdeptID builds Talent Matching Software, a product that connects people with career opportunities and is described as aiming to cut bias and friction when employers hire. The role description candidates see lists matching algorithms, data pipelines and infrastructure used by partner organisations as areas a Software Engineer touches. It also describes working with product managers to turn user needs into technical requirements, writing production code, reviewing other engineers' code, joining architecture discussions and improving deployment pipelines.

This guide is for candidates interviewing for a Software Engineer position at AdeptID, including the Senior track where candidates describe a record of owning technical projects as expected. It covers the six reported rounds, the twelve reported questions (design, SQL, testing, debugging and behavioral), and a seven-day schedule. Every reported question, technical and behavioral, has its own guidance, follow-up questions and a plan day.

Candidates report six rounds over roughly four to six weeks: Technical Screen, System Design Interview, Coding Interview, Behavioral Interview, Final Round and Offer Discussion. The Final Round is described as a set of conversations with several team members.

Focus areas

  • Ranking & Scoring Systems
  • Talent Matching Software Domain
  • Recommender Systems Concepts

Overview

Most reported design questions can be framed as one kind of service: it takes a person or a role, retrieves candidates from skill data, scores and ranks them, and returns results quickly. That is this guide's reading of the questions, not a description of AdeptID's product. The design questions ask about a real-time matching service, database choices for skill-based talent data, a microservice that integrates with third-party job boards, and protecting sensitive applicant information. Prepare one reusable architecture sketch with a request path, a retrieval stage, a scoring stage, a cache, a store and an ingestion path, then bend it to each question.

The remaining technical questions are about operating that system. One asks how you would optimize a slow-running query in a high-volume production environment, one how you would test edge cases in a complex algorithmic matching system, and one how you would find the root cause of a latency spike. Candidates also report topic areas of ranking and scoring, recommender concepts, and search and retrieval, so be ready to explain how a score is computed, how a ranked list is evaluated, and what changes when the input data is sparse, duplicated or skewed.

The behavioral side is not an afterthought. Five reported questions cover refactoring a legacy system without downtime, disagreeing with a peer or manager, trading speed against quality, handling shifting product direction at a startup, and mentoring or improving documentation. Candidates also say the role expects you to explain the reasons behind your architectural choices, so each story needs a decision, its alternatives, and a result you can state honestly.

Requirements candidates describe name a modern backend language, relational databases and cloud-native development, with machine learning pipelines, data-intensive applications and HR-tech experience listed as extras. Python, SQL and cloud infrastructure appear as examples of the ecosystem. Refresh the mechanics of whichever language you will code in, and be able to read a query plan without help.

The AdeptID interview process

These are the six stages candidates describe, in the order they report them. Which questions appear in which stage is not reported, so prepare every question type for the stage that matches its format.

Technical Screen

Candidates describe the Technical Screen as an initial assessment of baseline skills in technical areas. Nothing more specific about its format or length is reported. Prepare for fundamentals in the areas on your resume: the language and database you name, complexity analysis, and how you reason about a production service. Be ready to talk through a design or query problem aloud.

What to demonstrate

  • Baseline command of the technical areas on your resume
  • Fluency with data structures, complexity and the mechanics of your main backend language
  • Ability to explain a technical choice in plain, ordered steps

How to prepare

  • Re-read every project on your resume and write one sentence on why each technology was chosen
  • Practise explaining how you would optimize a slow-running query: read the plan, check indexes, check row estimates, then change the query or schema
  • Work the real-time matching service question as a spoken outline so a short design prompt does not catch you cold

System Design Interview

The System Design Interview is reported as an in-depth discussion of system design and architecture. The architecture areas candidates report for this role are scalability and traffic spikes, data modeling for structured versus unstructured data, and consistency versus availability. The design questions reported for this loop include the real-time matching service, database architectures for skill-based talent data, the microservice for third-party job boards, and applicant data privacy, so prepare one sketch you can adapt.

What to demonstrate

  • Scalability reasoning, including how the design behaves under traffic spikes
  • Data modeling and storage choices for skill and applicant data
  • Consistency versus availability trade-offs stated explicitly
  • Security and privacy handling for sensitive records

How to prepare

  • Draw the matching-service sketch: API, retrieval from a skills store or search index, scoring stage, cache, ingestion path, and the place where staleness is acceptable
  • Write a comparison of a relational store, a document store and a search index for skill-based data, with the query each makes cheap and the one it makes expensive
  • Outline the job-board integration service: per-board adapters, retries with backoff, rate limits, idempotent ingestion, and what happens when a board is down
  • List privacy controls for applicant data: field-level access, encryption in transit and at rest, audit logging, retention, and test data that contains no real records

Coding Interview

Candidates describe the Coding Interview as a hands-on session for problem-solving and coding skill. The technical areas reported for coding are code quality, testing strategy across unit, integration and end-to-end levels, and performance tuning through Big O analysis. Reports stress that fundamentals count at every level, so do not skip data structures and complexity. The testing question about edge cases in a matching system is the closest reported match to this format.

What to demonstrate

  • Working, readable code in a language you choose carefully
  • Correct complexity analysis and awareness of bottlenecks
  • Tests you write or describe for normal and edge inputs

How to prepare

  • Solve the archive-a-resource-graph and merge-partitioned-event-streams practice problems in one language and state time and space complexity after each
  • Build an edge-case table for a ranking function: empty candidate list, ties in score, missing skills, duplicate candidates, one very large candidate pool
  • Practise narrating while you type: restate the input, name the brute-force version, then improve it
  • Review one SQL practice problem on join fan-out so a query question does not inflate counts

Behavioral Interview

Reports describe the Behavioral Interview as a conversation judged on how you communicate and how your behavior fits the team. Candidates are advised to structure answers with Situation, Task, Action and Result. Five behavioral questions are reported for this loop: refactoring a legacy system, disagreeing with a technical decision, speed versus quality, changing requirements at a startup, and mentoring or documentation. Which of them appear in this round and which in the Final Round is not reported, so prepare all five.

What to demonstrate

  • Clear communication of technical decisions
  • Ownership of outcomes, including the ones that went badly
  • Collaboration under disagreement and shifting priorities

How to prepare

  • Write a one-page STAR outline for each of the five reported questions, using five different projects where you can
  • For each story, add the number or observable result and one thing you would change
  • Rehearse the stories aloud and cut each to the decision and its reasoning, not the backstory
  • Prepare an answer for the resume deep-dive: why each major technical choice was made and what you rejected

Final Round

Candidates describe the Final Round as concluding interviews with multiple team members for a holistic evaluation. It is several conversations, and the topics they cover are not reported. Because of that, keep your design sketch, your technical depth on your own projects and your behavioral stories all ready rather than guessing which will come up.

What to demonstrate

  • A holistic evaluation across several team members, as reported
  • Whatever the earlier rounds covered, since the topics here are not reported

How to prepare

  • Keep one story bank and one architecture sketch so your answers agree no matter who asks
  • Prepare two or three questions per conversation about the team's matching, data pipelines and deployment process
  • Review all twelve reported questions once more in the days before this round
  • Prepare how you would explain a ranking trade-off to a product manager without jargon

Offer Discussion

The Offer Discussion is reported as a conversation about the job offer and next steps. Reports do not say whether it includes any technical exercise. Use it to confirm scope and expectations of the role, such as which of the described responsibilities are yours first, and to settle the practical details of starting.

What to demonstrate

  • Clear communication about what you need to decide
  • Understanding of the role's scope and the next steps

How to prepare

  • Write a list of questions about team structure, what the first projects are, and how code review and deployment work
  • Decide in advance which terms matter most to you and what you need to know before responding
  • Keep notes from earlier rounds so you can ask follow-ups about topics that came up

Where candidates lose points

Drawing a generic web service for the real-time matching question, with no retrieval or scoring stage

Practise the sketch with a candidate retrieval step, a separate ranking step, a cache, and an ingestion path that keeps skill data current. State which part tolerates stale results and which does not.

Answering the slow-query question with 'add an index' before reading a plan

Describe the sequence: capture the actual query, run EXPLAIN with analysis, compare estimated and actual rows, check join order and fan-out, then change the index, query or data shape. Name how you verify improvement and protect writes.

Treating the job-board integration as a single happy-path API call

Cover per-board adapters, normalised internal records, retries with backoff, rate-limit handling, idempotent writes, dead-letter handling and monitoring of each board separately, since third parties fail independently.

Giving behavioral stories with no decision, no cost, or no result

For each of the five reported questions, write the decision, the alternative you rejected, what it cost and how you measured the result. Cut background so the reasoning takes most of the answer.

Describing edge-case testing as 'I would write more unit tests' for the matching system

Bring concrete cases: ties in score, empty or huge candidate pools, missing or duplicate skills, stale data. Add property checks on ranking order and a regression set of known good matches.

Questions & practice

How do you approach testing for edge cases in a complex algorithmic matching system?

Medium · Problem-Solving & System Design

Approach

  1. Unit-test the pure scoring functions against small hand-computed cases. Keep scoring free of I/O so each piece (skill overlap, weighting, normalisation) can be checked with exact expected values.
  2. Write property-based tests (Hypothesis in Python, for example) for invariants that must hold for any input: scores stay within the defined range, the same input always gives the same output, ties are broken by a documented deterministic rule, and properties your spec states hold, such as adding to a candidate's profile a skill the job requires never lowering that candidate's score. Adding a required skill to the job can legitimately lower scores, so state whose skill list changes.
  3. Enumerate the edge inputs explicitly. Cover an empty profile or a job with no skills, a skill missing from the taxonomy, duplicate skills, casing and synonyms, Unicode, very long skill lists, zero candidates, every candidate tied, missing location, and None or NaN in numeric features.
  4. Keep a golden set of candidate-job pairs with expected orderings as a regression suite. Between versions, compare the top-k overlap and a ranking metric such as NDCG so an intentional improvement is distinguishable from accidental drift.
  5. Add metamorphic and fairness checks. Changing a field that should be irrelevant (a name, for example) must not change the score, and on an evaluation set compare outcome rates across groups. Then test performance at worst-case input size, and run a new version in shadow mode against live traffic before it serves results.

Follow-up

  • There is no single correct ranking. How do you decide a test has failed?
  • A change improves the offline metric but a partner reports worse matches. How do you investigate?
  • How do you make a component with randomness or a trained model reproducible enough to test?

Archive a resource graph without breaking live references or recursing

Medium · graph traversal · topological order · tenant isolation

Resources reference other resources within a tenant; for the largest tenant the reference table holds up to 2,000,000 nodes and 8,000,000 edges. Archiving a resource must archive everything reachable from it that nothing outside the set still references, refuse when a live external referrer exists, and terminate when references form cycles, which they legitimately do. Produce the archive order and the refusal list, targeting O(V+E). Say what stops the traversal crossing a tenant boundary, and why recursion is the wrong control structure at this size.

Approach

  1. Load the subgraph with the tenant predicate on both endpoints of the edge, not only on the side you started from. Scoping the left table alone is the classic cross-tenant leak: one mis-entered edge then pulls another tenant's resources into the traversal and, worse, into the archive.
  2. Traverse iteratively with an explicit stack. A 2,000,000-node graph can hold a chain deep enough to exhaust a native stack in the low tens of thousands of frames, and that failure is a process crash rather than an error you can return.
  3. Treat cycles as data rather than corruption: compute strongly connected components with Tarjan in O(V+E) using its own explicit stack, then condense. The condensation is a DAG, so a topological order over it gives the archive order, and every member of a component archives in one transaction because no order within a cycle is valid.
  4. Decide refusals with reverse edges. A candidate is archivable only if every in-edge originates inside the candidate set, so build the transpose or count in-degrees restricted to the visited set, and emit each blocked resource with the id of the external referrer, which is the only part of the answer an operator can act on.

Follow-up

  • The graph is read in one query and the archive writes a minute later. What can change in between, and how do you make the write safe?
  • The candidate set is 400,000 resources. Is that one transaction, and if not, what does a half-finished archive look like to a reader?

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?

Can you explain how you would optimize a slow-running query in a high-volume production environment?

Medium · Technical & Domain Expertise

Approach

  1. Confirm which query is slow and how much it costs in total. Use the slow query log or pg_stat_statements (total time = mean time x calls), since a 5 ms query run a million times can matter more than one 3-second query. Reproduce it with real bind parameter values, because plans can differ by value.
  2. Read the plan with EXPLAIN (ANALYZE, BUFFERS). ANALYZE really executes the statement, so run writes inside a transaction you roll back, or use a replica. Look for sequential scans on large tables, estimated rows far from actual rows (stale statistics: run ANALYZE), nested loops over many outer rows, and sorts or hashes spilling to disk.
  3. Fix the access path. Build a composite index with equality columns first and the range or ORDER BY column last, or a covering index (INCLUDE) for an index-only scan. Remove what makes an index unusable: a function or implicit cast on the indexed column, or a leading-wildcard LIKE '%term'. Replace deep OFFSET pagination with keyset pagination, select only the columns you need, and collapse ORM N+1 loops into one query.
  4. Change production safely. In Postgres, CREATE INDEX CONCURRENTLY avoids blocking writes (it cannot run inside a transaction block and is slower). Every new index adds write cost, so check the insert rate. Test on a production-sized copy and compare p95 before and after.
  5. If the query is inherently heavy, move the work: cache the result, precompute it in a materialized view or summary table on a schedule, or send reporting reads to a replica or warehouse instead of the transactional primary.

Follow-up

  • The same query became slow overnight with no deploy. What could have changed?
  • The new index fixed the read but inserts slowed down. How do you decide what to keep?
  • The query is fast when run alone but slow under production load. What do you check next?

Stop tag and share joins from fanning out a page

Medium · join fan-out · semi-joins · many-to-many

resource_tag is (resource_id, tag_id) with PK (resource_id, tag_id); resource_share is (resource_id, shared_with_user_id, permission). The tagged-and-shared listing inner-joins resource to both, filters tenant_id, tag_id = ANY($2) and shared_with_user_id = $3, orders by updated_at DESC and takes 50. Pages come back with fewer than 50 distinct resources and the total in the header is far too high. Explain the row multiplication, rewrite both the page query and the count query so each is correct, and name the index each one needs. PostgreSQL 16.

Approach

  1. Do the arithmetic against the predicates that are actually there. An inner join emits one row per matching child row, and both joins are filtered: tag_id = ANY($2) admits only the requested tags, shared_with_user_id = $3 admits one user's share rows. So a resource holding three of the requested tags and shared with $3 once yields three rows, not one — the multiplier is its count of matching tags times its share rows for that single user, and that second factor is 1 unless the table admits duplicate (resource_id, shared_with_user_id) pairs. LIMIT 50 then limits rows rather than resources, and COUNT(*) counts pairs — the header is the product, not the population.
  2. Reject DISTINCT as the fix. It deduplicates after the product has been built, so the planner must materialise and sort the fanned-out set before the LIMIT can apply, and it leaves any SUM or AVG in the same select list wrong.
  3. Rewrite both filters as semi-joins, keeping resource as the only row source: AND EXISTS (SELECT 1 FROM resource_tag rt WHERE rt.resource_id = r.resource_id AND rt.tag_id = ANY($2)) and the same shape against resource_share. A semi-join stops at the first match per resource and preserves the driving index order, so ORDER BY updated_at DESC, resource_id DESC LIMIT 50 still stops after 50 rows.
  4. Count with the same predicates and no join at all: SELECT count(*) FROM resource r WHERE r.tenant_id = $1 AND r.status = 'active' AND EXISTS (...) AND EXISTS (...). Nothing multiplies a resource, so the number is the population.

Follow-up

  • The filter changes from 'any of these tags' to 'all of these tags'. Rewrite it and state what it costs relative to the ANY form.
  • A resource can be shared with the same user twice under different permissions. Does your count change, and should it?

How would you design a service to handle real-time matching requests for thousands of users?

Medium · Technical & Domain Expertise

Approach

  1. Clarify what a match request returns (ranked jobs for a candidate, or ranked candidates for a job), the latency target and the peak request rate. Thousands of users is a modest load: a few stateless API replicas behind a load balancer handle it, so say early where you will not overbuild.
  2. Split matching into two stages. Retrieval narrows the pool cheaply with an inverted index from skill to entity, or an approximate nearest-neighbour index over embeddings. Scoring then ranks only those candidates, and a size-k heap keeps the top k in O(n log k).
  3. Move expensive work off the request path. A batch or event-driven job computes features and embeddings ahead of time, so the online path is just lookup plus scoring. Cache results per user, keyed by profile version with a TTL, and invalidate them when a profile-updated or job-updated event arrives.
  4. If a request can exceed the latency budget, make it asynchronous: enqueue it, return a request id, and deliver the result by polling, SSE or a websocket. Workers scale horizontally on queue depth.
  5. Plan for failure. Set a timeout on every dependency, fall back to the last cached or a non-personalised list when scoring is down, and make requests idempotent. Track p50 and p99 latency per stage so you can see whether retrieval or scoring is the slow part.

Follow-up

  • A new job posting has to appear in match results within a minute. What changes in the pipeline?
  • How would you record why a candidate was ranked where they were, so a partner can audit a result?
  • Traffic grows 100x. Which component breaks first, and how do you scale it?

What are the trade-offs between different database architectures for storing and querying skill-based talent d

Medium · Technical & Domain Expertise

What are the trade-offs between different database architectures for storing and querying skill-based talent data?

Approach

  1. Relational model as the source of truth: people, skills and a person_skill(person_id, skill_id, level) junction table with a composite index on (skill_id, person_id). Finding people who have all of skills A, B and C becomes WHERE skill_id IN (...) GROUP BY person_id HAVING COUNT(DISTINCT skill_id) = 3. You get foreign keys, transactions and one place to rename a skill.
  2. Document store: each profile is one document with an embedded skills array. A whole profile reads in one fetch, and uneven resume shapes fit without migrations. The cost is that cross-profile queries and taxonomy changes (merging two skill names) mean touching many documents, and integrity rules move into application code.
  3. Graph model: skill-to-related-skill and occupation-to-skill edges make multi-hop questions natural, such as which roles are reachable from this skill set. Bounded hops can also be done with recursive CTEs in a relational database, so a graph store only pays off when traversals are deep and frequent.
  4. Search and vector indexes: an inverted index (BM25 relevance, facets, fuzzy matching on free-text skills) or a vector index (HNSW-style ANN over embeddings) answers similarity queries a B-tree cannot. Treat both as derived, eventually consistent copies, not the system of record.
  5. Recommend a combination and name the cost. A common answer is relational for writes and integrity, plus a search or vector index fed by change data capture or an outbox table. The price is sync lag and the dual-write problem, so explain how you detect and repair index drift.

Follow-up

  • A skill is renamed or two skills are merged in the taxonomy. What has to change in each store?
  • How do you keep the search index consistent with the primary database after a failed sync?
  • How would the schema change if skill proficiency had to be stored with a history over time?

How do you ensure data integrity and privacy when handling sensitive applicant information?

Medium · Technical & Domain Expertise

Approach

  1. Classify the data first. Identifying fields (name, email, phone), sensitive attributes (demographics, anything protected) and derived data (scores, embeddings) need different handling. Minimise what you collect, and keep PII in a separate store or table keyed by a surrogate id so matching can run on pseudonymised records.
  2. Encrypt everywhere. Use TLS in transit and encryption at rest with keys held in a KMS (envelope encryption, scheduled key rotation). Add field-level encryption or tokenisation for the most sensitive columns, so a database dump or a leaked replica does not expose them in plaintext.
  3. Control access. Apply least-privilege roles and per-tenant isolation (row-level security or a tenant_id enforced in every query path) so one partner cannot read another's applicants. Keep secrets in a secrets manager and write an audit log of who read which record.
  4. Integrity: enforce rules in the database (NOT NULL, foreign keys, unique constraints, CHECKs) as well as at the API boundary with schema validation. Wrap multi-row changes in transactions, and use idempotency keys or natural-key upserts on ingestion so retries do not create duplicate applicants.
  5. Retention and deletion: define retention periods and make deletion reach every copy (replicas, search indexes, caches, analytics exports, backups by expiry). Keep PII out of application logs, and mask or synthesise data in non-production environments.

Follow-up

  • An applicant asks to be deleted. List every place their data lives and how you remove it from each.
  • How would you keep demographic data for fairness auditing without letting it reach the matching model?
  • How would you prove to a partner that their applicants are isolated from other partners' data?

Walk me through how you would architect a microservice to integrate with third-party job boards.

Medium · Problem-Solving & System Design

Approach

  1. Put one adapter per job board behind a common interface (fetch, normalise, publish) that maps into a single canonical internal job schema. Store each raw payload alongside the normalised record so you can replay it when a mapping bug is fixed.
  2. Choose the ingestion mode per board. Pull boards get scheduled polling with a stored cursor or updated-since timestamp. Push boards get webhooks: verify the signature, acknowledge quickly and enqueue. A queue between fetching and processing lets workers scale and absorbs bursts.
  3. Build in reliability. Give each board its own rate limiter (token bucket) to respect its quota. Retry only retryable failures (429, 5xx, timeouts) with exponential backoff and jitter, add a circuit breaker per board, and send records that keep failing to a dead-letter queue for inspection.
  4. Make writes idempotent by upserting on a unique (board_id, external_id) key, so redelivered webhooks and re-polls do not create duplicates. Detect the same job posted on several boards with a normalised fingerprint (company, title, location), and keep that as a separate step from ingestion.
  5. Handle drift and operations. Validate incoming payloads, quarantine invalid ones instead of crashing the pipeline, and run contract tests per adapter. Keep OAuth tokens and API keys in a secrets manager with automatic refresh. Publish job created, updated and closed events for downstream services, and monitor ingestion lag and error rate per board.

Follow-up

  • One board's API is down for six hours. What happens during the outage, and how do you catch up afterwards?
  • A board ships a breaking API version change. How do you roll the adapter forward without losing data?
  • How do you detect that a job closed on the board when the board never sends a deletion?

If a critical service latency spikes, what is your systematic approach to identifying and resolving the root c

Medium · Problem-Solving & System Design

If a critical service latency spikes, what is your systematic approach to identifying and resolving the root cause?

Approach

  1. Scope it before forming a theory. Is it p50 or only p99? Which endpoints, all hosts or one, and when exactly did it start? Line the start time up against deploys, config or feature-flag changes, traffic shifts and dependency incidents. If users are hurting, mitigate first (roll back, scale out, shed load) and investigate in parallel.
  2. Work through the metrics systematically. Check RED (rate, errors, duration) per service and USE (utilisation, saturation, errors) per resource: CPU, memory and GC pauses, connection-pool wait time, thread or worker queue depth, disk and network I/O.
  3. Use distributed tracing to find which span grew: a database query, a downstream call or in-process work. Then follow that lead into the slow query log, lock waits, cache hit rate, or retry storms, where client retries multiply load on an already struggling dependency.
  4. Test one hypothesis at a time. Compare a slow trace with a fast one, take one suspect host out of rotation, or reproduce in staging. Treat the cause as confirmed only when the fix brings the metric back to baseline and a reversal brings the spike back, or the mechanism is directly observed.
  5. Separate the trigger from the root cause in the write-up. Add an alert on the leading indicator (pool wait time, queue depth) rather than only on latency, and add a load test or a guard (timeouts, retry budgets, bulkheads) so the same failure mode cannot recur silently.

Follow-up

  • p99 rose sharply while p50 stayed flat. What does that point to?
  • You rolled back the latest deploy and latency stayed high. What do you look at next?
  • How do you stop client retries from turning a slow dependency into an outage?

Suggested practice checklist

Each day targets reported questions and the stack candidates list: matching-service design, SQL, testing, debugging, then the five behavioral stories. The last day is a full run-through of the six reported rounds.

Day 1 — Map the loop and your own projects

  • Write the six reported rounds in order, and next to each the question types you expect to practise for it.
  • List every project on your resume with the technology, one design decision, and one result you can state.
  • Time yourself on the matching-service outline and on reading one EXPLAIN plan, then pick the weaker one to spend extra time on.

Deliverable: A one-page loop map plus a project inventory, with the weaker of the two timed drills marked.

Day 2 — Design the real-time matching service

  • Sketch a matching service on one page: API, candidate retrieval, scoring stage, cache, store, and the ingestion path.
  • Write a comparison of a relational database, a document store and a search index for skill-based talent data, naming the query each makes expensive.
  • Write a skill-overlap score, compare offline ranking metrics (precision@k, recall@k, NDCG), and explain cold start for new candidates or new jobs. Note when content-based matching beats collaborative filtering for job matching.
  • Say aloud where you accept stale results and how you would tell when results are wrong.

Deliverable: A one-page matching-service diagram, a three-column storage comparison table, and a short note on scoring, ranking metrics and cold start.

Day 3 — Protect applicant data and tune slow queries

  • Write a checklist of controls for sensitive applicant data: access, encryption, audit logging, retention, test data.
  • Take one slow query you wrote before and walk through its plan, noting index choices, row estimates and join order.
  • Do the SQL practice problem on join fan-out and note how the counts inflate and how you stop it.

Deliverable: A privacy checklist, an annotated query plan with a before-and-after change, and a solved fan-out problem.

Day 4 — Integrations and latency incidents

  • Outline a microservice that ingests listings from several third-party job boards, covering adapters, retries, rate limits and idempotency.
  • Write an incident runbook for a latency spike: confirm the symptom, find what changed, check dependencies and saturation, then isolate the cause.
  • Say aloud how you would separate the trigger of a spike from its root cause.

Deliverable: An integration-service outline and a one-page latency runbook.

Day 5 — Coding practice and edge-case testing

  • Solve the archive-a-resource-graph problem in your chosen language and state its time and space complexity.
  • Solve the merge-partitioned-event-streams problem, handling late events and empty streams.
  • Build an edge-case test table for a ranking function covering ties, duplicates, missing skills and very large pools.

Deliverable: Two working solutions with complexity notes and a written edge-case test matrix.

Day 6 — Behavioral stories, part one

  • Write STAR outlines for the legacy refactor, the technical disagreement and the speed-versus-quality stories, each from a different project.
  • Add a measurable result and one thing you would change to each story.
  • Record yourself telling each story and cut it down to the decision and its reasoning.

Deliverable: Three STAR outlines with results, and a recording of each told aloud.

Day 7 — Behavioral stories, part two and a full run-through

  • Write STAR outlines for the changing-requirements story and the mentoring or documentation story.
  • Run a spoken pass through all six rounds: one design sketch, one coding problem, one query explanation, and two stories.
  • Write your questions for the team conversations and for the offer discussion.

Deliverable: Two more STAR outlines, a completed spoken run-through, and a list of questions for the team.

Behavioral stories for the AdeptID loop

The reported behavioral questions focus on engineering judgement rather than personality: refactoring safely, disagreeing with evidence, trading speed for quality, absorbing shifting direction, and helping other engineers. Candidates are advised to use the STAR structure. For each story, make sure it shows a decision you made, the alternative you passed on, and a result you can describe honestly.

Describe a time you had to refactor a legacy system; how did you manage the technical debt while maintaining u

Medium · Problem-Solving & System Design

Describe a time you had to refactor a legacy system; how did you manage the technical debt while maintaining uptime?

Approach

  1. Choose a system you personally migrated or rewrote in stages. Describe the pain in two sentences (for example, a module nobody could change safely) and spend most of the answer on how you made the change reversible.
  2. Name the safety mechanisms: characterization tests that pinned current behaviour before you touched it, feature flags to route a small share of traffic to the new path, and shadow or dual-run comparison of old and new outputs.
  3. For a database, describe expand-contract steps: add the new column or table, write to both, backfill, switch reads, then remove the old structure. Say why that keeps uptime intact and how you rolled back.
  4. Explain how you ranked the debt: by how often the area changed and how much risk it carried, not by ugliness. State what you deliberately left alone.
  5. Close with measurable results: error rate, latency or incident count before and after, and the lesson. The story fails if it is a single big-bang rewrite with no rollback plan.

Follow-up

  • How did you decide the rewrite was worth doing rather than patching?
  • What was your rollback plan, and did you ever use it?
  • How did you keep feature work moving while the refactor was in flight?

Tell me about a time you disagreed with a technical decision made by a peer or manager. How did you resolve it

Medium · Behavioral & Values

Tell me about a time you disagreed with a technical decision made by a peer or manager. How did you resolve it?

Approach

  1. Pick a real disagreement about a technical choice, such as a queue versus a synchronous call, or a schema shape. State both positions fairly in a sentence each so the listener sees you understood the other view.
  2. Show how you brought evidence rather than opinion: a small prototype, a benchmark, an incident log, or a written comparison of costs. Say what the data showed, including if it supported the other side.
  3. Describe the resolution mechanism: you agreed on a decision criterion, asked a third engineer to review, or ran a time-boxed trial. If you were overruled, say that you committed fully to the outcome and what you did to help it work.
  4. Give the result and what you learned about arguing technical points. Avoid casting the other person as the problem, and avoid a story where you simply deferred and had no view.

Follow-up

  • What would have changed your mind in that disagreement?
  • Looking back, who was right, and how do you know?
  • How did the working relationship afterward compare with before?

Describe a project where you had to balance speed-to-market with code quality.

Medium · Behavioral & Values

Approach

  1. Choose a project with a hard deadline where you made explicit scope calls. Name the date or event driving it and the quality bar you refused to cut, such as tests on the data-handling path, a stable public API, or monitoring.
  2. List what you deliberately shortened: skipped optimisation, a manual step, a narrower feature set. Say that the debt was recorded as tickets with owners, not left as a vague intention.
  3. Explain how you judged risk: which parts were hard to change later (schemas, public interfaces) and so got care, and which were cheap to redo and so shipped fast.
  4. Report the outcome honestly, including the cost of the shortcut when you paid it back, and what you would do differently. Claiming there was no trade-off at all makes the story unconvincing.

Follow-up

  • How did you decide which shortcut was safe and which was not?
  • Did the deferred work ever get done, and how did you make sure of it?
  • How did you explain the trade-off to the product manager or stakeholder?

How do you handle changing requirements in a startup environment where the product direction may shift?

Medium · Behavioral & Values

Approach

  1. Open with a concrete case where priorities shifted mid-build, and say what changed and who changed it. Do not complain about the change; the story is about your mechanism for absorbing it.
  2. Describe how you keep the design flexible where change is likely: for a matching product that might be ranking rules or data sources behind a narrow interface, while stable parts such as storage and API contracts stay fixed.
  3. Show how you manage the human side: you wrote down the assumptions the current plan rested on, confirmed the new priority with the product manager, and stated what the shift did to the timeline and which work was now wasted.
  4. Say how you avoided thrash: short iterations, demoing early, and asking what evidence would settle the direction before building. End with the result and what you would set up earlier next time.

Follow-up

  • What did you throw away, and how did you feel about it?
  • How do you tell a real change in direction from a passing request?
  • How do you keep a codebase maintainable when requirements keep moving?

Tell me about a time you mentored a junior engineer or improved team documentation.

Medium · Behavioral & Values

Approach

  1. Pick one specific person or document. For mentoring, name the gap (for example, writing safe database migrations) and the pattern you used: pairing on a first change, then review comments that explained why rather than just what.
  2. For documentation, say what was missing and who was blocked by it. Describe what you wrote, such as an onboarding guide, a runbook for an on-call alert, or an architecture note, and where it lives so it stays near the code.
  3. Show the effect with evidence you actually have: the junior engineer shipping an independent change, fewer repeated questions in chat, a new hire using the runbook. Do not invent numbers.
  4. Explain how you kept it going: a review checklist, an owner for the doc, or a regular check-in. The story weakens if the help is vague or if it only shows you doing the work for them.

Follow-up

  • How did you adjust your approach to how that person learned?
  • How did you keep the documentation from going stale?
  • What did mentoring teach you about your own technical habits?