A few months ago a stakeholder pinged me on Slack with what sounded like a small ask. “Can you add a column to the customer dashboard? We need the average order value.” I almost said yes and went straight to the dbt model. I’m glad I didn’t, because the column they wanted already existed, two tabs over, under a slightly different name. What they actually needed was for someone to walk them through the dashboard once. Twenty minutes of conversation saved a pull request, a code review, and a deployment.
This is the 80/20 rule of being a useful engineer: 80% of the value comes from understanding what the person actually needs, and 20% comes from the code that delivers it. Most teams have it backwards. They reward shipping. They under-reward the boring, unscalable, deeply human work of asking good questions before you open your editor.
Vague tickets are the default, not the exception
I used to get frustrated when a Jira ticket arrived with three lines of context and a deadline. Then I realised that’s just the shape of the work. The person who wrote the ticket isn’t being lazy. They have a problem in their head, a fuzzy idea of the solution, and a calendar full of meetings. They typed what they could and assumed you’d figure out the rest.
So you have to figure out the rest. Not by guessing. By asking.
The reflex move is to read the ticket, think “I get it”, and start coding. The trap is that you’ve now committed to a specific interpretation of a vague request, and every hour of work you put in makes you more attached to that interpretation. By the time you demo it, you’ve spent two days building something the user didn’t want, and now you have to choose between throwing the work away or quietly hoping nobody notices.
The cheaper move, by an order of magnitude, is to spend twenty minutes asking questions before you write a single line.
The two questions that do most of the work
There are a hundred frameworks for requirements gathering. I’ve read books about it. I’ve sat through trainings. After all that, I keep coming back to two questions that, if you ask them honestly, get you 80% of the way there.
”Who is going to use this?”
Not “who asked for this”, which is a different question. Who will actually open this dashboard, click this button, run this report? If the answer is “the finance team”, that’s a start. If the answer is “Marco from finance, every Monday morning, before the leadership sync”, that’s gold. Now you know what shape the output needs to be in, what time it needs to run, and what level of detail Marco can absorb on a Monday morning with one coffee in him.
The mistake I made for years was assuming “the team” was a useful answer. Teams don’t open dashboards. People do. And different people on the same team often want completely different things from the same data.
”What decision will this drive?”
This one is the rephrase that has saved me the most rework. If somebody asks for a new metric, I ask: when this number is high, what do you do? When it’s low, what do you do? If the answer is “nothing, we just want to see it”, congratulations, you’ve found a vanity metric and you can de-prioritise it without much guilt.
If the answer is concrete, “if churn goes above 5% we trigger a retention campaign”, now you know the metric needs to be reliable, defined the same way every time, and probably alerted on. Suddenly a one-line ticket has a real spec.
I once spent two weeks building a beautiful real-time view of pipeline lag for a team that, when pressed, admitted they only checked it during the Monday standup. A daily snapshot would have been fine. Half a day of work, not two weeks. Asking “what decision will this drive” up front would have saved me 80% of the effort.
Rephrase the request back, in concrete terms
Once you’ve asked your two questions and listened, the next move is to say it back. Not as a parrot. As a translator.
“So if I understand correctly, you want to know, every Monday at 9 a.m., how many customers placed at least one order in the last 7 days, broken down by region, so the regional managers can prioritise outreach. And the threshold you care about is below 100 orders. Is that right?”
That sentence does three things at once. It forces you to articulate what you heard, which surfaces the bits you didn’t actually understand. It gives the stakeholder a chance to correct you while the cost of correction is still tiny. And it creates a written artefact you can paste into the Jira ticket, so future-you and the rest of the team know what was actually agreed.
I’ve watched this single habit turn junior engineers into people the business actively asks for by name. It’s not magic. It’s just respecting that the person on the other side of the table has a problem and you have a duty to understand it before you solve it.
Shadow the user for fifteen minutes
This is the highest-leverage thing I do, and it’s also the one I most often skip. If the user is in the same building or the same Zoom call, ask if you can watch them do their job for fifteen minutes. Just watch. Don’t suggest improvements. Don’t fix anything. Don’t even speak unless they ask you a question.
You will learn things in those fifteen minutes that no spec document or backlog refinement meeting will ever surface. You’ll see the spreadsheet they actually use, with all the manual edits and weird color-coded cells. You’ll see them copy-paste a value from one tool into another, every single morning, because nobody ever told the engineers that the export was missing one column. You’ll see the workaround they invented to deal with the bug nobody fixed.
I once shadowed an analyst who was supposedly using a dashboard I’d built. She wasn’t. She had quietly built her own pivot table in Excel, exported the raw data every morning, and was using my “dashboard” as a glorified data source. Not because the dashboard was bad, but because she needed three filters that I’d left out. I added the filters in an afternoon and she became my biggest internal advocate.
You don’t get that insight from a Jira ticket. You get it from sitting next to someone for fifteen minutes.
The anti-pattern: “I’ll just build it and we’ll iterate”
I’ve said this. Everyone has said this. It feels productive. It feels agile. It is, in practice, often a way of avoiding the harder work of asking questions, because asking questions makes you look like you don’t know what you’re doing, and building feels like progress.
The cost of “build first, iterate later” is rarely just the wasted code. It’s the demo where the stakeholder politely says “this isn’t quite what I meant”, and now you’ve used up some of the goodwill they had for you. It’s the second iteration that gets less time and attention than the first, because everyone has moved on. It’s the GitHub repo full of half-finished features that nobody uses but nobody can delete either, because someone might be relying on them.
Iteration is a real and useful tool. But iteration on something you didn’t bother to understand is just expensive guessing. Iteration on something you understood 80% of, after a real conversation? That’s the actual job.
The discipline isn’t to ask infinite questions before you start. It’s to ask the few questions that turn a fog of vague intent into a sharp, falsifiable picture of what success looks like. The questions are cheap. The code that comes after them is expensive. Get the order right and you’ll be the engineer your stakeholders ask for by name. Get it wrong and you’ll be the engineer they cc on tickets, hoping someone else picks them up.