Anatomy of a Good Software Ticket & Workflow

May 5, 2018

Most of the work I do is with remote teams, where externalizing goals is best (less in-person interaction), and processes that lend to asynchronous work (e.g. not relying on people being on at certain times of the day) are best.

Over time, I've found a particular pattern for executing projects and writing tickets that has worked well. Use this for inspiration in your own process, or adopt it to get started.

Starting concepts

I'll take a few concepts for granted here to get us started:

  • You estimate in "points", whether a home-brewed system, or something like the Fibonacci scale
  • You probably operate in "sprints" of 1-2 weeks. These usually need to be pre-planned, and the size of a sprint is informed by how many "points" of effort you were able to get done in past sprints
  • You're probably a technical leader for your team, and work in conjunction with a project manager – though the project manager is tasked with long-term planning and product features appearing in the sprint, you, the tech lead, are just as responsible for helping line up achievable timelines and better the project management process over time

The "unit of work" and its categories

Whether it's GitHub issues, Pivotal Tracker, Trello, etc., these all express a "unit of work", the "ticket", "issue", etc. For the sake of standardizing, I'll just call these tickets.

Tickets tend to fall in a few buckets, or categories:

  • Bugs - Often need immediate resolution, giving them the ability to slip into the current sprint's work. May receive "automatic points", i.e. a timebox (usually a half-day to a day) worth of effort where a developer tries to diagnose the issue, and resurfaces to the team if not resolved.
  • Features - New functionality.
  • Refactors - Adjustments to existing functionality, or technically-focused tickets that bring down the complexity of software through refactoring.
  • Spikes - Research tasks oriented toward architecting, surveying potential solutions/libraries/techniques, prototyping, etc.
  • Risk mitigation - Preemptive security-oriented work, and a lot of DevOps work. Some companies delegate trust entirely to their technical leaders in this arena, and infrastructure is just a hidden cost, but others have trouble internalizing that most of infrastructure/operations is a big exercise in risk mitigation. We pull these out into their own category so we can report on a set of mitigations to management in the future. These are tough, because it's often difficult to trace any revenue back to these.

Ticket/team Agile philosophy at play

The goal in building a solid team is to ensure everyone's on the same page with where the product is going. It should not be the case that a technical leader, or project manager, have too much knowledge of near-term goals for the product. Long-term roadmaps may be less relevant to developers, but even these should at least be superficially shared. A team's members should have roughly equal knowledge insofar as the work to be done in the current sprint.

A team also needs a feel-good factor of forward momentum. This means we want to do work and put it behind us, stacking the pile one rock at a time. This means not letting tickets linger, or letting scope creep sabotage the original intent of a ticket.

Finally, we want to carve out our tickets "on the fly." You've probably seen the project management system with its dozens, hundreds, or even thousands of dead-in-the-water tickets that may have been written too early. Agile methodology leans toward figuring out features just shy of their implementation, meaning less time wasted thinking about work that may turn out to be unnecessary, or not so high-priority as it was weeks/months ago.

These tickets are usually 1:1 with GitHub pull requests (or branches).

Anatomy of a good ticket

A good ticket has a few well-defined sections it implements. Places that anyone on the project can jump to in order to understand the ticket. Here's a good set I normally work with:

  • Business Requirement - A user story or explanation of risk being mitigated that the ticket deals with. In rough terms, it is the business outcome the company is paying for. This can be used later to help deliver high-level reports of progress to management, and keeps it on everyone's mind that every line of code traces back to some business-level justification. If this cannot be clearly defined for a ticket, then you should stop until the Business Requirement can be made certain.
  • Questions (optional) - If a ticket is moved to the Pending Questions status, then questions are always recorded here in the ticket description for a stakeholder to read and respond to.
  • Acceptance Criteria - Once a Business Requirement is set, we need a bulleted list of items that we can check off to know that the requirement is met.
  • Notes - Miscellaneous details that may provide additional context to a ticket. Especially useful for leaving technical code notes – e.g. links to the codebase, hints about what to change in code, etc. Also a great place to leave notes when a team member has a strong opinion on a technical approach for a ticket. Notes don't belong in Acceptance Criteria because they may not represent exactly how the ticket needs to be implemented. I think of them more as "cheat codes" that the team helps to build around a ticket. On a team with a new member, you will find yourself writing a lot of Notes while explaining bits and pieces to them during meetings.
  • Original - Sometimes it's helpful to keep the original ticket description intact, especially if stakeholders are in the system, or if it adds valuable context that is hard to recapture in the other sections. Most often seen for bug reports, where every ounce of information is worth consideration!

Example ticket ("Pending Questions")


  • Business Requirement: The transaction log is inspected nightly for chargebacks, and an admin is notified if one is found
  • Questions
    • We see that chargebacks outside of a 90 day window aren't reported this way. Are there any historical chargebacks to backport into the system? Or can we ignore these?
  • Acceptance Criteria
    • The transaction log at the payment gateway is inspected nightly
    • An admin is notified via an email with subject "ALERT!", and the body shows Name, Email, Amount, and Description of the chargeback
    • A model instance is saved with the details of the chargeback (User reference, amount, description)
  • Notes
    • Jen believes that this can be implemented using the existing TransactionDownloadService
    • We're doing this nightly because the payment gateway throttles requests, and in a previous spike we found that any more often could cause issues
  • Original
    • Mark in accounting noticed reconciliation issues due to chargebacks not accounted for in the system. He hopes we can resolve in the next 2 weeks for their master report.

Ticket process

The goal is to take raw business requirements and turn them into tickets that developers can work on. We want to do this as efficiently as possible. This process can be embedded in a ticket's "workflow" – usually a "status" field in your project tracking system of choice (you may need to customize it a bit to get this working, or re-use its own terminology).

Here's the ticket workflow I've used most often – feel free to tweak for your own needs:

  • Backlog - The ticket isn't ready for work yet, but the team can begin to look at it.
  • Pending Questions - The ticket is pending questions from developers to the client or project manager.
  • Ready for Development - Via team meeting, the Acceptance Criteria were agreed upon, and the ticket is ready for work.
  • … And from there on, you may have "Code Review", "QA", "Acceptance" etc. type statuses depending on your own workflow.

Team meetings

As a team (technical lead, developers, project manager, etc.), you will meet to go over tickets in a sprint (hopefully your next sprint's tickets, but if just starting, then this sprint). Your goal is to convert the Backlog tickets into Ready for Development tickets, or getting them to Pending Questions for the project manager to forward to stakeholders and then record the response to in the ticket.

To do this, rotate a "meeting leader" through the developers / team lead that will screen-share and write the ticket changes out. This person records what the team decides upon for a ticket. They also keep a timer to timebox the time spent with that ticket.

You'll need to establish a URL to a queue in your project management system to pull tickets in the relevant sprint that are "Backlog". The meeting leader just pulls tickets off the top of this queue for the team to look at.

When looking at a ticket,

  • Define the Business Requirement first
  • Then, define Acceptance Criteria by discussing the Business Requirement as a team; the person leading the meeting should simply ask "what is the next Acceptance Criteria item to record?" Someone will suggest something, and the team will discourse if necessary, or agree it's right, and move on to the next item.
  • If questions come up that only a stakeholder or someone else not in the meeting can answer, add them to the Questions section of the ticket, and move it to Pending Questions status afterwards.
  • After Acceptance Criteria seem to be fleshed out, the person leading the meeting should ask "Are we ready to estimate?", giving enough time for any other notes or concerns.
  • Now, have everyone provide their point-estimate via chat at the same time. This helps prevent estimating what others are estimating, so you get a more true number here.
    • And, if the average is too high, or a particular person votes too high (e.g. over a certain threshold, like, say, the equivalent of 3 days of work), then ask why it was voted that high. If well-justified, the ticket can probably be broken into two, and worked on in smaller, more-digestible pieces. We really don't want large tickets entering the "Ready for Development" queue.

Distractions, pitfalls

Here are some common distractions you'll run in to in meetings:

  • Getting caught up in future functionality - Some people have a tendency to want to talk too far into the future of a product, losing sight of the near-term feature. Refocus them.
  • Accidentally expanding ticket scope, or inviting scope creep - Developers sometimes see what isn't there, and sometimes that is well-founded exploration. There's an art to this though; sometimes you're inviting new features that were never even requested by the client. Put these in check as necessary, and let the project manager handle "Do they need this feature too?" type requests.
  • Getting caught up in tech details - Sometimes even the meeting leader (perhaps you, the tech lead!) will go diving into code while screen-sharing. Don't do this! Unless it's for a super quick reference to something, you are basically taking everyone along with you to do work on the ticket! That's at the cost of your time, and everyone else's. If you don't know have an answer that you know the codebase has, setup a "Spike" ticket to go find the answer and put it behind you and move on!

There's also some gotchas:

  • Though seemingly a small detail, I believe it is critical to update Acceptance Criteria (in meetings) as soon as you get answers from the Questions you posed, and delete the Questions as soon as possible! Our goal is up-to-date ticket descriptions that reflect the goal at hand as clearly as possible. This also prevents you from needing to dig through ticket comment history to piece together what's going on; the description is the authority! The old responses/questions don't matter as soon as you convert them into Acceptance Criteria.
  • Some teams end up with too much written in terms of Acceptance Criteria before the team even sees the ticket. The goal of meetings is to arrive at a team-agreed understanding of a ticket, so avoid this! This is where many projects go wrong; the team doesn't have enough say in how work is done.

Handling blockers

Sometimes, one ticket will block another. Don't convert blocked tickets to "Ready for Development" unless they are exceedingly clear. Tend toward leaving them for future meetings, when the blocker is resolved.

Handling bugs

Recognize two types of bugs:

  • Emergency bugs - Go straight to "Ready for Development" status, often a project manager puts them in with as much detail about the bug as possible. Decide what point estimate to automatically apply (e.g. 1 day) and make it clear the team is timeboxed on these – i.e. if it takes longer than 1 day, it needs to go back to "Backlogged" for the team to consider. This is the only type of ticket that can bypass meetings, initially.
  • Regular bugs - These may not be high-priority, and so go in with the normal set of tickets to look at.

Timeboxing ticket review

You want to set a time limit (e.g. 5-10 minutes) that you'll spend on a ticket. If this time limit is hit, one of a few things has usually happened:

  • Consensus could not be reached on the Business Requirement. This indicates unclear product direction, and often requires that the project manager work out the business goal.
  • Consensus could not be reached on Acceptance Criteria. This can indicate that a "Spike" should be authored to do research and clear up the confusion. For example, perhaps the team could not decide if Postgres built-in search was acceptable for the use-case vs. bringing in Elasticsearch.
  • The ticket represents something too complex. The tech lead should take that ticket, break it down, and let the team approach it again (or, alternatively, leave a note in the ticket to break it down next time you meet and move on).
  • … Or, somet other issue is afoot. Take note and bring up in retrospectives later.

In all these cases, we move on from the ticket for that meeting. This way, no one ticket can capitalize on all of the team's time, and progress can still be made in other areas.

Always move forward

If client requirements change out from under a developer, and the only action is to either abandon the ticket or rewrite it, always close out the ticket as-is and meet to agree on a new one.

Here's why:

  • The ticket is now an irrelevant sunk cost – close it!
  • It should be closed in a way that still credits the team the "points spent." It's still work that was done, even if the client requirements changed out from under it. It's also good psychologically: it feels bad to be the developer that has their ticket deleted.
    • If they wrote code you believe to still be relevant, keep their branch around in source control and reference it in your new ticket for the next developer to use as a starting place
  • The ticket has context around a now-unnecessary or not-quite-yet-correct feature in terms of its comments, history, etc. – this is all noise, close it out!
  • The priority of the feature may have changed. No reason to keep working on it in the same ticket if this is the case; subject it as if a new feature!

Doing work, dealing with the unforeseen

Developers now only need a link to the current sprint's "Ready for Development" tickets. They can self-assign and move it to "In Progress" or similar, at this point. Simple!

Sometimes a ticket is far more complex than thought, has some important items still not explored, or is outright unachievable by that developer within the alotted points-estimate. In these cases, the developer should return the ticket to "Backlogged" status (with a reason) for the team to look at again. That developer can explain their problem in the next meeting, and the team can decide how to tackle the issue.

A warning on estimating developer productivity

It is tempting to compare developers by comparing point-output. Be wary of this;

  • If a developer returns tickets to "Backlogged" instead of wasting additional time on them due to a problem with the ticket, they would be penalized by losing points.
  • Senior developers pairing with juniors can't work on their own tickets. The junior could even end up with a higher point-output.
  • Team members who are spending too little time in code review will have more time to inflate their "point output" and slow down other team members as a result.

Points really only have meaning at the team level; a team produces points, not a developer. Use the team-level estimates to determine how much work can fit in a sprint.

Use every-few-weeks retrospectives to tweak process

Be sure to check in with the team to see what's working, and what isn't. Change this process, ticket statuses, meeting format, etc. as the team sees necessary!

This is also a chance to decide if code refactors (i.e. tickets that don't offer much business value aside from reducing time spent on future issues, or reduction of bugs) are necessary, and where they are.

Conclusion

I hope this gave you a good template to start with for executing work. I've used this exact framework on remote projects as well as for single-person consulting, and it has some great benefits:

  • Everything is externalized for working on a project – any team member can peer in at what is to be done, or what's getting done, and get a high level of detail
  • It emphasizes incremental forward progress; requirements come in, get broken down, and small chunks can go directly to production as they are completed
  • It's tool-agnostic; you can worth with most any project tracking platform, especially if you're already committed to one

Feel free to reach out if any questions, or you need help!


By Daniel Starling

Software consultant in Portland, OR

Contact me

Daniel Starling

Software consultant in Portland, OR

Need help? Contact me!