Structured Problem Solving and Decomposition Questions
Methodical problem solving for open-ended and ambiguous situations once the problem is defined: decomposing a goal or problem into mutually exclusive, collectively exhaustive parts (issue trees, metric trees and driver breakdowns, work breakdown into subproblems and vertical slices), forming and prioritizing hypotheses (hypothesis trees and funnels, including laying out candidate explanations for a metric drop or model degradation and the cheapest test for each branch), choosing an analytical approach, and reasoning to a recommendation. Also covers turning a vague mandate into measurable, testable subproblems with owners, breaking a large initiative into workstreams, mapping dependencies, sequencing the work, deciding the first deliverable and what to defer, structuring plans that mix research, analytics and experiments, and talking through real examples of cutting a messy problem into parts. Covers explaining and adapting structured problem-solving methods across contexts, choosing and switching methods, and coaching others to structure ambiguity. Excludes turning a vague request into a scoped problem statement, named-framework business cases, root-cause techniques for failures and metric movements (running the diagnosis itself), prioritization scoring and trade-off decisions, deciding how to act under incomplete information, market sizing and estimation, and framing machine-learning problems, which are covered elsewhere.
You own a nine-month, revenue-critical migration to the cloud. How would you split it into top-level workstreams that cover everything without overlap, and how would you decide the order and the dependencies between them?
Sample Answer
Direct answer
Split by one dimension only, the kind of deliverable each workstream produces, so every task has exactly one home. I would use six workstreams: discovery and planning, cloud foundation, workload migration, operations readiness, decommission and exit, and program and change management. Then order them by the critical path (the longest chain of dependent work, which sets the earliest finish date) and move the revenue-critical systems last, after the process has been proven on safer ones.
Structured elaboration
Why MECE matters here. MECE means mutually exclusive (no task in two workstreams) and collectively exhaustive (nothing falls between them). Overlap causes double work and blurred ownership; gaps are where a revenue-critical migration gets hurt late. Test it: take ten random tasks (set up VPN, train support staff, shut off the old database server) and confirm each lands in exactly one workstream. Then ask "where do security, cost and training live?" and make sure each has one named home plus an explicit boundary.
Terms used in the table: a wave is a group of applications migrated together, and the wave plan says which applications go in which wave and when. Identity means who can sign in and with what permissions. The security baseline is the minimum set of security settings every account must have. Tagging is attaching labels (team, cost center) to cloud resources so cost and owners can be traced. A region is a geographic location where the cloud provider runs data centers. Runbooks are step-by-step instructions for handling a known situation. Decommissioning is shutting down and removing the old systems. Rollback is returning an application to the old environment if the move fails.
| Workstream | Covers | Boundary rule |
|---|---|---|
| 1 Discovery and planning | Inventory of applications, dependencies and data; target design; wave plan | Produces plans, builds nothing |
| 2 Cloud foundation | Accounts, network connectivity, identity, security baseline, cost budgets and tagging (the "landing zone", the pre-built environment workloads move into) | Environment only; per-application security checks belong to workstream 3 |
| 3 Workload migration | Moving applications and their data in waves, including cutover (the moment traffic switches) and rollback plans | One owner per application |
| 4 Operations readiness | Monitoring, alerting, runbooks, on-call, deployment pipelines, cost review routines | Defines how the new environment is run; the shared runbook format, on-call and alerting live here, while each application's own rollback steps stay in workstream 3 |
| 5 Decommission and exit | Retiring old systems, data retention, contract and facility exit | Starts only after a wave is stable |
| 6 Program and change management | Governance, risk register, communication, training | Cross-cutting, owns no technical deliverable |
Worked example
Illustrative nine-month order (months 1-9):
| Workstream | Months | Depends on |
|---|---|---|
| Discovery and planning | 1-2 | None |
| Cloud foundation | 1-3 | Early target design from discovery (regions, compliance needs) |
| Operations readiness | 2-5 | Foundation; minimum version before the first production workload |
| Workload migration | pilot month 4, waves in months 5-8 | Foundation and operations readiness |
| Decommission and exit | 7-9 | Each wave stable first |
| Program and change management | 1-9 | None |
Operations readiness has a minimum version that must exist before the month-4 pilot: monitoring and alerts on the pilot app, a tested rollback runbook for the pilot app (its steps come from the workstream 3 rollback plan; operations readiness checks that on-call can actually run them) and a named on-call person. It is finished by the end of month 3; the rest (cost review routines, deployment pipelines for later waves) continues through month 5 alongside the early waves.
Waves: pilot (a low-risk internal app, month 4), wave 1 low risk (month 5), wave 2 (month 6), wave 3 medium risk (month 7), wave 4 revenue-critical systems (month 8), leaving month 9 as buffer and for finishing decommissioning. Order criteria: start long-lead items first (tasks with slow waiting time that cannot be compressed: network connectivity, compliance approvals meaning sign-offs that the new setup meets legal or regulatory rules, large data transfers), keep an easy rollback until each wave is stable, and avoid cutovers in business peak periods.
Trade-offs and pitfalls
- Splitting by team or by application type mixes dimensions and breaks MECE; a mixed split looks fine on a slide and fails at the first overlapping task.
- Moving the revenue-critical system last trades a later benefit for lower risk. If the cost of the old environment is the burning problem, you might move one revenue-critical but simple component earlier with a tested rollback.
- Big-bang cutover is the wrong turn for revenue-critical systems; migrate in waves with a rollback path.
- Operations readiness is the workstream most often forgotten, and the first production incident exposes it.
- What would flip the order: a hard external date (data center contract ending) moves decommission planning to the front and compresses waves.
Take a goal like 'onboarding completion dropped 30%' or 'migrate our monolith while cutting cost 20%'. Show me how you break it into smaller subproblems, how you decide the split, and how you know when to stop splitting.
Sample Answer
Direct answer
First I turn the goal into a precisely defined number. Then I split it using a rule that guarantees the pieces do not overlap and cover everything, and I pick the splitting dimension that separates owners and actions. I stop splitting when each leaf is testable, owned, measurable and decision-relevant.
Worked decomposition: "onboarding completion dropped 30%" (illustrative numbers; the monolith goal is worked through with numbers after the table of other goals)
- Define the metric. Completion = users who finish setup within 7 days of sign-up, divided by users who start. Check what "30%" means. A relative drop from 60% to 42% is 30% relative (18 percentage points); a drop of 30 points is a different problem.
- First split: by funnel stage. Stages are sequential, so every user stops in exactly one place (mutually exclusive) and a user who finished passed them all (exhaustive). A simplified two-stage funnel:
| Stage | Before | After |
|---|---|---|
| 1. Verify email | 75% | 75% |
| 2. Connect first data source | 80% | 56% |
| Completion (stage 1 x stage 2) | 60% | 42% |
Check: 0.75 x 0.80 = 0.60 and 0.75 x 0.56 = 0.42. Stage 2 fell from 0.80 to 0.56, which is 30% relative, so it holds the whole drop. A real funnel has more stages.
3. Second split inside stage 2: by what the user did. (a) never reached the connect screen, (b) reached it but never attempted, (c) attempted and failed. Each user is in exactly one state. The three states cover the stage-2 users who did not finish. Users who connected successfully are a fourth state, (d), kept in the split so it stays exhaustive and the sum test passes: with illustrative counts per 1,000 users who verified their email, before the drop 800 are in (d); after the drop 560 are in (d), and the 240 extra non-completers are spread across (a), (b) and (c). Each leaf has a metric from event logs, an owner (navigation team, product design, integrations engineering) and a test (count users in the state, before versus after). "Funnel" here means the ordered steps users pass through from sign-up to finished setup, and event logs are the recorded actions (screen viewed, button clicked) that let you count users at each step.
How I decide the split
I choose the dimension where (1) branches imply different actions, (2) branches map to different owners, (3) the data already exists, and (4) the split can be checked cheaply. A split by device or customer segment is useful too, but as a second-level cut, because it does not tell a team what to fix.
The stopping rule
A leaf is done when it is:
- Testable: one analysis or small experiment answers it in days, not weeks.
- Owned: one person or team can act on it.
- Measurable: it has a metric, a baseline and a target.
- Decision-relevant: a yes or no would change what we do.
Too shallow: a leaf needs a multi-week project or has two owners. Too deep: leaves nobody owns, or whose answer would not change the plan.
The same method on other goals
| Goal | Split rule | Leaves that pass the stopping rule |
|---|---|---|
| Migrate a monolith (one large deployable application) and cut cost 20% | First fix the baseline: 20% of which bill, and are one-off migration costs included? Then split by module along clear boundaries, and cost into run cost versus migration cost | Milestone 1: cost-per-module table. Milestone 2: move one low-risk module behind an interface (a stable boundary, so the rest of the application calls it the same way before and after the move) and measure its before/after cost. Each deliverable has an owner and a number |
| Reliability work (SRE, site reliability engineering) | Split by user journey, each piece tied to a service-level objective (SLO), a target like "99.9% of checkout requests succeed over 30 days" | "Checkout survives the loss of one zone" (a zone is a separate data-centre area within a cloud region), proven by a failover drill (deliberately switching to the backup) in staging (a test copy of the production system) |
| Raise engagement through recommendations (machine learning, ML) | Split along the pipeline: candidates retrieved (the shortlist the system pulls from the catalogue), ranking (ordering that shortlist), presentation (how it is shown), measurement | "Is a relevant item in the top 50 candidates?" is testable offline with logged clicks (recorded past clicks, treated as evidence of what was relevant) |
| User registration feature | Split by component: form validation, account storage, email verification, session creation, abuse protection | Each component has its own acceptance test (a check that it does what was agreed) and can be built and checked alone |
The monolith goal with numbers (illustrative)
Suppose the yearly bill is 1,200k and "cut cost 20%" means a saving of 240k a year, run cost only, with one-off migration cost reported separately. First split, by cost type, is run cost 1,200k plus one-off migration cost (tracked, not counted against the 20%). Second split, run cost by module: checkout 400k, search 300k, reports 200k, admin 100k, shared infrastructure 200k (400 + 300 + 200 + 100 + 200 = 1,200). Each module is a different team's code and bill, so each has an owner. Stopping check on the leaf "reports module, 200k": testable (move it behind an interface and compare its bill before and after, in weeks), owned (the reports team), measurable (baseline 200k, target for example 140k, a 60k saving, which is a quarter of the 240k goal), decision-relevant (if the saving is small, the next module is chosen instead). Shared infrastructure fails the check as a single leaf because no one team owns it, so it is split further by the module that consumes it.
Pitfalls
- Splitting by whatever is easiest to draw, which gives branches nobody can act on.
- Mixing two dimensions at one level (stage and device), which breaks mutual exclusivity.
- Splitting until the tree looks impressive instead of until leaves are testable.
A binary classifier's production accuracy has degraded and you need to organize every plausible source of the error before anyone starts debugging. How would you structure the possible causes so they do not overlap and nothing is missed, and how would you check your structure is sound?
Sample Answer
Direct answer
Accuracy is correct predictions divided by labelled predictions. Both sides of that fraction come from only four places, which is why four branches can cover it. A prediction depends on the inputs and on the deployed model and pipeline; the label it is compared with depends on the real outcome and on how labels are produced. So the number is determined by four things: the inputs the model receives, the true relationship between inputs and the real outcome, the deployed model and pipeline that turns inputs into predictions, and the process that produces labels and the metric. A fall in accuracy requires a change in at least one of them, so those four are my top-level branches. I check soundness by replaying past incidents onto the tree and by testing every leaf for a single home.
The tree (example: a spam filter, where the two classes are spam and not spam)
| Branch | Leaves |
|---|---|
| A. The inputs changed | A1 Traffic mix changed (new senders, new languages, spam share shifted). A2 Upstream data broke (nulls, schema or unit change, stale feature values). A3 Training/serving skew: a feature is computed differently online than it was for training |
| B. The input-to-outcome relationship changed | B1 Real-world behaviour changed (spammers adopt new tactics, so old patterns no longer mean spam) |
| C. The model or pipeline changed | C1 A new model version or retrain shipped. C2 A threshold or configuration changed. C3 A dependency or preprocessing library changed behaviour |
| D. The measurement changed | D1 Labels are late or incomplete in the evaluation window. D2 The labelling rule or labeller pool changed. D3 The sampled population being labelled changed, or is too small so the number is noisy. D4 The metric or dashboard computation has a bug |
Terms in the leaves: a threshold is the score cut-off above which the model says "spam". Upstream means earlier in the data flow. A schema is the agreed list of fields and their types. Retraining means fitting the model again on newer data. A preprocessing library is shared code that cleans and converts raw data before the model sees it. Drift means live data or the real-world pattern has moved away from what the model learned from. Data drift is the inputs changing (A1); concept drift is the link between inputs and the true outcome changing (B1).
Tie rule that keeps leaves exclusive: classify each cause by where in the chain it originates. A broken upstream job that feeds bad values is A2, even though it also looks like data drift. A shift in the spam share is A1, since it changes the inputs, not the rule linking them to labels. Two more overlaps to settle in advance. Skew versus a changed library: if a feature is computed differently online than in training and nothing was deployed this week it is A3; if a deployed code or library change made it differ it is C3 (the change event is the origin). Traffic mix versus labelled-sample mix: if real traffic changed it is A1; if traffic is unchanged but the emails chosen for labelling changed, it is D3.
How I check the structure is sound
- One-home test: write five real past incidents (or imagine plausible ones) and place each. If one fits two leaves, sharpen the leaf definitions. If one fits none, there is a gap.
- Exhaustiveness argument: could accuracy move while all four factors stay fixed? If I cannot construct such a case, the four branches cover the space. Where I cannot argue it, I add an explicit "unexplained" leaf that must shrink to zero before anyone calls the investigation finished.
- So-what test: each leaf maps to a different owner or action (data team, ML team, labelling team, analytics).
- Peer review: ask someone who did not draw the tree to find a cause with no home.
One incident traced through the one-home test (illustrative numbers)
Daily accuracy on 1,000 labelled emails falls from 95% (950 correct) to 89% (890 correct). Investigation shows a feature called sender reputation arrives empty for 12% of emails since a data-job change last Tuesday. Placement: the model and threshold are unchanged (not C), labelling volume and rules are unchanged (not D), spammer behaviour is the same on emails with a score (not B). The inputs are wrong, and they are wrong because an upstream job broke, so the single home is A2, not A1 and not B1. Fixing the job and re-scoring the affected emails should restore accuracy; if it recovers only part of the 6 points, the remainder still has to be placed on a leaf, and an unplaceable remainder goes to the "unexplained" leaf.
Trying to break the exhaustiveness argument: random noise on a small labelled sample can move accuracy with nothing real changing. That is a measurement cause, which is why D3 includes "too small".
Same discipline on three other systems (one split each, checked with the same one-home and exhaustiveness tests used on the classifier tree)
A feature store is a service holding precomputed model inputs (features) for training and live use. A Kafka topic is a named stream of events, durably stored (the Kafka documentation likens it to a folder of events), that producers write to and consumers read from. Here a broker is a server holding the log, a partition is one slice of a topic, a sink is where a consumer finally writes the data, retries are repeated send attempts after a failure, replication lag is the delay before copies of data catch up, and cache lifetime is how long a stored value is reused before being refreshed.
| System and symptom | Buckets (by where it originates) | Mitigation per bucket |
|---|---|---|
| Feature store serving stale values | Writer side: the update job is late or failed. Store side: cache lifetime too long or replication lag. Reader side: wrong key, version or point in time requested | Alert on job freshness; shorten cache lifetime or fix replication; add a version check at read time |
| Kafka ingestion volume dropped | Producers send less (app change, real traffic fall). Transport loses or delays data (broker or partition trouble, exhausted retries). Consumers or sinks drop data (lag, skipped undecodable messages, write failures). Measurement (the counter itself) | Compare producer and consumer counts at each hop; alert on skipped messages; confirm with a second counter |
| Web page slowdown | Client and network. Server computation. Downstream dependencies (database, other services). Traffic or load | Trace one slow request to find which hop owns the extra time |
Pitfalls
- Mixing "what" and "where" in one level (for example "data drift" next to "upstream job failure").
- A catch-all "Other" holding most of the cases.
- Debugging before the tree is agreed, which anchors everyone on the first plausible story.
Your company wants a legacy web app secured in 30 days with a small team. How would you split the work into highest-value subprojects, and what would you explicitly defer?
Sample Answer
Direct answer
With 30 days and a small team you cannot make a legacy app secure; you can close the most likely and most damaging attack paths (an attack path is a chain of steps an attacker could follow, such as an exposed login page, a weak password, then customer data) and leave an honest list of what remains. Pick subprojects by risk removed per person-day, start with finding what is exposed, and write the deferrals down with a trigger for revisiting each. At day 30 claim "top attack paths closed", never "secured".
Structured elaboration
Order of thinking. First learn what you protect and who would attack it (customer data, payments, admin functions), because that decides what "highest value" means. Then list candidate subprojects and rank them by exposure, severity and effort.
Subprojects (highest value first)
- Inventory and exposure. What is reachable from the internet (admin pages, old test servers), which components and versions run. Close anything that never needed to be public.
- Known-vulnerable components. Scan dependencies and server software, patch or upgrade those with known public exploits (ready-made attack code anyone can download).
- Authentication and secrets. Multi-factor authentication (MFA: a password plus a second proof such as a phone code) for admin access, remove shared or default credentials, rotate secrets found in code and config.
- Compensating control in front. A web application firewall (a filter that blocks common attack patterns) is a compensating control, a safeguard that reduces risk when the flaw itself cannot be fixed yet, and it buys time for flaws you cannot fix in 30 days. (Formally, a compensating control stands in for a recommended control and is expected to give comparable protection; a firewall in front usually gives less, which is why it is recorded as temporary.)
- Top application flaws. Fix the worst findings of a scan or review (injection, where attacker-supplied text gets run as a database command or code; broken access control, where users can reach data or actions they should not) on the most sensitive functions.
- Detect and recover. Basic logging and alerts, plus a backup that you have actually restored once.
Explicitly deferred (with a reason and a trigger): rewrite or re-architecture (needs months; revisit after a residual-risk review, a check of the risk that remains after the fixes), low-severity findings (batch into normal sprints), single sign-on migration (one login shared across systems; large and not an attack-path closer), compliance certification (needs evidence over time), network micro-segmentation (splitting the network into small zones so one breach cannot spread; design work first).
Triggers to revisit each deferral: rewrite, the residual-risk review at day 30; low-severity findings, the first normal sprint planning after day 30; single sign-on migration, the residual-risk review showing shared credentials as the top remaining risk; compliance certification, an audit or customer contract that sets a date; network micro-segmentation, the inventory showing sensitive systems on the same network as exposed ones.
Worked example
Illustrative: 3 people x 20 working days = 60 person-days.
| Subproject | Person-days | Validation |
|---|---|---|
| Inventory and exposure | 8 | Independent external scan shows no unexpected open services |
| Vulnerable components | 14 | Re-scan shows known-exploited items gone |
| Authentication and secrets | 12 | Admin login without MFA fails; old secrets stop working |
| Web application firewall | 6 | Test attack strings are blocked, real traffic is not |
| Top application flaws | 12 | Re-test of the fixed findings |
| Logging and backup | 6 | A test event raises an alert; a restore succeeds |
| Validation and buffer | 2 | Residual-risk list reviewed |
The total is 60. The deliverable for leadership: what was closed, evidence for each, and the deferred list, each item with a named owner, a reason and its revisit trigger.
Variation: building an insider-risk detection capability from scratch. Decompose into data sources (identity and access logs, file access, endpoint activity, HR events like departures), signals (such as unusual download volume against the person's own baseline, or access outside their role), privacy constraints, tuning and review. Sequence privacy and legal constraints first, because they gate which data sources are allowed; then start with a few high-precision signals (signals that are rarely wrong when they fire), tune against a baseline period (a stretch of normal activity used to set thresholds), and route alerts to a small trained review group rather than automatic action. One signal worked through (illustrative): an employee normally downloads about 20 files a day; the rule fires when a day exceeds 10 times their own 30-day average and is at least 100 files, so 400 files in one day on the week they hand in notice fires, while 60 files on a busy day does not. Review the alerts raised in the baseline period: if 3 of 10 were real concerns the precision is 30%, and you tighten the threshold before anyone is contacted.
Trade-offs and pitfalls
- Scanning everything and fixing in severity order ignores effort and exposure; a medium flaw on an internet-facing login can outrank a high one deep inside.
- A WAF is a bandage, not a fix. Record it as a compensating control.
- Overpromising "secure in 30 days" damages credibility when the first finding arrives.
- If the app handles regulated data, some deferred items may not be deferrable; confirm obligations before finalizing the list.
- What would flip priorities: evidence of active exploitation, which moves incident response ahead of everything else.
Your feature depends on another team's API that is unstable and changes without notice. How would you break your work up so your team can still make progress, and how would you sequence the risky parts?
Sample Answer
Direct answer
Put a boundary of your own between your feature and their API, build against that boundary, and learn about the real API early with a small spike (a short, throwaway experiment). Your team then progresses on everything that does not depend on the unstable part, the risky integration is tackled first in its smallest form, and drift is detected by an automated daily check instead of by users.
Structured elaboration
Decouple. Define an interface owned by your team that describes what your feature needs (for example: estimate shipping for a cart, returning minimum days, maximum days and price). Your business logic and screens depend on that interface only. An adapter (a thin translation layer) maps their API to your interface, so a change on their side breaks one file, not the feature.
Split the work
- Spike on the real API. One or two days calling it for real: which fields exist, how errors look, how often it changes. Cheapest way to retire the biggest uncertainty.
- Interface plus a fake. A fake implementation with recorded sample responses lets everyone build and test without waiting.
- Own logic and UI. Fully independent of their stability.
- Adapter to the real API. Small, isolated.
- Drift detection. A scheduled contract check: a test, written by you, that asserts only the fields and behaviors you depend on, run daily against their test environment.
- Resilience. Timeouts, retries with waiting between attempts, a circuit breaker (stop calling a failing service for a short time), and a fallback behavior when it is down.
- Rollout behind a feature flag, so you can turn the feature off without a deploy.
Sequence the risky parts. Spike first, interface and fake second, so risk shrinks before the bulk of the work. Integration with the real API is scheduled early, not last, so surprises arrive while there is time.
Talk to the other team. Ask for a versioned contract, a channel for breaking-change notices and a stable test environment. Escalate with evidence (a log of unannounced changes) if the pattern continues.
Worked example
Feature: show a delivery estimate at checkout using the logistics team's estimate endpoint, which has twice renamed fields without notice.
- Day 1-2: spike shows the price field is sometimes a number and sometimes a string.
- Day 3: interface "estimate(cart)" and a fake with three recorded cases, including an error.
- Days 4-8: checkout UI and logic built against the fake; adapter written and tested with the recorded real responses.
- Day 9: daily contract check enabled; feature flag at 5% of traffic.
When the field is renamed again, the contract check fails the next morning and one adapter line changes. The check runs daily, so the check can take up to a day to notice the rename, plus however long the one-line fix takes to ship, so the exposed window can be longer than a day; during it the resilience layer (timeouts and a fallback such as "usually 3 to 5 days") keeps checkout working and the flag lets you switch the estimate off. The check also runs against their test environment, so it only catches changes that reach that environment first; if production changes first, the adapter's own validation of each live response (log it and fall back when a field is missing or the wrong type) is what protects users.
Trade-offs and pitfalls
- Do not wait for the other team to stabilize; but do not silently absorb every change either, since your adapter can hide a problem they should fix.
- Fakes drift from reality; the contract check exists to catch exactly that.
- A fallback has a product cost (an estimate that says "usually 3 to 5 days" instead of an exact one), so agree it with product in advance.
- What would flip the plan: if they plan to deprecate the API, invest less in the adapter and ask whether a different source is available. If the API is truly unusable, consider keeping your own copy of the needed data.
Unlock Full Question Bank
Get access to all 17 Structured Problem Solving and Decomposition interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.