How to make your sprints awesome

18 Oct 2020 - Hasitha Liyanage

Image credits: SpaceX

“Making sprints awesome” is literally the name of the internal document that describes our engineering process in detail. It is an agile process that is inspired by SCRUM and the 12 Agile Principles. We are making it public!

What a typical sprint looks like

A typical sprint starts on a Monday and lasts for 10 working days. Each day, as a team member you aim to reach the “definition of done” (DoD) for approximately 10% of your assigned work. DoD is “ready to deploy to PROD if necessary”. You should make even small, partial tasks ready for production by placing them behind feature flags. Enable feature flags for ongoing work in QA but disable them in PROD.


Wednesdays are special in that their focus is on the next sprint. By the end of the first Wednesday of the current sprint, you should have completely reviewed the requirements documents and the UI designs for the next sprint. You will need to take as much time off your planned work as necessary to do this properly. By the end of the second Wednesday of the current sprint, there should be zero clarity issues about the requirements documents and the UI designs, and all stories from the requirements document should be fully groomed.

Here, “groomed” means that each story has a complete technical design behind it and all the work is captured as subtasks in the task tracker (in our case, ClickUp) and each subtask has an estimate.

Our requirements documents come in the form of a 4-6 page “product outline” (PO) document which contains an introduction to the purpose of the feature, a list of stories and their acceptance criteria, along with links to UI designs.

So in order to have all the stories in the next sprint’s PO fully groomed by the second Wednesday of the current sprint, you will have to take a little time off your planned work each day to groom those stories. You will also need to make sure that you raise all questions and clarifications for the product manager as comments on the PO document well ahead of the second Wednesday.

At the end of the sprint, the current sprint’s work should be in production and the next sprint work should be ready for development (fully groomed, estimated and assigned).

Before you start the sprint on Monday

Your work should be already groomed, planned and assigned to you from the previous Friday.

In our philosophy, “grooming” is the process of eliminating uncertainty associated with a task. The source of uncertainty could be requirements clarity, dependencies, risks, technical knowledge gaps, architecture changes, implementation details, effort estimates – anything basically. While any of those remain, your task is not “ready for development”.

One of the stories assigned to you may look like this:

What the story title looks like:

As a user, I should be able to set reminders for for a ticket, so that I’ll be reminded to follow up on some action

What story ACs look like this:

  1. I should be able to enter a reminder to a ticket. I should be able to enter a date and a reminder text.
  2. I should receive an error if the date is in the past.
  3. I should be able to enter a reminder with a blank text.
  4. I should receive an email notification on the date specified in the reminder.
  5. I should see the following in the email text: <template>.
  6. I should receive the email on or before 9am in my timezone.

What UI designs look like:

“Add reminder” button. Changes encircled in red.


“Add reminder” modal


What story subtasks look like:

The subtask effort estimates are also shown here in hours.

  1. [Task Scheduler] Create new task queue “ticket reminders” [1h]
  2. [Ticket API] Create new endpoint the “add ticket reminder” [3h]
  3. [Task Scheduler] Create new task handler to send email when “ticket reminder” tasks are triggered [2h]
  4. [Ticket UI] Create dummy modal “add ticket reminder” [2h]
  5. [App] Wire up “add ticket reminder” modal to Ticket API [2h]
  6. [Testing] End to end developer test [30m]

What a fully groomed subtask looks like:

Let’s take the subtask,

[Ticket API] Create new endpoint the “add ticket reminder

The subtask can have ACs of its own. The only difference is that the ACs are for a developer and not the end user.

AC #1 API clients should be able to call the following endpoint to create a reminder for a ticket.

  POST /tickets/{ticketId}/reminders
    "text": "foo",
    "date": "2020/09/20",
    "userId": "jsmith",
    "ticketId": 1234

AC #2 Success response should look like this:

  200 OK
    "text": "foo",
    "date": "2020/09/20",
    "userId": "jsmith",
    "ticketId": 1234

AC #3 Failure responses (400, 401 and 500) should follow standard guidelines.

AC #4 Logic should be as follows:

  1. Check if the date is valid and is in the future
  2. Check if the user exists
  3. Check if the ticket exists
  4. Add new task to the “ticket reminders” queue
  5. In this subtask, the triggering of the scheduled task will only create a log entry. The actual sending of the email is a separate subtask.

Note here how we have made the subtask small, self-describing and self-contained. The assignee can execute it without having to chase after the author for explanations. We have also realized that if we tried to generate and send the email in this same subtask, it would probably span multiple days, so the first subtask merely generates a simple log entry for the developer to verify.

What questions you should have already asked:

Here are some examples of clarifications you have already made regarding this story from the previous sprint (which is when you groomed the tasks for the current sprint).

You: What should happen if the same user enters multiple reminders to the same ticket?

  • Product Manager: Right now, we only want one reminder. But do what’s easiest to implement.
  • Team Lead: Let’s allow multiple reminders. It’s easier to push multiple jobs into the queue than having to check the queue for existing jobs from the same user for the same ticket.

You: Should we be able to view or delete existing reminders?

  • Product Manager: In the future, may be. But we don’t want to spend time on that until we know if the basic reminder feature will be useful.
  • Team Lead: In that case, no need for a database record to represent the scheduled reminder. Just rely on the queue only.

You: What about performance?

  • Team Lead: System creates about 1000 tickets a week. Even if each one of those has a reminder, which is unlikely, our queue system can easily handle it. Performance is not an issue right now.

Day 1: Monday

Your goal today is to complete about 10% of your sprint commitments.

Considering an 8 hour workday and 75% productivity, you will have about 6 hours of productive time on a typical day.

This is what you will complete on Monday and report as “what I completed yesterday” during the Tuesday morning daily stand-up meeting:

  1. [Task Scheduler] Created new queue “ticket reminders”
  2. [Ticket API] Created new endpoint “add ticket reminder”
  3. [Task Scheduler] Created new task handler to send email when “ticket reminder” tasks are triggered

If you look at the groomed tasks, you’ll see this adds up to approximately 6 hours of work.

Always aim to reach “doneness” by the end of the day: your work should be production ready. The code should be merged to master and at least deployed to the QA environment before you go home.

If you find yourself going home with subtasks or pull requests still in progress, then it’s an indication that your subtasks and pull requests are too big. Slice them ruthlessly.

If it’s too difficult to do all of this (write the code, test, get code reviewed, merge and deploy) in one day, at a very minimum, submit the pull request before you go home and aim to get it reviewed, merged and deployed the very next day.

There are many ways to slice stories and subtasks into smaller and smaller slices without breaking anything. One of the biggest is the feature flag. You can also do things like implementing a specific capability as a function, unit testing the function and sending that as a PR. That addition in itself doesn’t break anything. The usage of the function can be in a future PR.

Day 2: Tuesday

Your goal today is to complete roughly 20% of your sprint commitments.

Before you start work, make sure someone reviews your pull requests from the previous day so that you can merge them. You only “close” a task or subtask when it’s actually deployed to the QA environment and verified by you to be functioning. In the case of Monday’s work, you need to manually call the “add ticket reminder” endpoint and test whether the log entry appears when the task is triggered. Ideally, your task scheduler should have some way to simulate the passage of a day, otherwise you’d have to wait at least till the following day to verify that the task got triggered!

Today, you can either continue to work on the backend (e.g. sending the email) or start work on the front end. While from an engineer’s perspective, it’s more logical to complete the back end work, you should also consider making progress on the front end side.

By building and deploying a dummy “create reminder” modal to the QA environment, your QA and design team members can at least verify the look and feel of the UI while you continue to work on the back end. You want as many bugs as possible to be reported early, not on the last day of the sprint. The dummy modal will simply display a “coming soon” alert box when the user clicks the “Set” button.

Now you may have a question, if you merge a PR with something like the above to master, won’t it be at risk of going to production along with the next production deployment? This is where feature flags come in. Rather than merging everything to a separate QA branch and then trying to do massive merges from QA to master after testing, put everything behind a feature flag. Set the feature flag in the QA environment to true (so that we can test the incomplete bits internally) but set it to false in production (so that end users won’t see new features until development is completed and the product manager decides to switch on the flag).

So the “what I completed yesterday” report for your Wednesday morning stand-up may look something like this:

  1. [Ticket UI] Create dummy modal “add ticket reminder”
  2. [App] Wire up “add ticket reminder” modal to Ticket API
  3. <Another task completed>

Day 3: Wednesday

Your goal today is to review the draft product outlines and UI designs for the next sprint, and also to complete 30% of the current sprint’s planned work.

The first priority today is for you to read the draft product outlines and draft UI designs shared by the product manager. Take as much time as necessary to read through every line in the document and review every changed screen in the UI designs.

Your aim is to get 100% clarity about the product manager’s expectations. Ask all your questions in the form of in-line comments within the documents and the designs so that everyone can see them. The product manager is expected to resolve all such questions at least two days before the second Wednesday of the sprint so that the engineers will have enough time to nail down their tech designs and complete grooming by the second Wednesday.

You can choose to review the documents individually or in a group, as long as everyone reads through the documents properly.

You may find that you don’t have much time left over to do sprint work on Wednesday. That’s OK. If you see that happening, plan your work so that you compensate by doing more work on Monday, Tuesday, Thursday and Friday.

The 10%-per-day is a rough guideline to ensure a smooth burndown. It’s not an exact rule.

So “What I completed on Wednesday” will probably look like:

  1. Reviewed product outlines for the next sprint
  2. [Testing] End to end developer test for “add ticket reminders”

The first task probably took you about 4 hours, leaving you only about 2 hours for sprint work.

Days 4: Thursday

Your goal today is to complete roughly 40% of the current sprint’s work and groom approximately 20% of the work you need to do in the next sprint. That 20% figure comes from the fact that you have roughly 5 days from the first Wednesday to the second Wednesday to complete the grooming for the next sprint.

Grooming can be done many ways. Some teams get into a meeting room or call and groom the stories together. In some teams, each member will own a subset of the stories, groom by themselves and only get into a meeting to review and discuss the outcomes. This second method is often preferable, not only because it is a more efficient use of time, but also because it gives each team member a sense of ownership. They can take on some small area of the system (even if it’s just one story) from product outline to production.

So today you might spend some time figuring out the APIs, database changes and front-end changes for one of the stories for the next sprint. Obviously, you will need to consult your team lead or architect wherever you need clarifications about the current system architecture and implementation details. The end result should be a set of self-explanatory subtasks with estimates.

Obviously, you will also work on the current sprint’s tasks.

Your “What I completed on Thursday” may look like:

  1. [Common Libs] Created email template for task notifications
  2. [Scheduler] Send email notification on task reminder rigger (replaced previous test log entry)
  3. Groomed ABC story for next sprint

Day 5: Friday

Your main goal is to reach roughly 60% completion of your sprint work. Why? Because that’s the progress you need to make if you’re to reach 100% by next Thursday. Obviously, you have to make progress on the next sprint grooming too.

What about unplanned tasks? E.g. unexpected production issues, manager requests etc.? Again, assuming an 8 hour workday and 75% productivity, don’t plan 8 x 0.75 x 10 = 60 hours of work for yourself for a sprint. Leave aside some hours for unplanned work. Let’s say when you look at the past few sprints, you notice that you’ve done about 10 hours of unplanned work per sprint, then only plan for 50 hours. You’re bound to get 10 more hours of unplanned work this sprint too.

So today, your work may look like this:

  1. [ABC component] completed some subtask from another story from this sprint
  2. Groomed PQR story from next sprint
  3. Fixed bug in task scheduler <bug ID>
  4. Attended a training

Day 6: Monday

Your goal is to reach about 70% of current sprint work “doneness” and about 60% of next sprint “readiness” (i.e. grooming).

There’s another thing you should ensure today: if you’re to complete grooming the next sprint’s work by Wednesday (Day 8), the product outline can’t keep changing till the last day. It needs to freeze at some point. So make sure that by the end of today, all clarifications related to all the stories, ACs and UI designs for the next sprint have been resolved by the product manager. There should be no unresolved comments. All clarifications should be incorporated into the ACs and the designs. Also remember, at this point you should not have any questions in your mind that you haven’t already raised to the product manager. If something has to change because of a question you raised too late, it’s your own fault.

Day 7: Tuesday

Your goal is to reach about 80% of current sprint work “doneness” and about 80% of next sprint “readiness” (i.e. grooming).

Day 8: Wednesday

Your main goal today is to get to 100% readiness for all stories assigned to you for the next sprint. All the subtasks should be in place, they should be self-explanatory, they should each have your estimate attached, and you should have reviewed them with your team lead and team members. In other words, all your subtasks should look like the example in the “Before you start the sprint on Monday” section above.

In addition to this, 90% of your current sprint work should have reached “doneness”. As with the first Wednesday, if you find you don’t have a lot of time left over after grooming, plan your sprint so that you compensate by shifting more work to days other than Wednesday. Note that this does not mean you work extra hours. Each sprint, you should only take up work that you can complete without overworking. So you need to account for the fact that the bulk of each Wednesday is focused on the next sprint.

Day 9: Thursday

Your only goal today is to get 100% of your sprint work to “doneness”. This is because Friday is focused on retros, planning the next sprint and fixing any last minute bug fixes. You should not be leaving any planned work for Friday.

Ideally, “doneness” includes QA verification as well. But practically, your QA will be lagging behind your development by a day or two, especially if you don’t deploy to QA on a daily basis or if your subtasks are not sliced in a QA-testable manner. So aim to have as much of your work as possible QA-verified by today. Keep Friday for any last minute bugs, and to provide your QA a bit of a buffer to catch up with your work.

Day 10: Friday

Your main goal today is to completely close off the current sprint: everything should either be already in production or in the very least, fully QA verified. Any spillovers should have been moved to the next sprint. Your task tracker (in our case, ClickUp) for this sprint should be completely clear.

Your second goal is to complete your sprint plan for next week: assign the already groomed stories and subtasks to team members, check that everyone’s work is within their capacity and commit to the product manager. Ideally, if you have done a proper job of creating and estimating subtasks, this should be a quick drag-and-drop job. When you come to work next Monday, there should be zero uncertainty about what needs to be done. The sprint plan should tell you exactly what you need to do.

The first thing Friday morning, your team will get together to do a retrospective of the sprint. You compare what you planned to achieve at the beginning of the sprint, You then try to understand the reasons behind that gap and come up with some concrete action items to improve. You then add those action items to your team backlog. This may take 30 minutes (at most 1 hour).

Next, you take all the tasks that have been groomed for the next sprint and arrange them into a sprint plan. Since all the tasks already have estimates and assignees, all you have to do is to sort them in order of priority and then make sure that the sum total of the estimates of tasks assigned to each person is within his or her typical sprint capacity. The resulting plan is what you communicate to the product manager and stakeholders. This too, will take about 30 minutes to one hour.

If you still have some last minute gaps or bugs to take care of, the remaining time on Friday is the time to get them out of the way. If there are no such bugs or gaps, then the remaining time is yours! Get together and do something that the team likes: maybe some tech experiments, maybe have a celebration, or maybe just go home and rest!