cswork / libraryOpen practice workspace

Interview guides · Expert Institute

Expert Institute Software Engineer Interview Guide

Expert Institute Software Engineer interview guide: reported rounds, questions and how candidates describe the process.

The 60-second brief

As a Software Engineer at Expert Institute, you will play a pivotal role in building and scaling the industry’s leading legal technology platform. Expert Institute serves as a critical bridge connecting litigation attorneys with top-tier expert witnesses, operating in a multi-billion-dollar market with immense room for expansion. Your work directly impacts how law firms evaluate cases, leverage data, and secure the insights necessary to win complex legal battles. In this role, you will tackle the unique challenges of a highly specialized, data-driven two-sided marketplace. You will help design and implement the core services that power intelligent case-matching, large-scale document processing, and advanced search systems.

This guide is scoped to a Software Engineer candidate at Expert Institute.

Focus areas

  • AWS Cloud Infrastructure
  • LLM-backed Document Processing
  • Distributed Systems Architecture

The Expert Institute interview process

Expert Institute candidates report 4 rounds over 3-5 weeks. The stages below are what candidates describe, not a published process.

Recruiter Screen

Initial discussion to align on background, career goals, and compensation expectations.

What to demonstrate

  • Initial discussion to align on background, career goals, and compensation expectations
  • Depth in AWS Cloud Infrastructure

How to prepare

  • Be able to walk your CV end to end in two minutes, and say why this company specifically.
  • Have your salary expectations, notice period and location constraints ready, and ask for the rest of the loop in writing.

Conversational Interviews

Interviews with engineering leaders to discuss technical experience, system design philosophy, and team culture fit.

What to demonstrate

  • Interviews with engineering leaders to discuss technical experience, system design philosophy, and team culture fit
  • Depth in AWS Cloud Infrastructure

How to prepare

  • Answer aloud and timed: When scaling a relational database like PostgreSQL, how do you decide between vertical scaling, read replicas, and sharding?
  • Answer aloud and timed: Describe a scenario where you would choose an asynchronous event-driven architecture over a synchronous REST API. How do you handle eventual consistency?

Practical Assessment

A weekend-long case study project simulating real-world challenges, including system architecture and production-grade code.

What to demonstrate

  • A weekend-long case study project simulating real-world challenges
  • Including system architecture and production-grade code

How to prepare

  • Answer aloud and timed: How do you approach VPC design, security groups, and IAM roles to ensure secure networking within an AWS environment?
  • Answer aloud and timed: Explain the event loop in Node.js. How do you prevent CPU-intensive tasks from blocking the main thread?

Final Round

Deep-dive technical reviews and behavioral discussions following the project submission.

What to demonstrate

  • Deep-dive technical reviews and behavioral discussions following the project submission
  • Depth in AWS Cloud Infrastructure

How to prepare

  • Answer aloud and timed: Write a SQL query to identify duplicate expert profiles based on matching metadata, and explain how you would optimize it using indexes.
  • Answer aloud and timed: How do you design and manage database migrations in a production environment with zero downtime?

Where candidates lose points

Structure your system design answers

When faced with open-ended architecture questions, use a structured framework. Start by clarifying requirements, estimating scale, defining the data model, sketching the high-level architecture, and then diving into bottlenecks and trade-offs.

Emphasize operational maturity

Do not just talk about writing code. Discuss how you monitor your services, handle errors, set up alerts, and ensure security. Showing that you think about day-two operations will set you apart.

When completing the case study, treat it as if you are submitting code to a production repository

Include a clear README explaining your architectural choices, trade-offs made due to time constraints, and how you would scale the system in a real production environment.

Show product intuition

Throughout your interviews, demonstrate that you care about the end-user. Ask questions about how features impact litigation attorneys, how users interact with the expert database, and how technical decisions influence the overall user experience.

Questions & practice

Explain the event loop in Node.js. How do you prevent CPU-intensive tasks from blocking the main thread?

Medium · Backend Development & Data Engineering

Approach

  1. Say what the runtime actually does before reasoning about the code.
  2. Name what is shared across threads and what owns each piece of state.
  3. Identify the window where an invariant is briefly untrue.
  4. Distinguish a value from a reference to it, and say which one you handed out.

Follow-up

  • What happens if two callers reach this at the same time?
  • Where could this allocate more than you expect?

Canonicalise a request body into a stable idempotency fingerprint

Medium · parsing · canonicalisation · hashing

idempotency_key.request_fingerprint is a SHA-256 over the method, path and canonicalised body, and a retry whose fingerprint differs must be rejected with 422 rather than served the stored response. Write the canonicaliser. Bodies are JSON up to 256 KB nested at most 32 levels; clients vary key order, whitespace and unicode escaping, and some send 64-bit ids as JSON numbers. Produce a deterministic byte string such that semantically identical bodies match and any semantic difference does not. State your complexity and name two normalisations you refuse to perform.

Approach

  1. Parse once into a tree, then re-serialise under fixed rules: object keys sorted, array order preserved, one escaping convention, no insignificant whitespace. Parsing is O(n) and sorting keys is O(k log k) per object, so O(n log n) overall with O(depth) stack, and the 32-level cap is enforced during parsing because hostile nesting is how a canonicaliser becomes a stack overflow.
  2. Sort keys by their UTF-8 bytes and say why the obvious implementation is wrong in some runtimes: a default string comparison that orders by UTF-16 code units places surrogate pairs, meaning code points from U+10000 up, below U+E000 to U+FFFF, which is not UTF-8 byte order, so two services written in different languages disagree on the same document.
  3. Do not re-encode numbers through a double. IEEE-754 binary64 represents integers exactly only up to 2^53, so normalising a 19-digit id through a float changes it, and 1 against 1.0 cannot be reconciled without deciding whether they are the same value. Preserve the literal token, and require ids as strings at the API boundary if you want them comparable.
  4. Reject duplicate keys rather than picking one. JSON permits them and parsers disagree, most keeping the last, so any choice you make ties the fingerprint to a parser detail that the code handling the request does not necessarily share.

Follow-up

  • A client sends the same logical request with an extra field your API ignores. Same key, different fingerprint, so you return 422. Is that the right answer?
  • Where does the fingerprint get computed relative to request decompression and the body-size limit?

Track a rolling failure rate per destination for circuit decisions

Easy · sliding window · ring buffer · circuit breaker

The egress service delivers about 1,500 webhooks per second across roughly 40,000 destinations, each call bounded by a 10 second timeout. Maintain, per destination, the failure rate over the trailing 60 seconds so a caller can ask before dispatch whether the circuit should open. Attempts arrive as (destination_id, finished_at_ms, outcome). Requirement: amortised O(1) per attempt, with total memory bounded by the destination count rather than by traffic. Give the structure, its exact memory, and the rule that stops a destination with three attempts from opening a circuit.

Approach

  1. Name the exact-deque version and then reject it as the default. Holding timestamps and advancing a tail pointer past anything older than now minus 60 seconds is a correct two-pointer window at amortised O(1) per attempt, but its memory tracks in-window traffic, so one destination in a retry storm holds hundreds of thousands of entries while thousands of quiet destinations hold none.
  2. Use a ring of 60 one-second buckets per destination, each bucket a pair of counters for attempts and failures. On an attempt, advance the ring by the elapsed whole seconds, zeroing at most min(elapsed, 60) buckets, then increment the head. That is amortised O(1) with a fixed footprint per destination.
  3. State the footprint: 60 buckets times two 4-byte counters is 480 bytes of payload per destination, so 40,000 destinations is roughly 20 to 25 MB with per-entry overhead, bounded by the catalogue rather than by the rate. The cost is granularity, since the oldest bucket ages out in whole seconds, which is far tighter than the decision needs.
  4. Require a minimum sample before the circuit may open. A destination with three attempts and three failures reads as 100 percent and is not evidence; a floor of roughly 20 attempts in the window makes the ratio meaningful, and below that floor use a run of consecutive failures as the trigger instead.

Follow-up

  • The fleet is 30 instances and each sees roughly a thirtieth of a destination's traffic. Where does the rate actually live, and what does a per-instance answer get wrong?
  • A destination answers in 9.5 seconds and succeeds. It is not failing but it is consuming your per-destination concurrency. What signal should open the circuit here?

Write a SQL query to identify duplicate expert profiles based on matching metadata, and explain how you would

Medium · Backend Development & Data Engineering

Write a SQL query to identify duplicate expert profiles based on matching metadata, and explain how you would optimize it using indexes.

Approach

  1. Name the grain you start from and join outward from it.
  2. Check whether any join is one-to-many before aggregating, or the sums inflate.
  3. Say which index the query would use, and what makes it unusable.
  4. Handle the rows that do not match: that is usually the actual question.

Follow-up

  • How does the query change if that join becomes one-to-many?
  • What happens to this when the table is ten times larger?

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 scalable notification system for a two-sided marketplace that handles real-time SMS, em

Medium · System Architecture & Distributed System

How would you design a scalable notification system for a two-sided marketplace that handles real-time SMS, email, and push notifications?

Approach

  1. Fix the scope first: who calls this, how often, and what they do when it fails.
  2. Name the read and write paths separately; they rarely have the same bottleneck.
  3. Choose a partition key and say what query it makes expensive.
  4. State the consistency you need, and where you are willing to be stale.

Follow-up

  • What breaks first when traffic grows ten times?
  • How does this behave when that dependency is down for an hour?

Explain how you would architect a high-throughput document processing pipeline that extracts text from PDFs, g

Medium · System Architecture & Distributed System

Explain how you would architect a high-throughput document processing pipeline that extracts text from PDFs, generates embeddings, and indexes them for search.

Approach

  1. Fix the scope first: who calls this, how often, and what they do when it fails.
  2. Name the read and write paths separately; they rarely have the same bottleneck.
  3. Choose a partition key and say what query it makes expensive.
  4. State the consistency you need, and where you are willing to be stale.

Follow-up

  • What breaks first when traffic grows ten times?
  • How does this behave when that dependency is down for an hour?

When scaling a relational database like PostgreSQL, how do you decide between vertical scaling, read replicas,

Medium · System Architecture & Distributed System

When scaling a relational database like PostgreSQL, how do you decide between vertical scaling, read replicas, and sharding?

Approach

  1. Fix the scope first: who calls this, how often, and what they do when it fails.
  2. Name the read and write paths separately; they rarely have the same bottleneck.
  3. Choose a partition key and say what query it makes expensive.
  4. State the consistency you need, and where you are willing to be stale.

Follow-up

  • What breaks first when traffic grows ten times?
  • How does this behave when that dependency is down for an hour?

Describe a scenario where you would choose an asynchronous event-driven architecture over a synchronous REST A

Medium · System Architecture & Distributed System

Describe a scenario where you would choose an asynchronous event-driven architecture over a synchronous REST API. How do you handle eventual consistency?

Approach

  1. Say who the caller is and what they do when the call fails halfway.
  2. Define the identity of a request so a retry cannot double-apply it.
  3. Separate accepted, pending, failed and confirmed; they are different facts.
  4. Design the error taxonomy before the success shape; callers branch on it.

Follow-up

  • What happens if the caller retries after a timeout?
  • How does a client discover it is on an old version of this contract?

How do you approach VPC design, security groups, and IAM roles to ensure secure networking within an AWS envir

Medium · System Architecture & Distributed System

How do you approach VPC design, security groups, and IAM roles to ensure secure networking within an AWS environment?

Approach

  1. Fix the scope first: who calls this, how often, and what they do when it fails.
  2. Name the read and write paths separately; they rarely have the same bottleneck.
  3. Choose a partition key and say what query it makes expensive.
  4. State the consistency you need, and where you are willing to be stale.

Follow-up

  • What breaks first when traffic grows ten times?
  • How does this behave when that dependency is down for an hour?

How do you design and manage database migrations in a production environment with zero downtime?

Medium · Backend Development & Data Engineering

Approach

  1. Fix the scope first: who calls this, how often, and what they do when it fails.
  2. Name the read and write paths separately; they rarely have the same bottleneck.
  3. Choose a partition key and say what query it makes expensive.
  4. State the consistency you need, and where you are willing to be stale.

Follow-up

  • What breaks first when traffic grows ten times?
  • How does this behave when that dependency is down for an hour?

What are the primary trade-offs between using a relational database like PostgreSQL versus a NoSQL store like

Medium · Backend Development & Data Engineering

What are the primary trade-offs between using a relational database like PostgreSQL versus a NoSQL store like DynamoDB for storing user activity logs?

Approach

  1. Clarify what is being asked and what a complete answer contains.
  2. State your assumptions explicitly before working the problem.
  3. Say what you would check first and why it is the highest-information step.
  4. Work from the requirement backwards to the design.

Follow-up

  • What assumption would you test first?
  • How would you know your answer was wrong?

p99 jumped on one listing filter while p50 stayed flat

Medium · query planning · composite index · percentiles

After a release that added an owner_user_id filter to the resource listing, p99 rose from 90 ms to 1.9 s while p50 stayed at 40 ms. Traffic and row counts are unchanged. resource carries the index (tenant_id, status, updated_at DESC, resource_id DESC). The new query filters tenant_id and owner_user_id, orders by updated_at DESC, resource_id DESC, and takes 20 rows. On PostgreSQL, explain the shape of the regression, prove it from a query plan, and give the index you would add.

Approach

  1. Start from the shape. A flat p50 with a moved p99 means a subset of requests changed cost, not all of them, so the first job is naming the subset. Bucket the endpoint's latency by the tenant's row count; the natural hypothesis is that large tenants are a small share of requests and all of the tail.
  2. Get the plan for the new query on a large tenant with EXPLAIN (ANALYZE, BUFFERS). Expect an index scan over the tenant's range, a filter discarding most of it, then a Sort feeding the Limit, possibly reporting Sort Method: external merge Disk. Read actual rows on the scan node, not estimated.
  3. Explain why the existing index cannot serve it. A composite B-tree is seekable only as a left prefix, and with no equality predicate on status the scan cannot treat updated_at as an ordering, because rows in the tenant's range are ordered by status first. Everything matching must be read and sorted before LIMIT 20 can apply, so a tenant with 400,000 rows pays 400,000 rows to return 20.
  4. Add (tenant_id, owner_user_id, updated_at DESC, resource_id DESC). Equality on the first two columns leaves the index ordered by updated_at within that pair, so the plan becomes an index scan that stops after 20 rows with no Sort node. PostgreSQL can scan a B-tree backwards, so the DESC markers matter only if the two sort columns ever disagree in direction; keeping them explicit documents the order the keyset cursor depends on.

Follow-up

  • The endpoint paginates with OFFSET. What does page 500 cost with your index, and what does the keyset version cost?
  • How would you have caught this before release, given that a 10,000-row seed database produces the same plan shape at an unnoticeable cost?

Suggested practice checklist

Built from the rounds and topics Expert Institute candidates report.

Day 1 — Map the Expert Institute loop

  • Write out the reported sequence: Recruiter Screen, Conversational Interviews, Practical Assessment, Final Round.
  • For each round, write one sentence on what it is judging, from the description above, and mark the one you are least ready for.

Deliverable: A one-page map of the 4 reported rounds, with the weakest marked.

Day 2 — Work AWS Cloud Infrastructure

  • Spend the session on AWS Cloud Infrastructure, which Expert Institute candidates report being tested on.
  • Write one worked example in AWS Cloud Infrastructure and time yourself on it.

Deliverable: One timed worked example in AWS Cloud Infrastructure.

Day 3 — Work LLM-backed Document Processing

  • Spend the session on LLM-backed Document Processing, which Expert Institute candidates report being tested on.
  • Write one worked example in LLM-backed Document Processing and time yourself on it.

Deliverable: One timed worked example in LLM-backed Document Processing.

Day 4 — Work Distributed Systems Architecture

  • Spend the session on Distributed Systems Architecture, which Expert Institute candidates report being tested on.
  • Write one worked example in Distributed Systems Architecture and time yourself on it.

Deliverable: One timed worked example in Distributed Systems Architecture.

Day 5 — Answer out loud: System Architecture & Distributed Systems

  • Answer aloud, timed: How would you design a scalable notification system for a two-sided marketplace that handles real-time SMS, email, and push notifications?
  • Answer aloud, timed: Explain how you would architect a high-throughput document processing pipeline that extracts text from PDFs, generates embeddings, and indexes them for search.

Deliverable: Spoken answers to 2 reported System Architecture & Distributed Systems question(s), under time.

Day 6 — Answer out loud: Backend Development & Data Engineering

  • Answer aloud, timed: Explain the event loop in Node.js. How do you prevent CPU-intensive tasks from blocking the main thread?
  • Answer aloud, timed: Write a SQL query to identify duplicate expert profiles based on matching metadata, and explain how you would optimize it using indexes.

Deliverable: Spoken answers to 2 reported Backend Development & Data Engineering question(s), under time.

Day 7 — Answer out loud: Behavioral & Leadership

  • Answer aloud, timed: Describe a time when you had to make a high-stakes technical decision with incomplete information. What was your process, and what was the outcome?
  • Answer aloud, timed: How do you handle a situation where a product manager proposes a feature with a tight deadline that compromises architectural integrity?

Deliverable: Spoken answers to 2 reported Behavioral & Leadership question(s), under time.

Behavioural preparation

Behavioural rounds judge the decision you made and what it cost.

Describe your experience building ETL/ELT pipelines. How do you handle data quality issues, retries, and schem

Medium · Backend Development & Data Engineering

Describe your experience building ETL/ELT pipelines. How do you handle data quality issues, retries, and schema evolution?

Approach

  1. Pick a story where you made the decision, not one where you watched it.
  2. State the situation in two sentences and spend the rest on the reasoning.
  3. Give the blast radius: what could have broken, and what you measured.
  4. Name the disagreement and how you resolved it with evidence.

Follow-up

  • What would you do differently if you ran that again?
  • How did you know your change caused the improvement?

Describe a time when you had to make a high-stakes technical decision with incomplete information. What was yo

Medium · Behavioral & Leadership

Describe a time when you had to make a high-stakes technical decision with incomplete information. What was your process, and what was the outcome?

Approach

  1. Pick a story where you made the decision, not one where you watched it.
  2. State the situation in two sentences and spend the rest on the reasoning.
  3. Give the blast radius: what could have broken, and what you measured.
  4. Name the disagreement and how you resolved it with evidence.

Follow-up

  • What would you do differently if you ran that again?
  • How did you know your change caused the improvement?

How do you handle a situation where a product manager proposes a feature with a tight deadline that compromise

Medium · Behavioral & Leadership

How do you handle a situation where a product manager proposes a feature with a tight deadline that compromises architectural integrity?

Approach

  1. Pick a story where you made the decision, not one where you watched it.
  2. State the situation in two sentences and spend the rest on the reasoning.
  3. Give the blast radius: what could have broken, and what you measured.
  4. Name the disagreement and how you resolved it with evidence.

Follow-up

  • What would you do differently if you ran that again?
  • How did you know your change caused the improvement?

Give an example of how you have mentored a junior or mid-level engineer. How did you help them level up their

Medium · Behavioral & Leadership

Give an example of how you have mentored a junior or mid-level engineer. How did you help them level up their technical skills?

Approach

  1. Pick a story where you made the decision, not one where you watched it.
  2. State the situation in two sentences and spend the rest on the reasoning.
  3. Give the blast radius: what could have broken, and what you measured.
  4. Name the disagreement and how you resolved it with evidence.

Follow-up

  • What would you do differently if you ran that again?
  • How did you know your change caused the improvement?

Tell me about a production incident you were responsible for resolving. How did you diagnose the issue, and wh

Medium · Behavioral & Leadership

Tell me about a production incident you were responsible for resolving. How did you diagnose the issue, and what did you implement to prevent it from happening again?

Approach

  1. Pick a story where you made the decision, not one where you watched it.
  2. State the situation in two sentences and spend the rest on the reasoning.
  3. Give the blast radius: what could have broken, and what you measured.
  4. Name the disagreement and how you resolved it with evidence.

Follow-up

  • What would you do differently if you ran that again?
  • How did you know your change caused the improvement?

How do you balance the need to ship features quickly with the responsibility of maintaining high engineering s

Medium · Behavioral & Leadership

How do you balance the need to ship features quickly with the responsibility of maintaining high engineering standards and reducing technical debt?

Approach

  1. Pick a story where you made the decision, not one where you watched it.
  2. State the situation in two sentences and spend the rest on the reasoning.
  3. Give the blast radius: what could have broken, and what you measured.
  4. Name the disagreement and how you resolved it with evidence.

Follow-up

  • What would you do differently if you ran that again?
  • How did you know your change caused the improvement?