Preparing your learning space...
50% through FDE Career Preparation tutorials
This tutorial covers the technical round of the FDE loop: the coding/interview fundamentals, the system design round, and the AI engineering round. Each emphasizes the same FDE truth — you're not a pure algorithm solver, you're an engineer who turns an ambiguous customer problem into a working, well-communicated solution. The examples are worked walkthroughs you can practice.
A typical FDE loop is a day of several rounds, roughly:
1. Intro / recruiter screen — fit, background, expectations 2. Technical / coding — can you write working code, out loud? 3. System design — could you architect a customer integration? 4. Customer scenario / case — how do you approach an ambiguous problem? 5. Behavioral — teamwork, conflict, ownership, communication 6. Hiring-manager wrap-up — motivation, comp, role fit
Rounds 4–6 are covered in the next tutorial in this series. This tutorial focuses on the technical, system design, and AI rounds and the preparation that stands you up for the whole loop. No round catches you cold if your fundamentals are solid and your communication is practiced.
Here's the key mental shift. A standard coding interview rewards pattern-matching on algorithms. An FDE technical round rewards gathering requirements under time pressure and communicating your approach, with code as the output of that process.
Concretely, FDE technical problems are often:
So the biggest preparation move isn't grinding harder, it's practicing how you think on your feet while the code editor is open.
Before any technical prep, you need one thing specific to the company: what is their product, and what would an FDE actually be doing with a customer?
This isn't just schmoozing. FDE technical questions are often literally lifted from the company's real customer problems.
The technical round is usually 45–60 minutes. A typical flow:
1. Warmup banter / product context (5 min) 2. Problem statement, deliberately under-specified (5 min) 3. YOU ask clarifying questions (5–10 min) 4. YOU narrate your approach before coding (5 min) 5. Code the solution, talking as you go (20–30 min) 6. Test it / discuss edge cases, complexity (10 min)
You control the middle of that timeline. The interviewers are watching whether you instinctively ask about inputs, edge cases, and constraints — because that's what an FDE does every day with a customer.
1. Restate the problem in your own words. → confirms you understood. 2. Ask about inputs, edge cases, constraints. → the critical FDE signal. 3. State your intended approach + language. → show a plan before code. 4. Write code in short, named, logical steps. → readable means debuggable. 5. Walk through a small example by hand. → prove it works before they ask. 6. Discuss complexity and edge cases. → close it out with rigor.
Never go silent for more than ~30 seconds. If you're stuck, say what you're stuck on. Interviewers grade the process and will actively steer a flailing but communicative candidate to a good place.
Problem. A customer sends you a list of events; each event either created, updated, or deleted a record. Return, for each record id, the final state after applying all events in order.
Clarify first — the under-specified part:
created, updated, deleted)value on create/update; none on delete)created targets an id that already exists? (Overwrite — assume last write wins.)deleted before created — ignore it.)def final_state(events):
state = {} # record_id -> value
for event in events:
rid, op = event["id"], event["op"]
if op == "delete":
state.pop(rid, None) # ignore missing deletes
else:
state[rid] = event.get("value") # create / update: last write wins
return state
events = [
{"id": 1, "op": "created", "value": "a"},
{"id": 2, "op": "created", "value": "b"},
{"id": 1, "op": "updated", "value": "z"},
{"id": 2, "op": "deleted"},
]
print(final_state(events)) # {'1': 'z'}
The logic mirrors real event-sourcing integrations: you only care about the final footprint, and pop with a default makes stray deletes harmless.
Problem. An API returns customer addresses in inconsistent formats. Normalize them into a standard shape: street, city, postal_code, country.
Clarify: How inconsistent? What's the output rule for empty fields? Case normalization — uppercase, lowercase, or title case for cities?
import re
def normalize_address(raw: dict, country: str = "US") -> dict:
return {
"street": (raw.get("street") or "").title(),
"city": (raw.get("city") or "").title(),
"postal_code": re.sub(r"\s+", "", raw.get("zip", raw.get("postal_code", "") or "")),
"country": country.upper(),
}
raw_a = {"street": "100 MAIN ST", "city": "AUSTIN", "zip": " 78701"}
raw_b = {"street": "200 elm", "city": "DALLAS", "postal_code": "75201"}
print(normalize_address(raw_a)) # {'street': '100 Main St', 'city': 'Austin', 'postal_code': '78701', ...}
print(normalize_address(raw_b)) # {'street': '200 Elm', 'city': 'Dallas', 'postal_code': '75201', ...}
Two skills land here: handling messy real data (raw.get chained to fall back between zip and postal_code) and defensive defaults (or ""), so a missing key can't blow up the pipeline.
Problem. A customer's device data includes a repeated, out-of-order message log. Return the messages re-sorted, with consecutive duplicates collapsed to the latest one.
Clarify: Sort key — timestamp or order of appearance? "Duplicate" — identical payload or same record id? Keep latest — by timestamp or last seen?
def clean_log(messages):
latest = {}
for msg in messages:
mid, ts, body = msg["id"], msg["ts"], msg["body"]
if mid not in latest or ts > latest[mid]["ts"]:
latest[mid] = msg
return sorted(latest.values(), key=lambda m: m["ts"])
log = [
{"id": "A", "ts": 10, "body": "v1"},
{"id": "B", "ts": 11, "body": "ok"},
{"id": "A", "ts": 14, "body": "v2"}, # duplicate of A, newer
]
print([m["body"] for m in clean_log(log)]) # ['ok', 'v2']
This combines deduplication (choose newest by comparing ts) with a final stable sort — the standard move for "make this noisy data clean and ordered."
Generic design problems usually start "design a scalable social feed." FDE design problems start closer to:
"A customer runs a legacy inventory system and wants to stream stock changes into our analytics platform so their dashboard is always current. Design the integration."
| Generic SD | FDE SD | |
|---|---|---|
| Starting point | A product idea | A specific customer's existing situation & constraint |
| Scale obsession | Billions of users | One account's realistic throughput |
| Golden target | Elegant scale-in | A working, maintainable integration they'll operate |
| Top question | "How many QPS?" | "What's the customer already running, and what's the constraint?" |
You should still know the standard cloud building blocks, but the framing is customer-first.
Following these three phases out loud keeps you in control and never loses the thread.
• What systems exist today, and where does the data live? • What's the data shape and volume? (events/rows per day? size of a record?) • What's the freshness requirement? (real-time? hourly batch is fine?) • Is the customer storing the source of truth, or are we mirroring it? • Who's going to operate this, and how much hand-holding after handoff? • What budget/severity for failures? (Are missed records worse than duplicates?)
These are discovery questions — the same ones you'd ask on the customer's site on day one. Naming an obvious-but-unstated constraint early is a strong signal.
✗ (builds the full fan-out pipeline with DLQ, K8s autoscaling, two region copies) ✓ "The MVP: a reliable importer that pulls changes hourly, writes them to our platform, and retries failures. I'd explicitly cut real-time streaming and multi-region in v1, because their stated freshness is 'end of day is fine' and the volume is ~50k rows/day. I'll note the scaling path as a delta."
Scope discipline is the strongest senior-FDE signal in the whole round.
[Customer source system] │ (poll or events) ▼ [Ingestion service] ──► writes raw events ──► │ ▼ [Transformation / normalization] │ ▼ [Durable store / target platform API] │ (retries on failure, idempotent writes) ▼ [Customer's dashboard / analytics]
A well-labeled CRUD service with a queue and a retry story covers most correct answers.
Choose the most relevant concern for this customer ("for this customer, the highest-risk one is idempotency on retry…") rather than listing all of them.
| Building block | When it helps |
|---|---|
| Message queue (SQS/Kafka/polling) | Decouple ingestion from processing; buffer spikes |
| Worker / cron | Scheduled batch pulls when freshness tolerates it |
| Retry + backoff + DLQ | Survive upstream bumps and isolate poison messages |
| Idempotency store (keyed on event id) | Make replays safe |
| Watermark / cursor table | Track how much data you've processed |
| Webhook vs poll | Webhook = push (needs public endpoint); poll = pull (works behind firewall) |
| Two-region / availability | Usually a "delta," not the MVP, for a single customer account |
Correct, boring, maintainable beats impressive.
Prompt. A customer wants their IoT device events in your analytics platform, current within minutes. Design the intake.
Discovery highlights: ~110k events/day, peak at 3am; freshness of minutes, not seconds; they have an internal endpoint to poll (no public webhook); duplicates possible on retry — device_id + seq is a stable key.
# Worker pulls a page, upserts by stable key, records the watermark
def poll_ingest(source_cursor):
rows = source_api.poll(cursor=source_cursor, limit=1000)
for row in rows:
upsert_in_platform( # idempotent: (device_id, seq) dedupes replays
key=(row["device_id"], row["seq"]),
data=normalize(row),
)
update_watermark(source_cursor, rows[-1]["cursor"] if rows else source_cursor)
return len(rows)
We poll (no public endpoint needed), writes are idempotent on a natural stable key so retries are harmless, and a watermark lets a crash resume where it left off. Minutes-level freshness means batch-polling every minute is fine — no need for streaming infra.
Prompt. E-commerce customer wants order data from two systems (a legacy POS and a modern storefront) reconciled into one dashboard.
Discovery highlights: the two systems trust different timezones (a classic real bug); source of truth is ambiguous; matching records across systems is the hard part.
Your design choices to defend:
updated_at per source, so the dashboard shows both systems' truth with a conflict flag, rather than silently destroying either.The seniority points: you turned a technical sync into a data-governance conversation (which system is authoritative) and a timezone bug into a normalizing decision.
Prompt. Give customers a self-serve API to pull their data, with per-customer rate limits, auth, and auditing.
Discovery highlights: only ~30 active customers, but each may script bulk exports; "fair use" over precise enforcement is right.
Your design:
429 with a Retry-After header so clients self-throttle.Enforcement tolerant of spikes with transparent backpressure beats brutal hard caps; auditing is a feature customers demand even if they don't ask for it.
1. Recap the MVP and what you deliberately deferred (scope discipline). 2. Name the 1–2 riskiest assumptions and how you mitigated them. 3. Say what you'd measure in the first week to know it's working (watermark lag, drop rate, reconciliation match rate). 4. Ask the interviewer what they'd cut or stress.
Closing with "what I'd measure first to know it's healthy" shows you don't just build systems — you run them.
Few interviewers expect you to have trained a model. They want to know you can use one competently in a customer setting: understand it as a tool, wire it to the customer's data (retrieval/context), think about cost/latency/failure, and evaluate whether output is good enough to ship.
If you can hold a confident, opinionated conversation about prompting, RAG, and evaluation, you'll clear this round even without ML research credentials.
| Concept | One-line explanation |
|---|---|
| Token | The model's atomic unit of text; cost and context limits are measured in tokens |
| Context window | Max tokens the model can "see" in one call — your design constraint |
| Prompt | The instructions + input you send; the single highest-leverage thing you control |
| System prompt | Persistent instructions that set the model's role/behavior for a session |
| RAG (retrieval-augmented generation) | Inject relevant documents into the prompt so the model answers from your data, not its training |
| Hallucination | The model confidently producing text that isn't true — your main reliability risk |
| Temperature | Controls randomness; low = deterministic, high = creative |
| Grounding | Framing an answer in verifiable retrieved data so it's traceable |
| Evaluation (evals) | A fixed test set used to measure whether model output is correct enough |
Know RAG, grounding, and evals precisely — those three come up in most AI-FDE conversations.
Task: classify a customer support ticket as a refund, an account issue, or a bug. Good prompt: "You are a support triage assistant. Given a ticket, return ONLY one of: REFUND | ACCOUNT | BUG. If unclear, return UNKNOWN. Ticket: <ticket text>" Better: - Constrain to a fixed output set (stops creative drift). - Add ONE example with the expected output (few-shot). - Request the classification AND a one-line reason, for audibility.
The reasoning you verbalize: you reduce a fuzzy request into a bounded format, add an example to anchor expected behavior, and ask for a reason so a human can audit decisions.
The classic AI-FDE prompt: "Customer wants to chat with their own manual/PDFs. How does that work?"
1. Ingestion — chunk the customer's documents (by section/heading, not hard line count). 2. Embeddings — encode each chunk into a vector via an embedding model. 3. Vector store— store vectors for fast similarity search (Pinecone, pgvector, etc.). 4. Query — embed the user's question, retrieve the top-K similar chunks. 5. Generate — stuff retrieved chunks into the model's context with a system prompt instructing it to answer only from those chunks. 6. Cite/source — return which chunk(s) the answer came from for trust.
Two things interviewers probe: chunking quality (chunk by semantic boundaries, not every N characters) and grounding (instruct the model "base your answer only on the provided text; if unsure, say you don't know"). You'll be asked why RAG works, not just to recite its steps.
1. Deterministic evals — a fixed set of N representative customer inputs with human-approved expected outputs; run on every change. 2. Metrics — for classification: accuracy/precision/recall. For generation: is the answer grounded + human spot-checks. 3. Failure taxonomy — what does "wrong" actually look like? • hallucinated (no supporting source) • wrong retrieval (good answer, irrelevant data pulled in) • right but unhelpful (format/verbosity miss) 4. Your job — pin failures to a cause (prompt, retrieval, or chunking), fix one variable, re-run the evals.
The senior move is to name the failure categories rather than treat "the model is wrong" as one blob.
Prompt: "Design an assistant that answers from a 5,000-page manual, live in chat." Your framing: • Can't stuff all 5,000 pages in one prompt — tokens/context blow up. → Use RAG to inject only the ~top-5 relevant chunks per question. • Long documents → chunk into 300–500 token chunks, embed, retrieve top-K. → Every query is now cheap and fast because you send only a slice. • Don't re-embed the corpus every query — embed once at ingestion, store vectors, reuse. • Cache common questions; if 20% repeat, you save 20% of cost and latency. • Bound output length + cap parallelism so a spike doesn't spike the bill.
You turn an "impossible" content problem into a cheap, fast one by design (retrieval over everything), not by asking for a bigger model. Sizing token cost per query is a credible touch.
If you consistently bring the conversation back to "how does this behave on their data," you've nailed the AI-FDE mindset.
Prompt. A bank customer wants to auto-draft replies to support tickets using your AI platform. Draft it, wire it, and talk about making it safe.
Your walkthrough:
Your close: "The difference from a demo is that I never let it auto-send, I pilot on a subset, and I keep receipts for audit." That single sentence compresses prompting discipline, RAG, evaluation, regulatory care, and rollout caution.
Save your progress and earn XP for completing tutorials.
4 questions · Pass with 70%+
1What is the single strongest FDE signal in a technical/coding round?
2To make replays and retries safe in an integration design, you should:
3In a RAG system, what is grounding primarily for?
4To answer questions from a 5,000-page manual live in chat, the correct approach is:
Technology
Forward Deployed Engineer
Lesson group
FDE Career Preparation
Progress
50% complete