How to Ask Better Questions
Asking well gets you the answer. Where the answer goes afterwards matters just as much.
Early in my career I thought asking questions was one skill. You ask or you don't, and asking is the brave part. Half true. Asking is fine. But the question itself does most of the work, and a lazy one gets you a lazy answer back.
A post by Bo French on the Atomic Object blog rearranged how I think about this, so here's my own version. Most of it comes from working on a real codebase, mostly remote, where a bad question costs someone an interruption and a good one saves the whole team an afternoon.
Do the boring homework first
Do the cheap stuff yourself before you pull someone in. Reproduce the bug. Read the whole stack trace, not just the first red line. Search the repo, the docs, the exact error string. git blame the file and read the commit that put the code there. Usually one of those just answers it. When it doesn't, you show up with a narrowed-down problem instead of "hey, this is broken," which is the gap between a two-minute reply and a thirty-minute debugging session you've now dragged someone else into.
Match the question to the room
A good question in the wrong place still lands wrong. An architecture debate has no business in a five-minute standup. A one-line clarification doesn't need a slot on anyone's calendar. Pick the venue that fits the weight: a quick DM, the team channel, a call. And ask the person who actually knows. This matters more when you're async, because the wrong channel means your question either sinks unanswered or quietly derails something else.
Write it down before you say it out loud
Before I ask anyone, I write the question down. Previously, I used to write down in a paper but now I use Notion or Obsidian. Just a short list. What I'm trying to do, what I already tried, and where what I expected stopped matching what actually happened.
- What I'm actually trying to do. Not the symptom, the goal.
- What I already tried, and what each attempt did.
- The exact error, copied. No paraphrasing.
- What I expected to happen instead.
Half the time I never hit send. Writing it out forces the structure that solves it (the rubber-duck thing, except the duck is a bullet list). And when it genuinely stumps me, that same list is already a question someone can answer in one read.
A well-written question is mostly a well-understood problem. Sometimes writing it down is how you find out you already had the answer.
Bring thick questions to the group
Once you're using shared time, spend it on questions that earn the audience. Thin questions have one answer. "Which env var sets the timeout?" Take that to a DM. Thick questions open something up. "Why are we catching every error here instead of letting some bubble up?" That one is worth getting the room for. Honestly, most standups drag because people bring thin questions to a thick setting.
The diamond: thin, then thick, then thin
The best idea I took from Bo French is the diamond. Open thin to get everyone on the same page. Go wide in the middle, into the real "why," where the actual conversation lives. Then close thin, with a quick check that everyone walked away with the same picture. Thin, thick, thin. It gives a conversation an obvious start and a clean exit, instead of the usual thing where a discussion trails off and nobody is sure if it got settled.
The answer has to land somewhere
Here's the part that took me longer to figure out. Asking well gets you a good answer. But that answer is useless next quarter if it lived in a DM thread and then scrolled out of reach. Teams lose more time re-discovering things they already solved than solving anything new.
So we keep one place for it. We call it Tribe Knowledge, and it lives in Notion. It's not code or a repo, it's documentation: a shared hub for the things everyone on the team actually wants to know. A code comment helps whoever reads that exact line. Tribe Knowledge helps the person who doesn't even know the line, or the file, exists.
Here's what sold me on it. I got handed a ticket to rotate every secret in the app. Session secret, JWT secret, the internal API key, the webhook secret. I figured these were just random alphanumeric strings I could regenerate and rename however I liked. They are not.
Generating the new value is the easy part. The catch is that each one expects a specific format, and they don't agree with each other.
- One had to be valid Base64. Hand it a plain random string and the service won't boot.
- Another only accepted exactly 32 bytes, because something downstream used it as a fixed-length key.
- One wanted raw hex, and when it got the wrong encoding it failed quietly instead of loudly.
- The values weren't interchangeable either. A secret that was fine for one was rejected outright by the next.
None of that was obvious from the variable names. They all just looked like random strings. So this time I didn't just leave a comment. I wrote the whole thing up in Tribe Knowledge: which secret wants which format and length, the order to rotate them in, and who needs the new value before anything starts failing. The next person who touches secrets reads that before they touch anything, and skips the afternoon I lost.
None of this means ask less. Ask constantly, it's still the fastest way to get good. Just do the cheap thinking yourself first, and once you've got the answer, put it somewhere the next person will trip over it. The best engineers I've worked with aren't the ones who know everything. They're the ones who made sure nobody had to learn it the hard way twice.
References
- 01How to Ask Better Questions — Bo French (Atomic Object — Spin)