For hiring managers and recruiters

Interview candidates on the work they'll actually do.

Mirror turns your codebase into anonymized problems that reflect your team's day-to-day work, each with a rubric. Weak fits show up early, and strong candidates stand out.

Candidates never see your code. Every problem is anonymized.

How it works

Set up once per repo. Reuse it for every role.

01

Connect a repo

We never change it or run it.

02

We anonymize it

Your system becomes a generic spec with every name removed.

03

Pick a role

We focus on the parts of the system that role touches.

04

Send the screen

3 to 5 problems with rubrics, graded as answers arrive.

Why not a generic coding test?

Puzzles measure practice. Mirror measures fit for your system.

Generic testMirror
RelevancePuzzles unlike the jobBuilt from your real system
SignalRewards memorized patternsNeeds reasoning, not recall
CalibrationOne level for everyoneTuned to seniority
GradingPass/fail or gut feelWeighted rubric, set up front
EffortWritten by handGenerated per role

Privacy and security

Candidates only see problems. Rubrics and solutions stay with you.

Repo left untouched

Never writes to your repo or runs your code.

Isolated and encrypted

Files encrypted per company, or no raw code kept at all.

Anonymized first

Names, tables, routes and hosts are stripped. We generate from anonymized code, never raw text.

Leak-checked

Every output is scanned for your identifiers. Any hit is blocked.

A sample problem set

Generated from an open-source Python app. First problem shown with its rubric.

Backend engineer senior 4 problems

Backend engineer owning the request-handling API and the data-access layer.

Design question 40 min

Making entry listing scale past a few million rows

You own the Content entry API in a Python service backed by a relational database. List endpoints accept limit and offset, return a total count, and serialize each entry through the Request and response schemas, which compute per-viewer fields: whether the caller bookmarked the entry, the bookmark count, and whether the caller subscribes to the author. The content entry table now holds about 3 million rows and the list endpoint serves roughly 40 requests per second, mostly anonymous. The 95th percentile latency has climbed from 80 ms to 900 ms over six months, and the database shows many small queries per request alongside one slow count over the filtered set. Product also wants a personal feed of entries from authors the caller subscribes to, with the same filters on labels and authors. Propose how you would restructure the query path, the pagination contract and the computation of per-viewer fields so the endpoint scales to 30 million entries. State which of your changes alter the API contract, how you would roll them out without breaking existing clients, and what you would measure to prove each change helped.

Rubric
Diagnosis
Identifies N+1 serialization and the unbounded count as the two distinct causes.
25%
Query design
Proposes concrete batched or annotated queries and supporting indexes.
30%
Pagination and contract
Handles cursor paging and the total-count trade-off with a rollout plan.
25%
Measurement
Defines before/after metrics and a realistic test.
20%

Red flags

  • Suggests only adding a cache without removing the query pattern
  • Keeps offset paging at 30M rows without justification
  • Ignores that anonymous callers have no per-viewer fields
Expected-solution outline
  • Name the two costs: per-row computed fields causing N+1 queries and a full count on every page
  • Replace per-row resolution with one annotated or batched query for bookmark state and subscription state
  • Move from offset to keyset (cursor) pagination, and either drop the exact total or serve an approximate or cached count
  • Define indexes for the label, author and feed filters, including the composite order used for feed paging
  • Describe contract changes (cursor tokens, total semantics) and a compatible rollout with deprecation
  • Give measurements: queries per request, p95, plan inspection, and a load test with anonymous and authenticated mixes
Debugging from a description 30 min

Authenticated requests slow down and the session table keeps growing

Read the problem and rubric

The Token authentication component decodes a signed bearer token, loads the backing session row and then the account row, and optionally lets anonymous callers through. A token is issued, along with a new session row, on registration, login and every account update. Over the last quarter you observe three symptoms: median latency of authenticated read endpoints rose from 25 ms to 60 ms while anonymous reads did not change; the session table grew from 2 million to 41 million rows and its index no longer fits in memory; and a mobile client that refreshes its account on every launch creates about 200 sessions per active account per month. There were no recent deploys to the Token authentication component. Write down your ranked hypotheses, the queries or metrics you would use to confirm or kill each one, and the fix you would ship first. Then describe how you would clean up the existing rows safely, and what you would change so the problem cannot recur while keeping the ability to revoke a token.

Hypotheses and evidence30%
Immediate fix25%
Safe cleanup25%
Prevention and revocation20%
Extend-this-system take-home 90 min

Add scheduled publication to content entries

Read the problem and rubric

Authors want to schedule an entry to appear at a future time. You are extending the Content entry API and the Relational data model and migrations in a Python service. Today an entry is created inside one transaction that also finds or creates its labels (flow: Entry creation), and every list, feed and read endpoint serializes entries through the Request and response schemas. Requirements: an author can set a publish time when creating or updating an entry; until that time only the author can see the entry; after it, everyone sees it without any manual action; the author can reschedule or cancel before publication; list endpoints keep their pagination contract and must not leak or count hidden entries; and existing entries must behave exactly as before. Deliverables: (1) the schema change and a migration plan that is safe on a table with 3 million rows; (2) the request and response schema changes, with validation rules; (3) pseudocode for the visibility predicate used by list, feed and read, and where you would apply it so no path can bypass it; (4) how entries become visible at the scheduled time and what happens if the process is down then; (5) a test plan listing the five most important cases, including time-zone and clock-skew edge cases.

Data and migration20%
Visibility design30%
Scheduling semantics25%
API and validation10%
Test plan15%
Design question 35 min

Replacing the library-owned label tables without downtime

Read the problem and rubric

A past migration replaced a third-party tagging library's tables with an owned label table and a link table between entries and labels, copying data with raw SQL and then dropping the legacy tables in a later migration. You are about to repeat this kind of change: the owned link table must be split so that each link also records the account that applied the label and the time it was applied, and the label table itself must be deduplicated case-insensitively. The service runs on a relational database with 5 million entries and about 20 million entry-label links, is deployed with rolling restarts, and cannot take more than a few seconds of write unavailability. Design the migration sequence, including how old and new application versions coexist during the rollout, how you backfill, how you verify correctness before cutting over, and how you roll back if verification fails after cutover. Call out which steps are reversible and which are not, and explain why you would or would not run the data copy inside a schema migration.

Migration sequencing35%
Correctness and verification25%
Rollback and risk25%
Operational judgment15%

See it on a real repo.

Pick a sample repo or paste a GitHub URL.

Try the demo Create an account