A forward deployed engineer writes real code, but sits with the customer instead of behind a product team. Interviews test both halves. Expect questions on why you want a customer-facing engineering job, stories about ambiguous projects and hard stakeholders, what-would-you-do calls about scope, access and promises made by others, and hands-on checks: profiling a messy table, pulling data from an API, shipping into a customer's own cloud, and tracing a failure across systems you don't own. Many loops also include a decomposition case. Each question shows what the interviewer is listening for, a shape for your answer and a short answer to say out loud.
Search all questions by round, difficulty and level, or save the ones you want to practise.
Path: the short version of what you have built and for whom.
The pull: a moment when working close to a user changed what you built.
Why now: what this role gives you that a product team does not.
"I started as a backend engineer on an internal data platform. The part I liked most wasn't the platform itself, it was the weeks when I sat with the operations team who used it. Twice I watched them work around a feature I'd built, and both times a small change fixed a problem they'd lived with for months. After that I kept volunteering for the messy customer-facing projects: a data migration for a new client, then a reporting integration that nobody else wanted. I want this role because it makes that the whole job. I get to write real code, but I also get to see whether it actually changes someone's day, and I'm at my best when the problem isn't fully defined yet."
Saying you want it because you enjoy travel or talking to people, with no sign you like building under ambiguity.
Core: an engineer embedded with a customer who builds and ships working software on their data.
Versus a consultant: you leave running code behind, not only advice or slides.
Versus a solutions engineer: you own delivery and outcomes after the deal, not the demo before it.
"I'd say it's an engineer whose desk is next to the customer. A consultant mostly tells you what to do and hands over a report. A solutions engineer mostly helps win the deal, with demos and proofs of concept before the contract is signed. A forward deployed engineer comes in when the customer needs the product to actually work on their data and in their systems. So I'm writing the integrations, the data pipelines, the small apps on top, getting it deployed where they need it, and staying until it's delivering value. The other half is carrying what I learn back to our own product team, because the fixes I keep repeating for customers are usually features we should build once."
Describing the role as sales support or pure advice, with no mention of shipping and owning working software.
Appeal: what being in the room gives you that a video call does not.
Honest cost: the part you expect to be hard.
Habits: how you keep notes, focus time and energy across accounts.
"What appeals to me is how much faster things move in person. In one afternoon on a customer's floor you learn which spreadsheet really runs the business and who actually decides things, and that can take weeks over calls. The honest cost is energy and focus. Switching between two customers in a day is tiring, and it's easy to lose deep work time. What makes it work for me is keeping a running notes file per customer with decisions, open questions and who owns what, so I can pick up where I left off. I also block time for building and protect it, and I'm upfront with my manager early about the travel pattern I can sustain, so there are no surprises later."
Saying travel is no problem at all, or showing no plan for handling several customers at once.
People: meet the sponsor, then the people who do the work every day.
Data: get read access early and look at what really exists.
Narrow: pick one delay, one decision and one measure, and say it back.
"First I'd find out what the sponsor means by delays and why it matters now, because 'delays' could mean late deliveries, slow approvals or idle machines. Then I'd spend most of the week with the people doing the work: shadowing a planner, sitting with dispatch, asking what they check first when something runs late. In parallel I'd push for read access to the key data so I can see what's actually recorded, how clean it is and how far back it goes. By the end of the week I want to play back one narrow problem, something like 'shipments leaving the second warehouse miss their slot because loading plans are made before stock is confirmed,' with a measure we agree on and a first thing I can build in the next two weeks."
Starting to build a model or dashboard on day one before anyone has agreed what problem it solves.
Problem and user: who uses it and what decision or task it changes.
Measure: one or two outcomes with a baseline and a target.
Boundaries: what is out, what you need from them, and the date to review.
"I keep it to one page. At the top is the problem in the customer's own words, and the specific people who'll use what we build. Then the success measure, with a baseline. Something like 'planners currently spend most of Monday building the weekly schedule; the goal is under two hours, measured over four weeks.' Then what's explicitly out of scope, because that's where arguments start later. Then what I need from them: data access, a named person who can answer questions within a day, and time from real users for testing. Last, a review date. I walk the sponsor through it in person rather than just emailing it, because a scope nobody discussed isn't really agreed."
Treating scope as a list of features with no measure of whether the customer's problem got better.
Decision: who acts on a warning, how early, and what they can actually do.
Data: what is known when the warning must fire, and what 'late' means.
First version: simple rules or a baseline, shown in the tool people already use.
Loop: measure warnings against outcomes and improve.
"I'd start with the second half, doing something about it, because a prediction nobody acts on is worth nothing. Who would act? Maybe a dispatcher who can reroute, or customer service who can warn the client. How much notice do they need? That sets when the warning must fire and which data is available at that moment. Then I'd define late precisely, against the promised date or the carrier's estimate, and pull history to see how often it happens and where. My first version would be simple rules from that history, like a route and carrier pair that's usually late, shown as a flagged list in the dispatcher's existing screen. Then I'd track how many flagged shipments really were late and what actions were taken. Only if simple rules plateau would I bring in a proper model."
Opening with model choice and features without asking who acts on the prediction or what counts as late.
Situation: what you were asked for and what you built.
The miss: how you found out it wasn't used or didn't help.
Change: the habit you now follow, with proof you used it since.
"At my last company a client asked for a dashboard showing stock levels across their stores, and I built exactly that in three weeks. A month later almost nobody opened it. When I sat with a store manager, I saw why: they didn't need to see stock levels, they needed to know what to reorder before Friday's delivery cutoff, and they were still doing that in a spreadsheet. I'd taken the request literally and only spoken to the head office sponsor. We turned the dashboard into a short reorder list that went out Thursday morning, and usage picked up straight away. Since then I always watch the actual user do the task before I build, and I ask 'what will you do differently when you see this?'"
Blaming the customer for asking for the wrong thing, with no change in your own approach.
Context: the business, and why you needed to learn it fast.
How you learned: the people doing the work, their own words and documents, then the data.
Proof: how you checked you had it right, and what it changed in what you built.
"At my last company I was sent to a medical supplies distributor with no background in that business. For the first two days I sat with a picker and a planner and kept a glossary of every term they used, because words like 'backorder' and 'available' meant something narrower there than I'd assumed. I asked for the training material they give new staff, which taught me more than any system document. Then I went through their data with the glossary open and noted every place it didn't match what people had told me. At the end of the week I explained their order flow back to the planner in my own words, and she corrected two things I'd got wrong. One of them was how they counted available stock, which the whole tool depended on. I've used the glossary and the playback on every customer since."
Learning the business only from documents on your own and starting to build without checking your understanding with the people who do the work.
Thin slice: one user, one workflow, end to end on real data.
Boring stack: tools you and the customer can run, usually Python or TypeScript, SQL and a simple UI.
Skip, not ignore: leave out scale and polish, keep data access safe and write down every shortcut.
"I'd pick one user and one workflow and make it work end to end on their real data, even if it's narrow. Technically I'd go with whatever I'm fastest in and they can run, usually a Python service with SQL against a copy of their data, and a very simple web page or even a notebook the user can click through. Days one to three are getting the data in and understanding it. Then I build the core logic, and I get it in front of the user by the end of week one, not week two. What I skip on purpose is scale, fancy UI, full automation and edge cases that affect a handful of records. What I don't skip is keeping their data access secure and a short list of every shortcut I took, so nobody mistakes the prototype for production."
Spending the first week on infrastructure and architecture, or skipping security because it's only a prototype.
Shape: row count and date range, compared with what the customer expects.
Gaps: missing values in the columns you depend on.
Keys: whether the id that should be unique really is.
"I never take 'it's clean' at face value, so I start with a quick profile. The first query tells me how many rows there are, how many are missing a customer or a date, and the first and last order dates. I compare that with what the customer told me: if they said three years of history and I see eight months, that's a conversation now, not in week three. The second query checks whether order_id is really unique. Duplicates usually mean the export joined in a line-items table or a system re-sent records, and that silently doubles any total I calculate. Then I'd pick a handful of real orders and check them against their own screen with someone from their team."
SELECT COUNT(*) AS total_rows,
COUNT(*) - COUNT(customer_id) AS missing_customer,
COUNT(*) - COUNT(order_date) AS missing_date,
MIN(order_date) AS first_order,
MAX(order_date) AS last_order
FROM orders;
SELECT order_id, COUNT(*) AS copies
FROM orders
GROUP BY order_id
HAVING COUNT(*) > 1
ORDER BY copies DESC;
Loading the table straight into a model or dashboard and only finding the duplicates when the totals look wrong in front of the customer.
Rank: number each shipment's rows from newest to oldest.
Pick: keep row number one.
Ties: add a second sort key so the answer is stable.
"Customer systems often store history as an event log instead of a current-state table, so this comes up all the time. I'd use a window function: partition by shipment, order by the event time newest first, and number the rows. Then I keep only row one for each shipment. The detail that bites people is ties. If two status changes share the same timestamp, which happens when a system writes in batches, the choice is random unless I add a second sort key, like the event id, so the result is the same every run. I'd also check how timestamps are stored, because a mix of local times and UTC can make an older event look newer."
SELECT shipment_id, status, event_time
FROM (
SELECT shipment_id, status, event_time,
ROW_NUMBER() OVER (
PARTITION BY shipment_id
ORDER BY event_time DESC, event_id DESC
) AS rn
FROM shipment_events
) latest
WHERE rn = 1;
Using MAX of the time and MAX of the status separately, which mixes values from different rows.
Loop: follow the next-page link until there isn't one.
Rate limits: on 429, wait as the server asks, retry the same page, and cap the retries.
Safety: a timeout on every call, and raise on any other error instead of skipping it.
"I'd use one session so the auth header and connection are reused. The loop asks for a page, and if the server says 429, too many requests, I read the Retry-After header, sleep that long and retry the same page rather than moving on. I cap those retries, so a limit that never clears ends in an error instead of a loop that runs all night. Any other error status raises too, because silently skipping a page means missing records nobody notices. Otherwise I add the page's records and follow the next link the API gives me until there isn't one. Every call has a timeout so a hung connection doesn't freeze the job. In real use I'd also log progress and save a checkpoint, so a failure at page three hundred doesn't mean starting again."
import time
import requests
def fetch_all(base_url, token, max_retries=5):
session = requests.Session()
session.headers["Authorization"] = f"Bearer {token}"
url, params = f"{base_url}/orders", {"limit": 200}
records, retries = [], 0
while url:
resp = session.get(url, params=params, timeout=30)
if resp.status_code == 429 and retries < max_retries:
retries += 1
wait = resp.headers.get("Retry-After", "")
time.sleep(int(wait) if wait.isdigit() else 5) # can also be a date
continue
resp.raise_for_status() # a 429 past the cap fails loudly here too
retries = 0
body = resp.json()
records.extend(body["data"])
url = body.get("next") # full URL of the next page, or None
params = None # the next link already carries the query
return records
Catching every exception and carrying on, so failed pages vanish without anyone knowing.
Isolate: reproduce with the simplest possible call from the same machine.
Walk the layers: DNS, routing and firewall, proxy, TLS, then auth and the application.
Compare: list what differs between your test setup and theirs.
"A timeout rather than an error usually means the request never gets an answer, so I'd suspect the network before the code. First I'd reproduce it with the simplest call I can make from the same server, like a plain request to the endpoint with verbose output. Then I walk up the layers. Does the name resolve to the address I expect? Can I open a connection to that port at all, or is a firewall dropping it silently? Does their network force traffic through a proxy my code isn't configured for? If it connects, does TLS fail because they inspect traffic with their own certificate? Only when the connection is clean do I look at auth and payloads. I'd do this sitting with their network person, because they can see the firewall logs I can't."
Increasing the timeout, or disabling certificate verification to make the error go away.
Symptom: what broke and why it was hard to see.
Method: how you narrowed it down across systems with partial access.
Evidence and fix: what proved it, who fixed what, and what you added to catch it next time.
"At a previous job a customer's nightly sync to our platform dropped a few hundred records a week, never the same ones. Their team said our import was broken, and our logs showed every record we received loaded fine. I didn't have access to their middleware, so I asked them for its logs for one bad night and matched record ids across all three systems. The missing ones had all changed in the same second as another record, and their middleware treated anything with the same timestamp as a duplicate, so it kept one and dropped the others. I wrote it up as a one-page timeline with five example records at each hop, which made it hard to argue with. Their team changed the dedup key, and I added a daily count comparison between their source and our platform that alerts on any gap."
A story where the answer was simply that the other team was wrong, with no evidence and no follow-up check.
Packaging: containers and infrastructure as code so it installs the same way every time.
Their rules: identity and roles, network paths, secrets, logging and approved services.
Operations: who patches, monitors and gets paged once it's live.
"The software mostly stays the same, but everything around it becomes theirs. I'd package the application as containers and describe the infrastructure as code, so it installs the same way in their account as in our test environment. Then I'd sit with their cloud and security teams early and ask for the practical things: which regions and services are approved, how we get least-privilege roles, how traffic gets in and out, where secrets live, and where logs and metrics must go. I'd also ask about their change process, because in many companies a firewall change takes a week. The last question is who operates it after go-live: who patches it, who watches it and who gets called at night. That answer shapes what I build."
Asking the customer for broad admin access to their cloud account so things go faster.
Bundle everything: images, packages, models and config in one versioned, checksummed bundle.
Their route in: the approved transfer process and a local registry or package mirror.
Updates: tested offline first, with a rollback and a way to collect logs without a network.
"The big shift is that nothing can be downloaded at install time, so everything has to arrive in one bundle: container images, language packages, any model files, and config templates, all pinned to exact versions with checksums. I'd rehearse the install on a machine with networking turned off, because that's where you find the one library that quietly fetches something. Then I'd work with their team on the approved way to bring files in, often a scanned transfer, and push the images into a registry inside their network. For updates, I'd ship a new versioned bundle with release notes and a tested rollback to the previous one. Support is the hard part, so I'd build a command that gathers logs and config into one file their team can review and send out."
Planning to install by pulling from public package registries on the day, or having no rollback.
What and who: the system and the team taking it over.
Handover plan: pairing, runbook, and a period where they drive and you watch.
Result: what happened after you left, including any gaps.
"In my last role I built a data pipeline and a reporting app for a client, and their two-person IT team had to run it after my six weeks were up. From week three I paired with one of them on every change, so they'd seen each part working. I wrote a short runbook covering the five things most likely to go wrong, each with how to spot it and what to do, and I tested it by having them fix a failure I caused on purpose. In the last week they did everything and I only watched. A month after I left they hit a problem the runbook didn't cover, a password expiry on a service account. They fixed it, and I added it to the runbook for the next customer."
Handing over with a single long document on the last day and no sign the team had ever run it themselves.
Agreement: what we may use the data for, under the contract and their policies.
Least access: only the fields and rows needed, masked where possible, inside their environment.
Rules: the privacy laws that apply where they operate, and their security team's sign-off.
"Before any access I want to know what we're allowed to use the data for, which is set by our contract, their internal policies and the privacy law where they operate. That differs by country, for example data protection rules in Europe or health-data laws elsewhere, so I ask their privacy or legal contact rather than guessing. Then I ask for the smallest slice that answers the question: often I don't need names or phone numbers at all, so they can be masked or dropped before I see them. I keep the data inside their environment, not on my laptop, with named access that gets removed when the project ends. And I agree with their security team what gets logged, so we can show later exactly who saw what."
Copying a full production extract to a personal machine to work faster.
Decline kindly: thank them and say no without making them feel foolish.
Explain simply: the risk to their data and to both companies.
Offer a better path: work inside their environment or with an approved, masked extract.
"I'd thank them, because they're trying to help, and then say no. A production copy on my laptop means their customers' data sits outside their controls on a device that could be lost, and it probably breaks both our contract and their own policies, even if nobody would notice today. That's a risk to them, to me and to my company, and it's not worth a few days. Then I'd turn it into something useful: could we get me access to a workspace inside their environment, or ask their data owner for a masked extract through the proper route? I'd offer to help write that request so it moves quickly. That keeps the goodwill and still gets me unblocked."
Accepting because the customer offered, as though their offer makes it allowed.
Request: what they wanted and why it seemed reasonable.
Reasoning: the evidence that it wasn't worth it, or was the wrong fix.
The no: how you said it, what you offered instead, and the result.
"A customer's finance lead asked me to build a full approval workflow inside our tool, with multiple levels and email reminders. When I dug in, their existing finance system already had approvals, and they only wanted ours because two people didn't like the old screen. Building it would have taken about a month and left them with two approval systems that could disagree. So I went back with that picture, and the cost in time, and offered an alternative: a link from our tool that opened the right approval in their existing system, with the key numbers already shown. It took two days. The finance lead was a bit disappointed at first, but the two unhappy users were fine with it, and we spent the month on the forecasting work they'd actually bought us for."
Either never having said no, or saying no by pointing at the contract without offering an alternative.
What you saw: the problem at the customer, with specifics.
Your case: how you packaged it with evidence and a suggestion.
Result: what changed, and what you learned about influencing without authority.
"At my last company our product's import tool only accepted one file format, and at three customers in a row I spent the first week writing converters. Each time I mentioned it in passing, and nothing happened. So I changed how I raised it. I tallied the days spent across those customers, collected the three converters, and wrote a one-page note with the common pattern and a suggested design that reused most of my code. I asked for thirty minutes with the product manager instead of dropping it in a channel. They put a smaller version on the roadmap for the next quarter and asked me to review the design. What I learned is that product teams respond to evidence and a ready-made path, not to stories told in passing."
Only ever working around product gaps quietly, or only complaining about them with no evidence.
Why this week: the event or decision driving the date.
Smallest useful slice: what would meet that need by Friday.
Be clear: what the slice doesn't do and the plan for the rest.
"I'd start by asking what happens at the end of the week. Usually there's a specific reason, like a board meeting or a customer review, and it needs a lot less than the full feature. If the VP needs to show a forecast to the board, maybe the Friday version is the forecast for their top product lines, produced by a script I run and checked by hand, not a self-service tool. I'd propose that, be clear about what it doesn't cover, and put the month of proper work in the plan with a date. I'd also let my own manager know, because a pattern of this-week demands can wreck the rest of the project. What I avoid is promising the full thing by Friday and then shipping something broken."
Agreeing to the full feature by Friday to keep them happy, or refusing without asking why the date matters.
Confirm: make sure the gap is real, with specific evidence.
Internal first: tell your account team quickly and agree the message together.
Options: what is possible now, what data would fix it, and a realistic new plan.
"First I'd make sure I'm right. If the promise was predicting equipment failures and they've only recorded a handful of failures in three years, I'd show that plainly with the counts. Then I'd go to our account executive and my manager the same day, before the customer hears it any other way, and agree how we tell them. With the customer I'd be direct: this is what the data can support today, this is what it can't, and why. Then give options. Maybe we can deliver something valuable now, like flagging machines with unusual sensor readings, while they start recording failures properly so the original goal becomes possible later. I'd never quietly build something that looks like it works. And afterwards I'd help sales with a checklist so the next deal gets a quick data check before the promise is made."
Hiding the gap and building something that only appears to work, or blaming the sales team in front of the customer.
Size the incident: who is affected and what it's costing them right now.
Get help early: tell your manager and bring in a colleague for one of the two.
Tell both customers: what you're doing and when, so neither is surprised.
"A production issue that stops people working comes first, because every hour costs that customer something real. But I wouldn't just drop the demo. I'd first size the incident: is the system down, or is one report wrong? Then I'd tell my manager straight away, since this is exactly the kind of clash a team should absorb. Usually the answer is a colleague either takes the demo with my notes and rehearsal, or picks up the incident with me on a call. I'd let the renewal customer's account executive know early if anything changes, rather than on the day. And once the incident is fixed, I'd write down why a customer-facing system depended so much on one person, because that's the real problem."
Trying to do both alone without telling anyone, or treating the renewal as more important than a customer who can't work.
Who and why: the person and what made them skeptical.
Actions: what you did to understand them and show early results.
Outcome: how the relationship changed, with a concrete sign.
"I worked with an operations director who'd been through two failed software projects and told me in our first meeting she expected ours to fail too. Instead of defending the product, I asked her what went wrong last time. Both times, she said, vendors disappeared for months and came back with something her team couldn't use. So I did the opposite. I sent her a short written update every Friday with what worked, what didn't and what I needed. And I showed her team something working with their own data within ten days, even though it was rough. The turning point was when she found an error in my numbers and I fixed it by the next morning. After that she started inviting me to her weekly team meeting."
Describing the stakeholder only as difficult, with no curiosity about why they behaved that way.
Tell the sponsor now: the blocker, what it means for Friday and what you'll show instead.
Unblock properly: find out what IT needs and whether a smaller, safer slice is quicker.
Keep building: use a sample, masked extract or realistic fake data, clearly labelled.
"First I'd tell the sponsor today, not on Thursday, that full data access is two weeks out and what that means for Friday. Then I'd go and talk to IT in person to understand why it's two weeks. Often it's a standard review, and a smaller request, say read-only access to a masked sample or one table, can go through a faster path. Meanwhile I'd keep building on a realistic sample, either a small extract they're comfortable sharing or data I generate to match the real structure. On Friday I'd show the workflow working end to end on that sample, clearly labelled as such, and show the plan for switching to real data the day access lands. What I wouldn't do is go around IT, even if the sponsor offers to."
Working around the access controls to hit the date, or saying nothing until the demo is already late.
Contain: stop the bad numbers spreading, then fix or roll back.
Tell people: the report owner and your manager straight away, with scope and impact.
Correct and prevent: fix past outputs and add a check that would have caught it.
"First I'd stop it getting worse: roll back the change or pause the report so no more wrong numbers go out. Then I'd work out the damage, which figures were wrong, since when and by how much. Within the hour I'd tell the report's owner at the customer, and my own manager, in plain words: I made a change last week, it caused this error in these figures, here's what I've done so far and what I'll do next. I wouldn't wait until I had a perfect fix, because someone may be making a decision with those numbers today. Then I'd correct the past reports, send a short note of what changed, and add a test that compares key totals before and after any change. Owning it quickly usually costs less trust than they'd lose finding it themselves."
Quietly fixing it and hoping nobody noticed, or waiting days to raise it until the fix is perfect.
Stay helpful: small, quick things that build goodwill are fine.
Keep a list: write down every extra request and the time it takes.
Raise it: show the sponsor and your manager the list and let them choose priorities.
"Being embedded is partly about goodwill, so I'm happy to do small things, like helping someone fix a spreadsheet formula over lunch. But when it becomes daily, I start keeping a simple list of each request and how long it took. After a week or so I'd take that list to the sponsor and say, 'Your team's finding this useful, and here's what it's cost against the main project. Do you want me to keep doing these, or protect the time for the forecasting work?' That puts the choice with the person who owns the budget and the goal. I'd tell my own manager too, because it might mean the customer needs a bigger engagement. What I avoid is saying no to people one by one, or saying yes until the real project slips."
Saying yes to everything until the main project is late, or refusing people bluntly one at a time.
Where speed is fine: exploration, first drafts, one-off scripts.
Where it isn't: anything that touches money, security or runs unattended.
Growing: code review with peers and reusing good pieces across customers.
"I split the work in my head. Exploration notebooks and one-off scripts can be quick and messy, as long as nobody depends on them. But anything that runs without me watching, touches their money or their customers' data, or that another team will inherit, gets tests, clear names and a short readme, even on a tight deadline. The trick is making the good version fast, so I keep a personal toolkit of pieces I trust, like a tested API client and a data-checking script, and reuse them. I also ask a colleague to review my code even when I'm the only engineer on the account, because working alone at a customer is exactly where standards quietly slip."
Saying all customer code is throwaway so quality doesn't matter, or insisting on production polish for every experiment.
Shared picture: a regular sync on the account's health, risks and goals.
Push back in private: disagree before the customer meeting, not in it.
Offer a yes: say what you can deliver, and by when.
"I see the account executive as my partner on the account, not the enemy of good engineering. We both want the customer to renew and grow. So I keep a short weekly sync with them: what's working, what's at risk, what the customer's asking for. Most overpromising happens because the account executive doesn't know what's hard, so I try to make that visible early. If they want to commit to something I think is unrealistic, I say so privately before the meeting, with a reason and an alternative I can stand behind, like a smaller first phase with a date. In front of the customer we speak with one voice. And when they win something because my delivery made the customer happy, I want them to feel free to say that too."
Correcting the account executive in front of the customer, or treating sales as the problem rather than a partner.
ClapAssist is an AI interview assistant for Mac and Windows. It listens to the interview on your computer and shows you what to say, in short lines you can read while you talk. Your resume and notes are never stored on our servers. It stays out of screen share on every plan; only you can see it.