The hard part of bug management isn't picking a tool. It's deciding where bugs enter, who sets priority, and when a fix actually counts as done.

A client drops "login is broken again" into a WeChat group with a blurry screenshot. Three people read it. Nobody files a ticket. Three days later the client asks for status and you spend ten minutes scrolling chat history.

Close that door first.

1. One intake channel, and a translator

Phone calls, email, a client's CEO mentioning something at dinner — none of that goes straight to developers.

Pick one channel: a client portal ticket, or your account manager filing it on their behalf. Either way it needs six things:

  • Environment (which client deployment, test or production)
  • Account and role
  • Steps to reproduce, written out
  • Expected result
  • Actual result
  • Screenshot or screen recording, plus when it happened

Missing one, it goes back. Sounds bureaucratic. It kills half the "bugs" before a developer ever sees them: caching, someone edited a config, an ancient browser, and "that's how the feature was specced."

2. Put the severity ladder in the contract

Every bug is urgent — that's normal on the client side. What you need is a ruler both sides agreed to before things got tense.

Level What it means Response Handling
P0 Production down, data corruption, money at risk Within 2 hours Fix plan same day, hotfix if needed
P1 Main flow blocked, workaround exists Within 24 hours Current sprint
P2 Localized issue, main flow fine 3 business days Next sprint
P3 UX, copy, styling Batch it Group and do together

The value isn't precision. It's that the client can answer "do I call right now?" themselves. Attach it to the contract and acceptance gets noticeably quieter.

3. Plan sprints at 70% capacity

There is no such thing as a sprint with no new requests in outsourcing. Plan at 100% and the first interruption wrecks the whole thing.

Rule of thumb: available person-days × 0.7. Three people for two weeks is 30 person-days on paper — schedule 21. The other nine absorb P0/P1 work and small changes a client needs answered today.

Then set a freeze point. Anything arriving after the sprint starts goes to the next one by default. If the client insists, name what gets dropped or what it costs. Say it once at kickoff; it saves ten arguments later.

4. One sentence for the sprint goal

"Ship the order module and get client sign-off" is a goal. "15 pages, 8 bugs, 3 APIs" is a list.

A list can't tell you on Wednesday that you're going to miss — and Wednesday is when you can still cut scope. Friday night is not.

5. Log hours per task, watch one number

Half-day granularity is enough. Then watch bug hours ÷ total hours, weekly. Above 30% for three weeks running means something is off: code quality, how requirements were read, or testing. Stop and talk before the client complains.

Bonus: you finally have a basis for quoting instead of guessing.

6. Only the reporter can close a bug

Self-testing, then clicking "closed" is the classic trap. The client re-reports it next round and you treat it as new.

Rule: whoever reported it verifies it. Client-reported, client verifies. QA-reported, QA verifies. Close with one line on which build and how it was checked.

7. Retro in 30 minutes, three actions max

Three questions: which bugs were avoidable, which estimate was furthest off and why, what blocked someone.

Three actions, carried into the next sprint. A 15-item improvement list nobody executes is worse than no retro at all.

One last thing

Tools aren't the point — but tools decide whether any of this survives. Bugs, requirements, sprints and hours living in four separate places means every rule above quietly degrades. Stepwise keeps them in one platform, and the client portal lets clients file and track their own tickets, which removes most of the "is this fixed yet" traffic. Private deployment helps too when the client's own acceptance process is involved.

If you want to test it, import one live project and run two sprints. That'll tell you more than any feature list.