Capstone: Mock Loop & Self-Exam
Rehearse the whole loop under realistic constraints
Mock system-design: Cursor's data platform v1
After this you can design the end-to-end platform under interview conditions.
Set a 50-minute timer and a whiteboard. The prompt: design ingestion → lakehouse → orchestration → serving for billions of Cursor events per day, plus third-party business data, on a platform that barely exists yet. That last clause is the whole role. You are not running someone's mature stack; you are drawing the first version.
The deep-dive round watches one thing above raw architecture: do you reason like the person who will own this at 3am when freshness alerts fire. Quantify before you draw, name the failure modes before someone asks and kill your own components when the tail gets expensive.
Spend the first five minutes on scale mathEarn the right to design
Most candidates jump to boxes. The strong ones price the problem first, out loud, so every later choice has a number behind it.
- Event rate
- ~3B events/day ≈ 35k events/sec average, with peaks 3-5× during US working hours
- Raw volume
- At ~1 KB/event that is ~3 TB/day landing in bronze, ~1 PB/year before compaction or retention
- Small-file risk
- 35k/sec into naive micro-batches makes millions of tiny Parquet files - the first thing that kills query and list cost
- Third-party
- Stripe, Salesforce, HubSpot via connectors: low volume, high schema-churn, daily-ish freshness needs
Round aggressively. The interviewer wants to see you sanity-check, not nail the exact figure.
Walk the four layers in orderIngestion → lakehouse → orchestration → serving
Interactive diagram. Tab through its regions; each focused region shows its detail in the panel below.
Step through it in order; the gates are the steps generic candidates skip.
The figure's nodes cover ingestion through serving; orchestration is the layer that ties them together and doesn't get its own box. Model tables as Dagster software-defined assets so lineage is the graph, not a wiki. Partition assets by date to make backfills and replays a first-class operation, not a panicked manual script. Use sensors to trigger off Kafka offsets or file arrival instead of blind cron where freshness matters.
Name the failure modes before you're askedThis is where most candidates thin out
- Failure mode
- Duplicate events on retry
- Design answer
- At-least-once delivery + idempotent MERGE on a stable event key; treat exactly-once as a cost trade, not a default
- Failure mode
- Producer ships a breaking schema
- Design answer
- Schema registry rejects at the edge; bad records to dead-letter with offset + reason so you can replay after a fix
- Failure mode
- Late-arriving data
- Design answer
- Event-time partitioning + watermark window; reprocess the affected date partition rather than the whole table
- Failure mode
- Small-file explosion
- Design answer
- Buffer to sane batch sizes, compact on a schedule, monitor file count per partition as an SLO
- Failure mode
- Silent freshness lag
- Design answer
- Freshness check per gold asset with an SLA; page on the asset, not on the cluster
| Failure mode | Design answer |
|---|---|
| Duplicate events on retry | At-least-once delivery + idempotent MERGE on a stable event key; treat exactly-once as a cost trade, not a default |
| Producer ships a breaking schema | Schema registry rejects at the edge; bad records to dead-letter with offset + reason so you can replay after a fix |
| Late-arriving data | Event-time partitioning + watermark window; reprocess the affected date partition rather than the whole table |
| Small-file explosion | Buffer to sane batch sizes, compact on a schedule, monitor file count per partition as an SLO |
| Silent freshness lag | Freshness check per gold asset with an SLA; page on the asset, not on the cluster |
Each row is a question you answer before the interviewer reaches for it.
Cost and the agent-data boundaryThe two clauses generic candidates skip
Right-size clusters and prefer spot for backfills; reserve on-demand for SLA-bound jobs.
Storage layout is the cheapest lever: partition + compact + Z-order before you reach for bigger compute.
Attribute spend per asset/team so cost has an owner, not just a monthly surprise.
Cursor's data feeds agent and model capabilities, so PIIPersonally Identifiable Information. Data that can identify a person (names, emails, SSNs); regulated and sensitive. handling is a first-order design input, not a compliance afterthought.
Mask or tokenize PIIPersonally Identifiable Information. Data that can identify a person (names, emails, SSNs); regulated and sensitive. before it crosses into training-eligible tables; enforce with Unity Catalog RBACRole-Based Access Control. Granting permissions by role rather than configuring each person individually./ABAC.
Retention and audit on sensitive product + agent data; be able to prove who touched what.
When you reach a fork - Kafka vs. direct writes, exactly-once vs. idempotent at-least-once - state the trade and pick, then say what would change your mind. “I'd take at-least-once with idempotent merges because exactly-once doubles the coordination cost for a guarantee an idempotent key already gives me. If duplicates were unrecoverable downstream, I'd reconsider.” That is the autonomy signal the founding-engineer hire is graded on.
Don't design the mature 50-engineer platform. The role is one of Cursor's first data platform engineers, so a v1 that ships and a clear migration path beat a perfect end-state you can't staff. If you draw a five-tool best-of-breed stack with no build-vs-buy reasoning, you've failed the pragmatism filter.
Takeaway. Price the problem in the first five minutes, walk ingestion → lakehouse → orchestration → serving, then volunteer failure modes, cost controls and the PIIPersonally Identifiable Information. Data that can identify a person (names, emails, SSNs); regulated and sensitive. boundary before you're asked.
Self-check
QFor billions of Cursor events/day landing in bronze, why is at-least-once delivery with idempotent merges usually the right default over exactly-once?
Mock take-home / build prompt
After this you can practice scoping a demoable slice in a fixed timebox.
The take-home and the onsite both reward the same instinct: a finished small slice that runs and is tested, over a sprawling design that doesn't. Cursor's onsite is a paid, multi-hour build where you present trade-offs - so practice scoping like the clock is real, because on the day it is.
The promptBuild this in a 4-hour box
Build an idempotent incremental pipeline: land raw events to bronze, dedup to silver, expose a gold table with a quality check. Deliver working code, data-quality assertions and a README of trade-offs plus what I'd do next.
- Idempotency
- Re-running the pipeline on the same input must not double-count - MERGE on an event key, never blind append into silver
- Schema evolution
- A new nullable column shouldn't break the run; assert on contract, not on exact shape
- Partitioning
- Partition bronze by event date so incremental runs touch one partition, not a full scan
- Cost-awareness
- Process only new partitions; note in the README what you'd compact and when
A 4-hour timebox that ends with something demoableSlice, don't sprawl
- 10:00–0:20 · Scope and freeze. Write the smallest end-to-end slice on paper: one event type, bronze → silver → gold, one quality check. Cut everything else to the README's what I'd do next.
- 20:20–1:30 · Bronze + silver. Land raw, then dedup with an idempotent MERGE. Get a re-run to produce identical row counts - that's your idempotency proof.
- 31:30–2:30 · Gold + quality check. Build one aggregate and one assertion (row count, null rate or freshness). Make the assertion fail loudly on bad input.
- 42:30–3:20 · Tests and a re-run. Unit-test the transform, then run the whole pipeline twice and diff the output to prove idempotency.
- 53:20–4:00 · README. Trade-offs you made, what you cut and why and the next three things you'd build. This is graded as hard as the code.
-- silver.events: dedup bronze to the latest record per event_id.
-- Re-running this MERGE on the same bronze partition is a no-op:
-- that property is the whole point of the exercise.
MERGE INTO silver.events AS t
USING (
SELECT *
FROM (
SELECT *,
ROW_NUMBER() OVER (
PARTITION BY event_id
ORDER BY ingested_at DESC, _commit_version DESC
) AS rn
FROM bronze.events
WHERE event_date = :run_date -- incremental: one partition only
)
WHERE rn = 1
) AS s
ON t.event_id = s.event_id
WHEN MATCHED AND s.ingested_at > t.ingested_at THEN UPDATE SET *
WHEN NOT MATCHED THEN INSERT *;Be ready to defend every clause. Why ROW_NUMBER over event_id and not DISTINCT. Why the event_date filter makes this incremental. Why the MATCHED AND guard protects against an out-of-order late record overwriting a newer one. If you can't justify a line, an interviewer will find it.
Idempotency is verifiable, so verify it in the demo: run the pipeline, capture the gold row count, run it again, show the count is unchanged. A 20-second live diff beats a paragraph in the README asserting the pipeline is idempotent.
The classic failure is spending three hours on an elegant config-driven framework that ingests nothing yet. The onsite measures product sense and autonomy - a working bronze-to-gold slice with one real quality check and an honest README outscores a beautiful abstraction with no output. Timebox ruthlessly and demo something that runs.
Takeaway. Freeze the smallest end-to-end slice in the first 20 minutes, prove idempotency with a live re-run diff and treat the README of trade-offs as a graded deliverable, not a footnote.
Self-check
SQL & Python rapid drills
After this you can sharpen the live-coding skills the first screen tests.
Cursor's first technical screen historically forbids AI beyond autocomplete. So the only honest prep is to run that constraint on yourself: blank file, agent muted, a timer and you narrating correctness, scale and cost while you type. Reasoning is graded, not just the final answer.
Treat the rubric as a gap finder, not a score to admire. Mark the weakest proof, turn it into one practice rep and keep the artifact you would show an interviewer.
Four SQL drills that map to the jobEach is a real platform pattern
Given a change-data-capture stream, return the current state per entity.
ROW_NUMBER() OVER (PARTITION BY id ORDER BY ts DESC) then keep rn = 1.
Say why a window beats a self-join on a huge table.
Group events into sessions with a 30-min inactivity gap.
LAG(ts) to find gaps, a running SUM of the gap flag for session ids.
Note the partition + sort cost at billions of rows.
Write a MERGE that lands only one new partition into a target.
Defend the join key and the freshness guard.
Tie it to idempotency: re-run = no-op.
Conversion across ordered steps per user.
Window framing + conditional aggregation, no N self-joins.
Discuss skew if one step dwarfs the others.
SELECT
user_id,
event_ts,
-- session id = cumulative count of “new session” flags per user
SUM(is_new_session) OVER (
PARTITION BY user_id ORDER BY event_ts
ROWS UNBOUNDED PRECEDING
) AS session_id
FROM (
SELECT
user_id,
event_ts,
CASE
WHEN event_ts - LAG(event_ts) OVER (
PARTITION BY user_id ORDER BY event_ts
) > INTERVAL '30' MINUTE
OR LAG(event_ts) OVER (
PARTITION BY user_id ORDER BY event_ts
) IS NULL
THEN 1 ELSE 0
END AS is_new_session
FROM events
);Three Python drillsIdempotent transform, schema validation, backfill loop
- Idempotent transform. A function that, given a partition path, writes deduped output and is safe to re-run - overwrite by partition, never append-then-hope.
- Schema validation. Validate an incoming record against an expected contract; accept new nullable fields, reject a changed type, route the bad record to a dead-letter sink with a reason.
- Backfill / partition loop. Iterate a date range, process one partition at a time, log progress and be resumable after a crash so you don't reprocess what already landed.
from datetime import date, timedelta
def backfill(start: date, end: date, sink) -> None:
"""Process one date partition at a time; skip what's done so a
crash mid-run is safe to restart without double-processing."""
day = start
while day <= end:
if sink.partition_complete(day): # idempotency checkpoint
day += timedelta(days=1)
continue
rows = transform_partition(day) # pure, deterministic
sink.overwrite_partition(day, rows) # atomic per partition
sink.mark_complete(day)
print(f"backfilled {day}: {len(rows)} rows")
day += timedelta(days=1)“I'm processing per partition and checkpointing completion, so this is O(days) work but restartable - if it dies on day 40 of 90, the rerun skips the first 39. At billions of rows I'd also cap partition size and consider parallelizing across dates, watching for shuffle skew on the dedup step.”
Practicing with the agent on is the trap this round exists to catch. Mute it, time each drill and aim for a clean, tested solution you can defend line by line. The discomfort of coding unaided is the signal that you'd been leaning on the tool, not a problem to prompt your way out of.
Takeaway. Drill latest-record, sessionization, incremental upsert and a resumable backfill loop with AI muted and a timer running, narrating correctness, scale and cost the whole way.
Self-check
QTo return the current state per entity from a CDC stream, why prefer a window function over a GROUP BY with a self-join at billions of rows?
Behavioral & 'why Cursor' rehearsal
After this you can deliver values stories crisply on demand.
For senior data hires the values round is often informal, sometimes over a meal and it filters hard for mission belief and intensity. Charm won't carry it. What lands is a small set of quantified stories and a why Cursor that names the founding-platform and agent-data angle specifically.
Interactive diagram. Tab through its regions; each focused region shows its detail in the panel below.
Pick stories that hit the top bars; a generic 'I love hard problems' lands on none of them.
Rehearse five stories - quantified, in this shapeMap them to the behavioral themes the loop tests
- Story
- Built from scratch
- What it proves
- Extreme ownership with no scaffolding
- The number to lead with
- What didn't exist before you and the scale it now carries
- Story
- Ingestion at scale
- What it proves
- You've actually run billions of events/day
- The number to lead with
- Peak events/sec, the bottleneck, what you changed
- Story
- Cost win
- What it proves
- Pragmatic, cost-conscious judgment
- The number to lead with
- % or $ saved and the layout/compute lever that did it
- Story
- Incident / recovery
- What it proves
- Reliability instinct under fire
- The number to lead with
- Detection time, blast radiusHow much breaks if a change goes wrong; the scope of potential damage., the durable fix
- Story
- Cross-functional self-serve
- What it proves
- Treating the platform as a product
- The number to lead with
- Tickets or hours removed by the primitive you shipped
| Story | What it proves | The number to lead with |
|---|---|---|
| Built from scratch | Extreme ownership with no scaffolding | What didn't exist before you and the scale it now carries |
| Ingestion at scale | You've actually run billions of events/day | Peak events/sec, the bottleneck, what you changed |
| Cost win | Pragmatic, cost-conscious judgment | % or $ saved and the layout/compute lever that did it |
| Incident / recovery | Reliability instinct under fire | Detection time, blast radiusHow much breaks if a change goes wrong; the scope of potential damage., the durable fix |
| Cross-functional self-serve | Treating the platform as a product | Tickets or hours removed by the primitive you shipped |
Keep each to about two minutes: situation in 20 seconds, your action in the first person for a minute, a quantified result, then one line of reflection. Past two minutes you're narrating backstory, not the decision.
The 60-second 'why Cursor'Three beats, no filler
- 1The founding angle. You want to be one of the first data platform engineers, defining primitives rather than maintaining someone else's - enormous scale on a deliberately early-stage platform is the draw, not the deterrent.
- 2The agent-data angle. Name that the data here directly feeds agent and model capabilities, so privacy, security and ML-data fluency matter more than at an analytics shop - and that's exactly the work you want.
- 3The mission. Genuine belief that AI-assisted coding is where software is going, said plainly. Intensity reads as real only when the mission belief underneath it is real.
“I've spent four years building data platforms and the part I love is the early phase - when you get to define the primitives instead of inheriting them. Cursor is hiring one of its first data platform engineers against billions of events a day and that data feeds the agent itself, so getting privacy and lineage right isn't a checkbox, it's the product. I want to build that foundation while it's still being drawn.”
Have a crisp first-90-days answerA common senior probe
- Weeks 1-3: map what exists - current ingestion, the Dagster asset graph, where freshness and cost already hurt. Listen before you rebuild.
- Weeks 4-8: ship one self-serve primitive that removes a recurring pain (a standard ingestion pattern or freshness SLAs on the top gold assets).
- Weeks 9-12: harden the agent-data boundary - masking, access controls and audit - and write the operational standards the next hires inherit.
Record yourself answering and grade for three things: specificity (a real number, not “massive scale”), ownership (“I decided,” not “we were tasked”) and intensity that's grounded in the mission rather than performed. A generic “I love hard problems” reads as a red flag here; “I cut bronze storage 40% by fixing the small-file layout” reads as the hire.
Takeaway. Bring five quantified two-minute stories and a 60-second why-Cursor that names the founding-platform and agent-data angle, then rehearse a concrete first-90-days plan.
Self-check
Self-scoring rubric & gap plan
After this you can diagnose readiness and target remaining prep.
Prep without a scorecard drifts toward whatever's comfortable. Score each loop stage 1-5 against what it actually tests, map every weak score to a deep-dive module, then build a final-week plan that attacks one gap per day and ends in a full dry-run.
Treat the rubric as a gap finder, not a score to admire. Mark the weakest proof, turn it into one practice rep and keep the artifact you would show an interviewer.
Interactive diagram. Tab through its regions; each focused region shows its detail in the panel below.
Step each stage; the score table below maps one-to-one to these nodes.
Score each stage against what it testsBe honest - a 3 you can defend beats a hopeful 5
- Stage
- Recruiter / HM screen
- What it tests
- Why-Cursor motivation
- Your 1-5
- __
- Stage
- Technical phone screen
- What it tests
- Live SQL/Python, AI muted
- Your 1-5
- __
- Stage
- Take-home / practical
- What it tests
- Pipeline slice + README
- Your 1-5
- __
- Stage
- Onsite project day
- What it tests
- Product sense, shipping speed
- Your 1-5
- __
- Stage
- System-design deep dive
- What it tests
- Ingestion → serving, end to end
- Your 1-5
- __
- Stage
- Values / why-Cursor round
- What it tests
- Ownership, intensity
- Your 1-5
- __
| Stage | What it tests | Your 1-5 |
|---|---|---|
| Recruiter / HM screen | Why-Cursor motivation | __ |
| Technical phone screen | Live SQL/Python, AI muted | __ |
| Take-home / practical | Pipeline slice + README | __ |
| Onsite project day | Product sense, shipping speed | __ |
| System-design deep dive | Ingestion → serving, end to end | __ |
| Values / why-Cursor round | Ownership, intensity | __ |
Score before you study - the lowest numbers set your week.
Map weak scores to the deep divesEach gap has a home
- Lakehouse / ingestion
- Re-drill Delta/medallion, partitioning/compaction/Z-order, delivery semantics, dead-letter + replay
- Orchestration
- Dagster software-defined assets, partitions, sensors/schedules, backfills, multi-tenant scaling
- Observability / cost / security
- Freshness/volume/distribution checks, SLAs/SLOs, Unity Catalog RBACRole-Based Access Control. Granting permissions by role rather than configuring each person individually./ABAC, PIIPersonally Identifiable Information. Data that can identify a person (names, emails, SSNs); regulated and sensitive. masking, cost attribution
- Live coding
- The SQL/Python drills in this module, AI muted, timed, narrated
- Behavioral
- The five quantified stories and the 60-second why-Cursor
The readiness barTwo pass/fail questions
End-to-end, on a whiteboard, in ~50 minutes.
With scale math, named failure modes and a cost + PIIPersonally Identifiable Information. Data that can identify a person (names, emails, SSNs); regulated and sensitive. boundary you volunteer unprompted.
Bronze → silver → gold with one quality check, in a fixed timebox.
Idempotency proven by a live re-run, plus an honest what-I'd-do-next README.
Confirm logistics with your recruiterCheap certainty
- Exact stage order and how many technical screens to expect.
- The AI-tool policy per round - confirm whether the first screen is autocomplete-only.
- Onsite location (NY or SF), format and that it's a paid build day.
A final-week planOne weak area a day, then a full dry-run
- 1Mon-Wed. One lowest-scoring deep dive per day: re-read it, then do a timed drill or a 50-minute design rep on that exact gap.
- 2Thu. Behavioral day - record the five stories and the why-Cursor, grade for specificity and ownership, re-record the weakest.
- 3Fri. Full mock loop dry-run end to end: a no-AI coding rep, a 50-minute design, a scoped build and the values round, scored against this rubric.
- 4Weekend. Light review of flashcards only; rest beats cramming the night before intensity is being measured.
The rubric isn't decoration - it converts a vague “am I ready?” into a ranked list of drills. Re-score after the Friday dry-run; if every stage clears a 4 and you can answer both readiness questions yes, you're ready. If one stage still sits at a 2, that's the only thing left to work, so work exactly that.
Takeaway. Score each stage 1-5 before you study, route every weak score to its deep dive and run one full mock loop dry-run so the readiness bar - design it out loud, ship a slice in a box - is something you've proven, not hoped.
Self-check
QWhat are the two pass/fail readiness questions for this loop and why are they the right bar?