# Asking Good Questions

> How to ask questions at work that get fast, useful answers: being specific, showing your work, avoiding the XY problem, and picking the right channel for the moment.


---

# Asking Good Questions

Some questions get answered in two minutes. Others sit in Slack for three days, or get a one-word reply that
doesn't help at all. The difference usually isn't luck, and it isn't about how senior the person asking is.
It's about how the question is built.

Nobody teaches this. You learn to code, then you get dropped into a codebase you don't understand, working
with people who are busy, and you're expected to figure out how to ask for help without wasting their time
or looking like you didn't try. This guide is the part nobody explains: what makes a question fast to
answer, a template you can reuse under pressure, and how to pick the right channel so your question actually
lands.

## The phases

1. **[Why Some Questions Get Answered Fast and Others Get Ignored](01-why-questions-get-ignored.md)** -
   specificity, showing your work, and the XY problem: asking about your attempted fix instead of the real
   problem.
2. **[The Question Template That Actually Works](02-the-question-template.md)** - a reusable structure for
   any question, plus a bad question rewritten into a good one.
3. **[Async vs. Sync, and Reading the Room](03-async-vs-sync-reading-the-room.md)** - Slack versus a ticket
   versus a meeting versus walking over, respecting focus time, and when to escalate.

Read them in order. If your question is already solid and you only need to know where to send it, start
with Phase 3.


---

# Why Some Questions Get Answered Fast and Others Get Ignored

"Hey, does anyone know why this isn't working?" gets silence. "The `/checkout` endpoint returns a 500 when
`cart_id` is null, but only in staging - anyone seen this?" gets an answer in five minutes. Same asker, same
skill level, wildly different response. The question itself did the work.

## Vague questions get vague answers, if they get answered at all

"It doesn't work" tells the reader nothing. What's "it"? What does "doesn't work" mean - a crash, a wrong
number, a blank screen? The person reading your message now has to ask three follow-up questions before they
can even start thinking about the actual problem. Most people, staring at a busy Slack sidebar, scroll past
instead.

Compare:

- **Vague:** "My tests are failing, any ideas?"
- **Specific:** "`test_user_login` fails with `AssertionError: 401 != 200` after I added the rate limiter
  middleware. Passes if I comment the middleware out."

The second version lets someone answer without opening your branch. They already know the symptom, the
suspect, and a data point that rules things in or out. Specificity isn't about writing more - it's about
including the two or three facts that let someone reason about the problem instead of interrogating you for
them.

## Show your work

"How do I fix this bug?" invites a question back: "what have you tried?" Skip that round-trip - answer it
up front. Showing your attempts does two things: it proves you didn't skip the first steps everyone reaches for
(checked the logs, read the error, searched for it), and it stops someone from suggesting the first thing
you already ruled out.

"I checked the logs, nothing unusual. I tried restarting the service, same error. I searched the error
message and found a GitHub issue that looked related but their fix didn't apply here" tells a reviewer
exactly where the trail goes cold. Now they can start past that point instead of re-walking it with you.

This doesn't mean listing everything you did. Two or three attempts, the ones that felt most promising or
most confusing, are enough. If you tried nothing yet, say that too - don't imply you dug in when you
didn't.

## The XY problem: asking about your attempted fix instead of the real problem

The XY problem is when you have problem X, decide solution Y might fix it, get stuck on Y, and then ask
about Y - without mentioning X at all. The person answering solves Y for you, and it turns out Y was never
going to fix X. Everyone's time is gone.

**Real-world example.** A developer needs to get the last three characters of a filename (X: check the file
extension). They decide the way to do that is to get the string's length and slice it (Y). They ask: "How do
I get the length of a filename string?" Someone answers that. They ask: "How do I slice the last three
characters from a string?" Someone answers that too. Only after both answers do they discover the filenames
sometimes have no extension, or a four-letter one, and the whole slicing approach was wrong from the start.
If they'd asked "how do I check a file's extension reliably?" the first answer would've pointed at a
library function that handles all of it.

The fix is cheap: state the actual goal, then mention your attempted approach as context, not as the
question. "I'm trying to check a file's extension. I was going to slice the last three characters off the
filename - is there a better way, or does that work here?" Now the person answering can redirect you before
you've built on a broken foundation.

The pattern to watch for in yourself: if your question is entirely about *how* to do something, and you
haven't said *why*, stop and add the why. It costs one sentence and saves the whole detour.

```quiz
[
  {
    "q": "Why do vague questions like \"it doesn't work\" get slow or no responses?",
    "choices": ["People are too busy to help beginners", "The reader has to ask follow-up questions before they can even think about the problem", "Vague questions are against most team norms"],
    "answer": 1,
    "explain": "A vague question shifts the work of narrowing the problem onto the reader, so most people skip it instead."
  },
  {
    "q": "What is the XY problem?",
    "choices": ["Asking two questions at once", "Asking about your attempted solution (Y) instead of your actual goal (X)", "Asking a question that has two possible answers"],
    "answer": 1,
    "explain": "You get help with Y, but Y may never have solved X - and nobody knew X to redirect you."
  },
  {
    "q": "What's the cheapest fix for the XY problem?",
    "choices": ["Never mention your attempted approach at all", "State the actual goal first, then mention your approach as context", "Ask a stranger instead of a teammate"],
    "answer": 1,
    "explain": "One sentence stating the real goal lets the person answering catch a wrong turn before you build on it."
  }
]
```


---

# The Question Template That Actually Works

Five parts, in this order: what you're trying to do, what you expected, what actually happened, what you
already tried, and - if you can put one together - a minimal reproduction. Not every question needs all
five, but running through them before you hit send catches most of what makes a question unanswerable.

## The template

**1. What you're trying to do.** The goal, not the mechanism. "I'm trying to paginate a list of orders,"
not "I'm trying to use `slice()` on this array." This is what prevents the XY problem from Phase 1 - if your
approach is wrong, this line is what lets someone catch it.

**2. What you expected.** What should have happened if things worked. "I expected the second page to start
at order 21." Sounds obvious, but it tells the reader what "working" means to you, which is often not
obvious from the code alone.

**3. What actually happened.** The exact error, output, or behavior - not a paraphrase. Copy-paste the real
error message and stack trace. "It gives an error" makes someone ask "which one?" before they can help.
"It threw `TypeError: Cannot read properties of undefined (reading 'length')` on line 42" doesn't.

**4. What you already tried.** Two or three attempts, each with its result. This is the "show your work"
from Phase 1, folded into the template so it's never skipped.

**5. A minimal reproduction, if you can make one.** The smallest version of the code that still shows the
problem - ideally something someone can paste and run. Not always possible (some bugs only show up with
real data or a live service), but when it is, it's the single biggest time-saver on this list. Building it
also frequently reveals the bug to you before you even ask.

## A bad question, rewritten

**Bad:**

> Hey, my API call isn't working, anyone know why?

This has none of the five parts. It doesn't say which endpoint, what "not working" means, what was tried, or
show any code. Anyone who wants to help has to interview the asker first - and most people won't bother.

**Rewritten with the template:**

> **What I'm trying to do:** Fetch a user's order history from `/api/orders?user_id=123` and render it in
> the dashboard.
>
> **What I expected:** A 200 response with a JSON array of orders.
>
> **What actually happened:** A 403 response with body `{"error": "missing scope: orders:read"}`. Full
> response in the thread.
>
> **What I tried:** Confirmed the auth token is valid (works fine on `/api/profile`). Checked the token's
> scopes in the JWT payload - `orders:read` isn't listed. Not sure if I need to request that scope somewhere
> or if it's a backend config issue.
>
> **Minimal repro:**
> ```
> curl -H "Authorization: Bearer $TOKEN" https://api.internal/orders?user_id=123
> ```

This version can be answered without a single follow-up question. The reader can look at the scope issue
directly, or say "yeah, you need to request that scope in the OAuth config" in one reply. The asker did the
narrowing work instead of outsourcing it.

## Trim it to fit the moment

The full template is for a written question in Slack, a ticket, or a forum post - anywhere the answer might
come from someone who wasn't there for the last hour of your debugging. In a quick verbal check with someone
sitting next to you, you can compress it to two sentences: goal, and what's different from expected. The
five parts don't have to be five paragraphs; they're five things to make sure are covered, however briefly
the moment allows.

```quiz
[
  {
    "q": "In the template, what should \"what actually happened\" contain?",
    "choices": ["A paraphrase like \"it gives an error\"", "The exact error message, output, or behavior", "A guess at what caused it"],
    "answer": 1,
    "explain": "\"It gives an error\" forces a follow-up question. The exact text lets someone act immediately."
  },
  {
    "q": "Why does the template start with \"what you're trying to do\" rather than the code you wrote?",
    "choices": ["It's a more polite opener", "It surfaces the actual goal, which catches an XY problem before it wastes time", "It's required by most style guides"],
    "answer": 1,
    "explain": "Leading with the goal is what lets a reader catch a wrong approach instead of answering the wrong question outright."
  },
  {
    "q": "What's the biggest time-saver among the five parts, when you can produce it?",
    "choices": ["A long list of everything you tried", "A minimal reproduction someone can paste and run", "A polite greeting"],
    "answer": 1,
    "explain": "A minimal repro often reveals the bug to you before anyone even answers, and removes all guesswork for whoever helps."
  }
]
```


---

# Async vs. Sync, and Reading the Room

A perfectly written question can still land badly if it goes to the wrong place. Interrupting someone
mid-focus for something that could've waited a day burns goodwill. Waiting three days to ask something
blocking your whole team burns time. The channel matters as much as the wording.

## Match the channel to the urgency and the complexity

**Async (Slack message, ticket comment, email)** - default for most questions. Anything with a clear
answer that doesn't need back-and-forth: "does this API endpoint support pagination?", "is staging down for
anyone else?", "can you review this PR when you get a chance?" The person can answer when they resurface
from focus work, and there's a paper trail others can search later.

**A scheduled call or meeting** - for anything that needs real back-and-forth, or where explaining in text
would take longer than talking. "I don't understand how the auth flow is supposed to work across these three
services" is a 15-minute conversation with a whiteboard, not a Slack thread that spans forty messages over
two days. If you're rewriting your message a third time trying to make it clearer in text, that's the
signal to ask for 15 minutes instead.

**Walking over / interrupting in person** - reserve for genuinely urgent, blocking issues: production is
down, a deploy is failing and you need a second pair of eyes right now, you're about to ship something
risky and need a quick sanity check before you do. If it can wait an hour, it's not this category.

## Respect focus time

Most questions are not emergencies, even when they feel urgent to the person asking. Before interrupting
someone in a meeting, wearing headphones, or with a "do not disturb" status, ask yourself: will this still
matter in two hours? If yes, it's async. Sending it async doesn't mean it gets ignored - it means the
person can answer on their own schedule instead of dropping what they're doing.

A useful habit: when you send an async question, say whether it's blocking. "No rush, whenever you have a
sec" versus "this is blocking my PR from merging today" tells the reader how to prioritize you against
everything else in their queue. Without that signal, people default to treating everything as non-urgent -
which is usually the safer assumption for them, even if it's frustrating for you.

## Escalation etiquette

Sometimes you ask and get silence. The etiquette here is about timing and framing, not about being pushy.

- **Give it a real window first.** A few hours for something blocking, a day or two for something that
  isn't, accounting for time zones and whether the person's out. Pinging again after ten minutes reads as
  impatient, not urgent.
- **Nudge before you escalate.** A polite bump in the same thread - "following up on this, still blocked
  if you get a sec" - is not escalation. It's a normal part of async work.
- **Escalate the blocker, not the person.** When you do need to go to a manager, frame it around impact:
  "I've been blocked on X since Tuesday, asked in the thread, wanted to flag it's now affecting the sprint
  deadline" - not "so-and-so is ignoring me." The first gets the blocker solved. The second makes you look
  like you're keeping score.
- **Loop the original person in, don't go around them.** If possible, tell them you're escalating before or
  as you do it - "hey, going to loop in Sam since this is now blocking release, wanted you to know" - rather
  than letting them find out from their manager.

"I asked and got no answer" becoming "I'm now asking your manager" should feel like a last resort after a
real wait and a genuine nudge, not the second message you send.

```quiz
[
  {
    "q": "When should you default to an async channel like Slack or a ticket instead of a meeting?",
    "choices": ["Always, meetings are never appropriate", "For most questions with a clear answer that doesn't need back-and-forth", "Only when the question is urgent"],
    "answer": 1,
    "explain": "Async is the default for clear, answerable questions - it respects the other person's schedule and leaves a searchable record."
  },
  {
    "q": "What's a useful habit when sending an async question?",
    "choices": ["Marking every message as urgent so it gets seen", "Stating whether it's blocking, so the reader knows how to prioritize it", "Sending it multiple times to different people at once"],
    "answer": 1,
    "explain": "Without an urgency signal, most people default to treating a message as non-urgent - saying it's blocking changes that."
  },
  {
    "q": "What's the right way to escalate a question that's gone unanswered?",
    "choices": ["Go straight to their manager as soon as you notice no reply", "Give it a real window, nudge once, then escalate the blocker (not the person) while looping them in", "Ask the same question in a different channel without mentioning the first one"],
    "answer": 1,
    "explain": "Escalation should follow a genuine wait and a polite nudge, and should frame the impact rather than blame the person."
  }
]
```

Once you can get answers fast, the next skill is handling the moments where nobody's around to ask at all -
see [Your First On-Call](/guides/your-first-on-call) for what changes when you're the one holding the pager.
