0% completed
Choosing What to Leave Out
On This Page
What a Non-Goal Is
The Cost of Each Thing Left In
Writing the Non-Goals Down
Why the People Who Asked Must Agree
How Non-Goals Fail
When to Leave Something In
Using This in an Interview
Key Takeaways
Practice Questions
The new scheduler at the marketplace will:
- Start every job within 60 seconds of its scheduled time, including the minutes after midnight when many jobs start.
- Retry a job after a timeout only if the job has declared that it is safe to run twice.
- Never retry a job that has declared that it is unsafe, and instead alert its owning team within 15 minutes when a run times out.
- Give every run an identifier and a recorded result that the owning team can see.
- Have one on-call rotation, in the platform group.
The new scheduler will not:
- Run multi-step workflows, in which one job starts only after another job finishes.
- Start jobs to the exact second.
- Guarantee that a job declared unsafe runs exactly once.
- Host or run the code of the jobs it starts.
The second list took longer to agree than the first. Every item on it was something a team had asked for, and every item was left out on purpose. What makes such a list a set of decisions that stay decided, rather than a set of refusals that teams keep reopening?
What a Non-Goal Is
A non-goal is a written decision that the work will not do something a reasonable reader might expect it to do. It is not a list of everything outside the project. Nobody expects the scheduler to send email, so "will not send email" adds nothing. A non-goal is worth writing only when someone has asked for the thing, or when a reader would assume it is included.
Each non-goal has three parts:
- The decision, stated plainly.
- The reason, usually a cost in numbers and the number of teams that need the thing.
- A revisit trigger, which is a measurable condition under which the decision will be reopened.
The trigger is what separates a non-goal from a refusal. A refusal says "no." A non-goal says "not now, for this reason, and here is the evidence that would change our answer."
Notice that every non-goal on the right has its own trigger, and that none of the promises on the left depends on a non-goal being built first.
The Cost of Each Thing Left In
Every feature added to a shared system costs the team that builds it, the team that runs it, and every team that must wait for it. The Staff engineer estimated the cost of each requested item before deciding. Each estimate is rough, but each one is a number that the requesting team can check.
Multi-step workflows. Two of the 26 owning teams asked for them: the data team and the search team. Supporting workflows means storing dependencies between jobs, deciding what happens when one step fails, and showing the state of a whole chain. The platform team estimated about 2 extra quarters of work, which would delay the retirement of schedulers A and B by the same amount. During those 2 quarters, incidents would continue at about 6 a quarter.
Sub-second start times. The pricing team asked for jobs that start at an exact second. The Staff engineer checked every job's stated need and found that the tightest real requirement was about 2 minutes, for a job that refreshes prices. Meeting a one-second target at the midnight peak would need a different and more complex dispatch design, for a need that no job has today.
Exactly-once runs for unsafe jobs. The finance lead asked that the seller fee job be guaranteed to run exactly once. No scheduler can promise this. When a run times out, the scheduler cannot tell whether the job finished its work, stopped halfway, or is still running. Only the job can check its own effects, for example by asking whether a seller has already been charged this month. The scheduler therefore promises something it can keep: a job declared unsafe is never retried, and its owning team is alerted within 15 minutes.
Hosting job code. The data team asked the platform group to run the jobs themselves, not only to start them. That change would turn each team's migration from changing a schedule entry into moving its job code onto new machines. The Staff engineer estimated that it would raise the average effort per team from about 5 engineer-days to about 20.
Writing the Non-Goals Down
The non-goals went into the design document as a table, with the team that asked for each one.
| Non-goal | Asked for by | Reason | Revisit trigger |
|---|---|---|---|
| Multi-step workflows | Data team, search team | 2 of 26 teams; adds about 2 quarters | 5 teams with a written use case |
| Start times under one second | Pricing team | Tightest real need is about 2 minutes | A job whose owner states a business cost for starting one second late |
| Exactly-once runs for unsafe jobs | Finance lead | The scheduler cannot know whether a timed-out run finished | More than 10 percent of jobs declared unsafe |
| Hosting job code | Data team | Raises effort per team from about 5 to about 20 engineer-days | The platform group starts a shared compute project |
Two triggers deserve a comment. The trigger for exactly-once runs does not reopen the guarantee itself, which remains impossible. It reopens a related question: if many teams declare their jobs unsafe, those teams probably need help making their jobs safe to retry. The 42,000 daily runs come from about 6,000 job definitions, because many jobs run every hour or more often. About 4 percent of those definitions were expected to declare themselves unsafe, so 10 percent would mean something had changed.
The trigger for workflows counts teams with a written use case, not teams that mention the idea in a meeting. A written use case states what the chain of jobs does today and what fails without workflow support, which gives the platform group something to estimate.
Why the People Who Asked Must Agree
A non-goal that the requesting team has not accepted is not a decision; it is a disagreement that has not happened yet. If the data team had not accepted the workflow non-goal, it would have kept scheduler B running for its pipelines. The migration would never have finished, and the company would still run two schedulers.
The Staff engineer met each requesting team before the design review and offered something in place of the request. The data team starts each pipeline step at a fixed time today, about 30 minutes after the previous step. On the new scheduler, each step can also read the previous step's recorded result and stop if that step failed. This covers both of the data team's current pipelines, and the search team's single pipeline, without workflow support. Both teams accepted the non-goal, and their managers' agreement is recorded in the document next to the trigger.
The pricing team accepted its non-goal after seeing the 2-minute requirement that its own job had stated. The finance lead accepted the limit on exactly-once runs once the seller fee job's owners agreed to keep their own check against charging a seller twice.
How Non-Goals Fail
Non-goals fail in three common ways:
- They are not written. The request returns halfway through the project as a new requirement. Requirements added after a plan is agreed are called scope creep, and each one moves the end date.
- They are written without a reason. Every new reader reopens the question, and the same argument happens in every review.
- They have no trigger. A permanent "no" leaves the requesting team with nothing to work toward. The team that needs workflows most may build its own small scheduler, and the company then has four.
The third failure is the most expensive, because it recreates the problem the project was meant to solve.
When to Leave Something In
Not everything requested should become a non-goal. A feature belongs in the first version when adding it later would cost much more than adding it now. The run identifier is the clearest example. It is cheap to include from the start, but adding it later would mean changing how every job receives its run request, across 26 teams.
Workflows are the opposite case. They can be built later on top of the run record without changing how any job is started, so leaving them out now costs little. The lesson Planning for Year One and Year Three shows how to design the first version so that a later feature can be added without a second migration.
Using This in an Interview
Name your non-goals early in a design discussion, each with a reason and a trigger. This shows that you considered the request and decided, rather than forgot it:
"I am leaving out workflows for now. Only 2 of the 26 teams need them, and building them would delay the migration by about 2 quarters. I would revisit that when 5 teams have a written use case, and the run record I am keeping makes them possible to add later."
Expect two follow-up questions:
- "What if the team that wanted workflows refuses to migrate?" Explain what you offered them in place of the feature, and that their agreement is part of the decision.
- "Why is the run identifier in scope when workflows are not?" Compare the cost of adding each one later: one changes every job's integration, and the other does not.
Key Takeaways
- A non-goal is a written decision not to do something a reasonable reader might expect, with a reason and a revisit trigger.
- Estimate the cost of each requested item in numbers before deciding to leave it out.
- A non-goal counts only when the team that asked for it has accepted it, usually after being offered something in its place.
- Non-goals without a reason are reopened in every review, and non-goals without a trigger lead teams to build their own systems.
- Leave a feature in when adding it later would cost much more than adding it now.
Leaving workflows out of the first version only works if a later version can add them. That later version is planned, but not built, in Planning for Year One and Year Three.
Practice Questions
1. Why is "the scheduler will not send email" a poor non-goal?
<details><summary>Show answer</summary>Because nobody expects the scheduler to send email. A non-goal is worth writing only when someone has asked for the thing or a reader would assume it is included. Listing unrelated features hides the non-goals that matter.
</details>2. The finance lead wants the seller fee job to run exactly once. Why does the scheduler not promise it, and what does it promise instead?
<details><summary>Show answer</summary>Because the scheduler cannot tell whether a timed-out run finished its work. Only the job can check its own effects, such as whether a seller was already charged. The scheduler promises never to retry a job declared unsafe, and to alert the owning team within 15 minutes when such a run times out.
</details>3. What is the most expensive way a non-goal can fail, and why?
<details><summary>Show answer</summary>A non-goal with no revisit trigger. The requesting team has nothing to work toward, so it may build its own system to meet the need. A fourth scheduler would recreate the problem the project was meant to solve.
</details>4. A team asks for a feature that is cheap to add now but would require changing every job's integration if added later. Should it be a non-goal?
<details><summary>Show answer</summary>Usually not. When adding a feature later costs much more than adding it now, it belongs in the first version. The run identifier is an example: cheap at the start, but a change across 26 teams if it were added after the migration.
</details>Reading Progress
0%
On This Page
What a Non-Goal Is
The Cost of Each Thing Left In
Writing the Non-Goals Down
Why the People Who Asked Must Agree
How Non-Goals Fail
When to Leave Something In
Using This in an Interview
Key Takeaways
Practice Questions