How the totals are made
This page is the whole arithmetic. It is public on purpose. The product claims that its numbers reconcile and that it says what it could not read. A claim of that shape is worth nothing if the reader has to take it on faith.
Most of what follows exists because of the second half. Adding up a column is easy. The hard part is saying, in the same breath, which issues were left out of it and why. A spreadsheet assembled by hand never does it. That is the reason a figure from this gadget can be defended when somebody asks where it came from.
If you are looking for how to set the gadget up, start here. This page assumes it is already on a dashboard.
What is read
One search, and three kinds of field on each issue it returns.
The search is the filter or the JQL chosen in the form. It runs with the permissions of whoever is looking at the dashboard. Two people opening the same gadget can see two different grids, each right for the person looking. A grid read for somebody is never wider than their own view of Jira.
Two exceptions:
- A grid somebody published is their view, and it says so over the figures.
- A grid kept automatically is read while nobody is looking, as the person who switched that schedule on. It is kept only for them.
Per issue, only what the grid needs:
- the two axis fields, so the issue can be placed in a cell;
- the numeric field being added up, or the several that stand in for one another;
issuetype, which carries the hierarchy level, andstatuswhen an axis is status or board column;statusCategoryandresolutiondatewhere the read writes the totals of old finished work, to put each finished issue in the period it was resolved in;createdon the Sprint scope axis, because a sprint set on the creation screen leaves no record in the history.
Nothing else on the issue goes into the grid. Not the description, not the comments, not the assignee.
Two things read more than that, and they are named here rather than rounded off. The Sprint scope axis and Crosstab Sprints ask Jira for each issue's change history. When an issue joined a sprint is recorded nowhere else. Jira hands that history over whole. It carries the past values of every field, the assignee's and the description's among them, and who made each change. Only the changes to the sprint, the status and the field being added up are used. None of the history is kept.
There is one more exception. When an axis is Parent, the epic an issue sits under, the parent arrives as a whole issue and its own summary is what its column is called. So on that one axis the label is text somebody typed into a ticket. It is drawn on the grid, carried into an export and held in a kept grid. Every other axis is labelled with a field value. The axis rule is stricter still, and is covered on the privacy page: no axis can be a person.
A few more things are read when they are needed. Two are about the site, two about the reader and one about a publisher:
- the order a board draws its statuses in, when an axis is status;
- the site's time-tracking settings, when the settings form is open or the figure is a length of time;
- the reader's time zone, from their own Jira profile, when an axis is a date with a time in it or a render may use their totals of old finished work;
- the reader's display name, from the same profile, when they publish a grid;
- a publisher's display name, asked by account id when their grid is drawn.
What counts as a number
A field holds a number if it is one. It also holds one if it is a string written the way a person writes a number: digits, an optional decimal point, an optional exponent. Everything else is no value rather than zero.
That is narrower than it sounds, and deliberately. In JavaScript, Number('0x10') is 16, 0b101 is 5 and 0o17 is 15. A story point estimate carrying the text 0x10 once added sixteen points to a board. The cell drew a figure the reader could find nowhere in Jira. So three notations no Jira field renders and nobody types are refused. The alternative is a total that is wrong in a way nothing on screen can explain.
Booleans are not numbers. A string that is not a number is not a number.
One kind of numeric field is refused as a metric outright. Work Ratio is timeSpent / originalEstimate × 100, a percentage Jira works out per issue. Adding eleven of them gives 5500, which is not a percentage of anything. Jira also writes -1 where an issue has no estimate, so the sum is not even a total of the ones it has. What a reader wants from that column is the ratio of the sums. The sum of the ratios is never that figure, at any size of table.
One estimate, several fields
An organisation rarely keeps one estimate. Three teams put it in Story Points, two in Story point estimate, one in a custom Effort that only they have. A portfolio view still has to be one grid rather than three.
So the metric can be several fields, consulted in order: the first of them that has a value, per issue. That is exactly the rule somebody stitches together with a spreadsheet formula today. The caption under the grid says which fields were in play.
A single field is the same rule with one entry. So a configuration saved before this existed goes on meaning what it meant.
One metric against another
A metric can be set against a second field of the same quantity: the time spent against the original estimate, say. On a full-width page the grid then offers two more views: the second field's total over the same issues, and the first total less the second.
A missing value counts as zero. An issue with five hours logged and no estimate puts five hours into the difference: unplanned work shows up in full. An estimate with nothing logged against it counts the other way. So the difference covers the issues carrying either field, and opening a figure lists exactly those issues.
The difference is a sum like any other, so its cells add up to its margins and its margins to the corner. Two grids over different fields usually cannot be subtracted cell by cell, because each covers its own issues. Here both totals are over the same issues, so the subtraction holds.
Where an issue lands
Every issue the search returned lands in a cell. Two cases are worth stating, because they are where a naive implementation goes wrong.
An issue with no value in the chosen field. It still has a row, a column and a reason to be on the board. So it lands in its cell and adds nothing to the sum. Dropping it would make the grid disagree with the issue count, with nothing on screen to say why. How many there were is counted, per cell, and that is what the No value view draws.
An issue that belongs to more than one group. Labels and components are multi-valued: an issue with three labels genuinely belongs in three rows. Every cell it belongs to counts it. That is the only honest thing a cell can do.
An issue whose axis field is empty is drawn under None. That is a row, not an omission. An issue with no component is still an issue the filter returned.
A sprint is the exception, and it is deliberate. The field carries every sprint an issue has ever been in. The rule above would put a carried ticket in each of them. But a closed sprint is a fact about where the work was, not where it is. Measured on a real board, a filter of nine open and future sprints drew 41 rows. Of those, 32 were closed sprints the issues had passed through. The totals came to 335 where the issues themselves came to 266.
So a sprint axis draws each issue once, in the sprint it is in now:
- the running one, if it is in one;
- otherwise the future one it is queued in;
- otherwise the last one it was seen in.
The search behind such a figure excludes the sprints that outrank it. JQL has no operator for the sprint an issue is in now.
Showing today’s figures. Each cell now counts the issues carrying no figure.
Issues carrying no Story point estimate by Status and Issue Type, in All work
| To Do | ||||
|---|---|---|---|---|
| Ready for Development | ||||
| In Progress | ||||
| BA in Progress | ||||
| In Review | ||||
| In Testing | ||||
| Ready for QA | ||||
| Done | ||||
| Blocked | ||||
| Canceled | ||||
| Total |
This grid holds 4354 issues of the 4789 this filter returned. 6 epics and 429 sub-tasks were not counted, with 20 in Story point estimate between them.
Each of these carries the table itself: every figure with its headings and totals, and a note of what the grid is of, when it was read and what it left out.
Keep this stores the grid on screen under today’s date, for whoever kept it - these figures, not a fresh read of the same filter. It is how a number quoted at a meeting can be shown again months later.
How this grid was read, and what it leaves out
Read at Nov 2, 2026, 10:31 AM. Read with your permissions, so another reader may see a different total. A deeper fill means a larger figure among the others in this grid, not a larger figure in general: the shading ranks the cells rather than measuring them.
Showing today’s figures. Each cell now counts the issues carrying no figure.
Issues carrying no Story point estimate by Status and Issue Type, in All work
| To Do | |||
|---|---|---|---|
| Ready for Development | |||
| In Progress | |||
| BA in Progress | |||
| In Review | |||
| In Testing | |||
| Ready for QA | |||
| Done | |||
| Blocked | |||
| Canceled | |||
| Total |
Showing the 2 biggest of 3 columns. The rest hold 10% of the total, and their figures are in it.
This grid holds 4354 issues of the 4789 this filter returned. 6 epics and 429 sub-tasks were not counted, with 20 in Story point estimate between them.
Each of these carries the table itself: every figure with its headings and totals, and a note of what the grid is of, when it was read and what it left out.
Keep this stores the grid on screen under today’s date, for whoever kept it - these figures, not a fresh read of the same filter. It is how a number quoted at a meeting can be shown again months later.
How this grid was read, and what it leaves out
Read at Nov 2, 2026, 10:31 AM. Read with your permissions, so another reader may see a different total. A deeper fill means a larger figure among the others in this grid, not a larger figure in general: the shading ranks the cells rather than measuring them.
Showing today’s figures. Each cell now counts the issues carrying no figure.
Issues carrying no Story point estimate by Status and Issue Type, in All work
| To Do | ||
|---|---|---|
| Ready for Development | ||
| In Progress | ||
| BA in Progress | ||
| In Review | ||
| In Testing | ||
| Ready for QA | ||
| Done | ||
| Blocked | ||
| Canceled | ||
| Total |
Showing the biggest of 3 columns. The rest hold 36% of the total, and their figures are in it.
This grid holds 4354 issues of the 4789 this filter returned. 6 epics and 429 sub-tasks were not counted, with 20 in Story point estimate between them.
Each of these carries the table itself: every figure with its headings and totals, and a note of what the grid is of, when it was read and what it left out.
Keep this stores the grid on screen under today’s date, for whoever kept it - these figures, not a fresh read of the same filter. It is how a number quoted at a meeting can be shown again months later.
How this grid was read, and what it leaves out
Read at Nov 2, 2026, 10:31 AM. Read with your permissions, so another reader may see a different total. A deeper fill means a larger figure among the others in this grid, not a larger figure in general: the shading ranks the cells rather than measuring them.
Drawn by the gadget itself, on an invented board. The figures are counted by the product rather than typed here; the controls are not live on this page.
Margins above the grand total
This follows from the second case above. It is the one place where the promise in the tagline has a limit that has to be said out loud.
When an issue sits in three rows, each of those three rows counts it. The row totals therefore add up to more than the number of issues, and so does what they are sums of. The grid does not hide that by picking one group for the issue, or by reporting the sum of the margins as the grand total. It holds both numbers:
| Number | What it is |
|---|---|
| Margin total | What the row totals come to, and what the column totals come to. They agree with each other and with the cells |
| Grand total | The same issues counted once each |
| Spread | How far apart the two are, and how many issues did it |
On a single-valued axis the two are the same number, and the grid says it reconciles. On a multi-valued one they are not, and the grid says that instead, with the size of the gap. Two points over a grand total of nine hundred is a footnote. Two hundred over is the grid saying something other than what the reader thinks it says.
Everything drawn adds up to what is beside it either way. That part is not conditional. A cell, its row total, its column total and the margin they belong to are one arithmetic. The suite transposes its fixtures to check it. The bug that broke it was invisible for six tickets, while every multi-valued fixture happened to put that field down the side.
Showing today’s figures. Each cell now holds a total.
Story point estimate by Labels and Issue Type, in All work
| api | ||||
|---|---|---|---|---|
| ui | ||||
| payments | ||||
| infra | ||||
| onboarding | ||||
| reporting | ||||
| None | ||||
| Total |
The smaller figure beside each total is the number of issues it adds up.
This grid holds 346 issues of the 380 this filter returned. Their Story point estimate total is 959. 34 sub-tasks were not counted, and carry no Story point estimate anyway. 6 issues belong to more than one group, so the totals in the table come to 972.5 while these 346 issues come to 959 between them.
Each of these carries the table itself: every figure with its headings and totals, and a note of what the grid is of, when it was read and what it left out.
Keep this stores the grid on screen under today’s date, for whoever kept it - these figures, not a fresh read of the same filter. It is how a number quoted at a meeting can be shown again months later.
How this grid was read, and what it leaves out
Read at Nov 2, 2026, 10:31 AM. Read with your permissions, so another reader may see a different total. A deeper fill means a larger figure among the others in this grid, not a larger figure in general: the shading ranks the cells rather than measuring them. None holds the issues with nothing in that axis’s field. The corner total covers only the 219 issues that carry Story point estimate. A grid of another field covers other issues, so subtracting one of these totals from the other does not give the difference between them.
Drawn by the gadget itself, on an invented board. The figures are counted by the product rather than typed here; the controls are not live on this page.
Which levels are counted
Jira stacks issues in three levels: sub-tasks below, standard issues in the middle, epics above. An estimate can sit at any of them, and the same work can be estimated at two.
Only the standard level is counted unless you say otherwise. Measured on a real board of 4789 issues, one epic was still open while all 31 of its children were Done. It carried 61 points, exactly what its children carried between them. The grid drew those 61 in To Do, because an epic's status describes the epic and not the work under it. On the open part of that board, that was 61 points of 214 in the wrong column. Its 427 sub-tasks were the mirror image. None carried an estimate, so they added two empty rows and nothing else.
Also count: Epics · Sub-tasks turns either back on, one at a time, for a team that estimates elsewhere. What is left out is counted rather than dropped in silence, and the count is on screen.
What was in the sprint at the start, and what arrived after it
Sprint scope is an axis of three groups:
- what was in the sprint when it started;
- what was put in afterwards;
- what the record does not say.
It is not a field: no issue carries it. It is read out of each issue's own history, against the sprint it is in now. That is the same sprint the sprint axis draws it under. So a sprint that passed unfinished work on to the next shows less here than in Crosstab Sprints, which counts an issue under every sprint it was in.
The boundary is the sprint's start date, and that is a choice with a cost. It is the only moment Jira Cloud offers. The moment a sprint was actually set running is not on offer, though Jira Data Center records it. Where the two differ, the answer differs with them.
What Jira Cloud hands over about a sprint
The sprint on an issue carries id, name, state, boardId, startDate and endDate, and a closed one also completeDate, the moment it was closed. The sprint endpoint behind it adds only createdDate. The moment of activation is in neither.
Measured across ten closed sprints of a public board, 840 issues: 63% of the add events fall after the start date, and 51% after activation. One sprint alone read 26 of 30 issues as added against the first, and 3 of 30 against the second.
Three groups, because two get one case backwards. A sprint set on the creation screen never enters the changelog. So an issue raised inside a running sprint has no history to read. Counted as "it was there at the start", the clearest case of added work would land under the opposite heading. Those issues are read from the creation date instead. What is left is the third group:
- an issue whose history was too long to be handed over whole;
- an issue in a sprint nobody has started, where there is no start to be either side of.
A sprint that was empty when it started says so. A team may open the sprint, start it and fill it two days later. Every issue in it is then added after the start. That is what happened, not a fault in the count. Measured on a real sprint: started on the 5th, filled in one move on the 9th, 69 issues, all of them added. The grid names the two dates rather than moving the issues into a quieter column.
These are the only figures in this product that do not open. Jira rejects Sprint CHANGED, Sprint WAS and Sprint CHANGED TO outright. On the same site, status CHANGED AFTER is accepted and answers. So the limit is the sprint field rather than the history, and there is no query to put behind any of the three groups. Every other axis here opens the issues behind every cell. This one says that it cannot.
Leaving out finished work
A board is cumulative: everything a team ever completed stays in it, and Done never empties. Measured on a real one, 6740 of 6893 story points sat in that single column, 97.8%. The other ten columns were slivers beside it.
Leave out work that is finished puts statusCategory != Done into the search itself, so the finished issues are never read. What counts as finished is the status category, not the status name. The category is Jira's own answer, and comes down on every issue. A site can call its last column anything, and names are no guide to which end of the process they are.
Because those issues are not read, the grid cannot count what it left out. It asks Jira instead. This is the one figure in the whole gadget that is not counted from the issues themselves:
Jira answers that question with a count it calls approximate, and does not promise it is caught up with the last few minutes.
The grid says so where it prints the number.
Everything else on screen is counted from issues this app read, with two exceptions.
The first is a Crosstab Total that counts issues, with no field to add up. It asks Jira the same question for its figure, instead of reading every issue to find out how many there are. It also asks for each level of the hierarchy it leaves out, so the sentence about epics and sub-tasks not counted is still said. On a board of twenty thousand issues, that is three or four requests in place of some twenty thousand points of the app's hourly pool. The figure is never cut short.
The second is a grid that counts issues, with no field to add up. Each of its two axes must take one value per issue from a list known before anything is asked:
- status category, status, priority, resolution, issue type or board column;
- a date cut at a grain the reader chose.
Each cell is asked of Jira with the same search a click on it opens. So is each row, each column and the whole.
Where the values come from, and when the grid is read instead
The priorities and the board's columns are Jira's own lists; every other axis takes its values from the last grid this reader kept of the same settings.
Counting is done only where both of these hold:
- every one of those requests together comes to under a third of the issues a read would take;
- the answers add up: each row's cells to that row's own count, each column's to its own, and the rows and columns each to the whole.
A value nobody listed, such as a status added since the grid was kept, is issues in the whole and in no row. The grid is then read instead.
Labels, components, versions, sprints, people and custom fields are always read. An issue can carry several of them, or their values are not a list anybody holds.
The option is off by default. Counting everything the filter returned is the true answer to "what is on this board". This product does not quietly discard what a filter gave it. The option is the way to say otherwise.
Fields held in seconds
Six Jira fields are lengths of time. Jira stores them as a number of seconds and displays them the way an administrator configured: 3d 1h 30m, or 3.19d, or 25.5h.
The same typed estimate is a different figure on different sites. A day is workingHoursPerDay long, and that is a setting. So 3d is 86400 seconds on a 24-hour day and 27000 on a 7.5-hour one. The grid reads the site's own setting and writes the figure the way the site writes it. It does not divide by 3600 and print hours. That would answer a question the site has already answered, in a unit the reader sees nowhere else in Jira.
It also avoids rounding. An hour has a factor of nine in it, so twenty minutes has no finite decimal in hours. A row of cells could then come to a little less than the total beside it. Whole minutes are all Jira stores, and 1d 20m is exact.
A site with time tracking switched off has no answer to give. There the grid draws hours. That is this gadget's own convention rather than a claim about the site.
Time between two dates does not use the working day. It is calendar time. An issue resolved 24 hours after it was created took a day, nights and weekends included, and in a working day of eight hours it would read 3d. A duration is written in the site's form with a day of 24 hours and a week of 7 days, and a sentence under the table says so. Rich Filters and Jira's own Control chart count lead time in calendar days too. Estimates and Time Spent keep the site's working day. So does a metric that takes a duration where an issue has one and one of them where it does not, because its figures have no single length of day. An exported workbook says calendar days where it would otherwise name the working day.
The width of a dashboard column is the other exception, and the common one. The site's own form is half as wide again as the same figure in hours. A gadget in a two- or three-column layout gets 346 pixels. Where that form will not fit, the grid writes hours and says so under the table. The same sentence says a wider gadget draws it the way the site does. For time between two dates it says instead that a wider gadget writes them in calendar days and weeks. So a reader on an ordinary dashboard sees hours. The paragraph above describes what the gadget does when it has the room.
The chart follows the table rather than deciding for itself. Hours on the chart alone would put two figures in one frame. At 696 pixels, one cell read 17w 2d 3h 55m in the table and 699.92h in the tooltip of the bar drawn from it. The width is meant to change how a figure is shown, not what it says.
The width decides only until somebody decides instead. The settings offer the site's form at every width, or hours at every width, beside the answer that lets the window choose. A gadget that has never been asked keeps letting the window choose. The question is asked only on a site that writes a duration out in full. Jira's other two forms are already as narrow as hours, so the choice would be between two words.
What those fields count is a lifetime, not a period, and that is the one thing to know before quoting a figure from them. Time Spent is everything ever logged against an issue, whenever it was logged. A grid of it answers how much has gone into this work altogether. It does not answer how much went in during a month or a sprint. No filter narrowing the issues will make it, because the narrowing picks which issues are counted and not which worklogs.
A grid built for the second question looks exactly like a grid built for the first, and reconciles with itself. It is wrong by however much was logged outside the period. So the safe reading of a time total here is "into these issues, ever". The same is true of Original estimate, which is what somebody expected at some point rather than the current plan.
The second question has a metric of its own, Time logged in a period. It reads each issue's worklogs and adds up the ones started inside the month. The month is cut at midnight in the reader's Jira time zone, where Jira cuts startOfMonth() for the same reader. The search is narrowed by worklogDate to the same month, so the issues it finds and the worklogs added up for them agree. Jira's search carries at most twenty worklogs an issue. Where an issue has more, its worklogs for the month are asked for one issue at a time, five at once, and an issue whose list could not be read is counted in a sentence under the grid. Last month and this month stay relative in a saved setup. The search behind a figure, and the one in an exported file, name the dates the figure was added up over.
The grid says this too, because a colleague reading the figure off a dashboard never opens this page. Where the metric is one of Jira's six time fields, a sentence in the first storey under the table says it. The figures belong to the issue rather than to any period an axis or a filter names. The sentence is not said for a duration between two dates. That is a stretch of time measured on purpose, and the one metric here the sentence would be false about.
Percentages that close
The % of row view divides each cell by its row total. Three things about it are worth knowing.
The margin at the end of the row holds what those shares are of, in the field's own quantity, rather than the hundred per cent they come to. A column of identical hundreds states that the arithmetic closed, which the reader can see. It never states what it closed on. A share such as 93.2% is of a figure that was on the screen in the view beside this one, and nowhere in this one. The sentence under the table says which margin it is, because both are headed Total. The two text exports say it again. They write bare numbers, so a percentage and a quantity arrive in one table with nothing to tell them apart.
Each share is rounded on its own. Half up, from the exact share. So 17 of 75 is written 22.7%, and any cell divided by hand comes out the figure on the screen. A row of them can therefore come to a little either side of a hundred. For example, 68.75% and 31.25% are written 68.8% and 31.3%, which is 100.1, and the sentence under the table says so. Rounding a row as a whole to close on exactly a hundred would mean writing some cell against its own digits. A figure a reader checks and finds wrong costs more than a row that does not close.
A row draws as many decimals as its smallest share needs to exist at all, up to three. With fewer, a share smaller than half a tenth of a per cent rounds to 0% before any reader sees it. Measured on the reference board, that drew 11 figures of 38 as 0%, and five of them carried work. Nothing told them apart from a cell where nobody had estimated anything.
Two rows get no shares at all, and say so rather than drawing zeros:
- a row whose total is nothing, which has no distribution to show;
- a row holding both positive and negative values. There
+10and-4against a total of+6are 167% and -67%, which are not shares of anything a reader can point at.
An all-negative row keeps its shares. They are shares of a deficit, as much a distribution as any other row.
Axes with too many values
An axis draws at most a hundred groups. Past that, the rest are pooled into Everything else. They are pooled rather than dropped, which is the point. What is drawn still adds up to what is beside it. The grand total is still the number somebody can check against Jira's own issue count.
Which hundred is decided by how many issues each value holds, not by which Jira returned first. First seen would be cheaper, and arbitrary: the hundred would move between two loads of the same dashboard.
None is never pooled. It is not a value of the field at all: it is the issues that have none. Weighed with the rest, it disappeared into the pool on an axis of a hundred and fifty labels. That took a hundred points of unlabelled work into a group whose cells do not open.
How many values were pooled is on screen.
Everything else does not compare. It holds whichever groups an axis had least of on the day it was read. So the same heading stands for a different set of groups at each moment. It carries no difference, and neither does any cell under it.
In the three views whose margins add up what is drawn, the totals beside those blanks are short by whatever the pool held. For example, a corner can read −10 000 where the step between the two moments was −10 060. Two views work their margins out from the two grids instead: an average and a share. There the opposite holds, and the pool is inside them. Both are said under the table and on the file's About sheet, in those words.
An axis that pooled on one of the two moments and not the other is the same fact, and reads worse. The groups that went into the pool are not named on the other grid either. So nothing is compared, and the corner can read zero over a board that moved.
How a read ends
A dashboard filter can hold tens of thousands of issues. The resolver this runs in has twenty-five seconds. Every request is drawn against a quota this app shares across every site it is installed on.
| Limit | Value | Why |
|---|---|---|
| The resolver's time | 25 seconds | The platform's |
| One read's clock | 15 seconds | Leaves the other ten for the requests after it and for the answer itself |
| One read, on an ordinary site | about 3100 issues | Fifteen seconds at 475 ms for a page of a hundred: 31 pages |
| Pages in one read | 240 | A backstop for a site whose pages come back short |
| One grid, across sittings | 20,000 issues | A product decision: at 20,200 points, nearly a third of the app's hourly pool |
| The app's hourly pool | 65,000 points | Jira's, stated in a header, for this app across every site it is installed on |
| Gadgets opened on one site | 13,000 points in any UTC hour | A fifth of the pool, so that no few sites leave every other without an hour |
| Schedules on one site | 6,500 points in any UTC hour | A tenth of the pool: nobody waits on a schedule, so it gives way to the people who do |
| One scheduled read | 40 seconds, 5,000 issues | 40 seconds fit fifty pages and one slow one; 5,000 issues, 5,050 points, fit a site's 6,500 for schedules with room to spare |
The five reasons
A read stops for one of five reasons, and only the first is "there was nothing left":
- the filter was exhausted;
- twenty thousand issues were read for one grid, across however many sittings. That is a product decision rather than a platform one: at the measured price below, a grid that size spends nearly a third of the app's hourly pool;
- the page budget ran out;
- the clock ran out, leaving the resolver room to answer at all. On an ordinary site that is about 3100 issues, and it is the reason most reads stop;
- this site's gadgets had spent their share of the hour, so the read stopped at its next page. The stop lifts at the top of the next UTC hour, and the grid says when.
Where 3100 comes from
It is the number this page is most likely to be quoted on, and it is not a constant. The read stops at fifteen of the resolver's twenty-five seconds. That leaves the other ten for the requests after it and for the answer itself. The figure is that fifteen-second budget divided by what one page of a hundred issues costs: 475 ms. That leaves room for 31 pages, and 31 pages is 3100 issues.
How the 475 ms holds up
The 475 was one run of ten pages. It was re-measured later across 180 pages. Their median was 373 ms and their mean 466, one page having taken 15.1 seconds on its own. So the figure sits almost exactly on the mean, by luck rather than by method. It is kept, and the reason it is right is not the reason it was written. A budget has to hold across every page of a read, not across the typical one. So the statistic that decides how many pages fit is the mean, with the tail in it.
It is not a measurement of the thing it describes. Every one of those 180 pages was fetched from a laptop over the public internet. The resolver does not run there. It runs inside Atlassian's infrastructure, next to the Jira it is asking. Two reads timed from inside a resolver on 22 September, on a development site of about a thousand issues, put a page at a mean of 344 ms. The figure above is kept because it is the more cautious of the two, and two reads of one small site are not your site.
So the reach is arithmetic on measurements rather than a promise. It is an estimate of your site rather than a property of it. A slower site reaches fewer, and a faster one meets the ceiling of twenty thousand instead. Neither needs anything in the app to change. The gadget does not guess. It says which of the five stopped a read, every time, on the grid that read produced.
Finishing a read
A read the clock, the page budget or the site's share cut short is not the end of it. Finish this read beside the caption reads on from where it stopped. It adds what it finds to the figures already on screen, and stops again if there is still more. So a filter of five or eight thousand issues is finished in two or three sittings, and one of fifteen thousand in five, rather than narrowed. The twenty-thousand ceiling holds across all of them. Every sitting has to begin within an hour of the first, because past that the board may have changed under it. A later Finish this read says the read was too old to add to and reads it again from the first page. So a read the site's share stopped can go on at the top of the next UTC hour, if that is less than an hour after its first sitting.
Jira's hourly pool
A read can also end because Jira refuses the request outright. That is not this app's limit but the quota named above, which is worth a number rather than a phrase.
65,000 points an hour, for this app across every site it is installed on. Jira states it to this app on every request that succeeds, in a header the gadget reads back: ratelimit-policy: "global-app-quota";q=65000;w=3600. That is a pool of 65,000 over a window of 3,600 seconds, with no site named in it. A separate per-second burst policy comes alongside it, and is not this. When the pool runs out, Jira answers 429 and refuses everything until the hour turns, with no tapering in between.
What a read costs
What one read spends out of that pool was measured on 30 September 2026. A search is charged one point for the request and one for every issue it hands back. That holds although every read this gadget makes is a POST, and Atlassian's published model charges write requests only the base cost. A count of the issues a search holds is two points. The field list is one point for the ninety fields the development site has, the only size measured.
How the price was read
The header above reports the points left only once about four fifths of the pool is gone. So it was read by spending that much on purpose, on the development site, before the app had a single installation to share the pool with.
So a search of about three thousand issues costs 3,131 points and one at the twenty-thousand ceiling 20,200. That is a point for each page of a hundred issues and one for every issue: 31 pages for the first, 200 for the second. The app gets some twenty of the first an hour or three of the second. Those are the app's own across every site it is installed on, not your site's.
One site's share
The gadgets people open on one site spend at most 13,000 of it in any UTC hour. That is a fifth, counted in app storage at the same prices. The schedules' tenth below is apart from it, so one site spends at most three tenths. It is a ceiling against a few sites leaving every other site without an hour, not a budget a site is meant to meet. A load that reads as far as its clock allows costs about 3,150 points, so the ceiling is four such loads from one site inside one hour. What that comes to for a site of your own size is worked through on getting started.
A grid nine people open is nine reads. Each person reads with their own permissions, so no read is shared between them. The same signed-in person reloading the same grid within five minutes reads nothing, unless that read could not be held; the privacy page says when. Two standups in one hour, ten people each, opening one 500-issue grid: 20 reads, about 10,100 points, inside the share. A third standup in the same hour goes past it.
Once a site has spent it, a gadget asks Jira nothing more until the hour turns. It says that the limit is this app's rather than Jira's, and when it lifts. A read under way stops at its next page and says the same.
Two more things count against the same share:
- A press of Publish, which reads the whole filter again.
- The settings form, a few points for each question it asks Jira. Once the share is spent, the form says so and when it lifts. A search it could not check is stored as written.
What is answered from app storage asks Jira nothing, and opens even once the share is spent: a grid or the sprints held for five minutes, and a kept grid. A published grid asks only the name of whoever published it. Once the share is spent, it opens without the name.
Answers set aside 500 points of the share at a time in app storage before they read on, and see what the others set aside. So a site stops within 500 points of the share for each answer reading at that moment. Twenty side by side can go past it by twenty such portions, not by twenty shares. Near the share, an answer can be told it is spent a little early, while the others' portions are set aside and not yet spent. An answer that asks a few questions and no more sets nothing aside, and is written once, when it ends.
Two things this knowingly leaves open:
- four sites at their ceiling, or four installations under one owner, can spend three tenths each, which is more than the whole pool; three leave a tenth for everybody else;
- an answer that cannot read or write the ledger in app storage reads Jira uncounted, rather than refuse the reader.
Two consequences are worth stating rather than discovering:
- Leaving out finished work spends less of it, because issues that are never read are neither requests nor points. On a cumulative board that is most of them.
- A grid cut short by a
429is the one truncation a reader cannot fix by narrowing their filter. The grid says so in those words, rather than blaming the site.
What this app has measured for itself:
- the header above;
- what each kind of request costs of it;
- the number of requests a render makes: twelve for a grid of 989 issues, three for one of 69, and none at all for reading a grid it kept earlier.
Where every number on this page comes from is recorded with the source, which is not public.
Schedules
A grid kept automatically is read the same way and spends the same pool. It reads the whole grid, as the person who switched the schedule on, once a week, once a month or once a sprint, one run at a time. Nobody waits on it, so its clock is longer than a read in the gadget: forty seconds. That is room for fifty pages at the measured pace, and one of the slow pages the measurement also met. Its ceiling is five thousand issues, a quarter of a reader's, which is 5,050 points.
Nobody is looking at it either, so it is the read that has to be most careful of everybody else's. The schedules on one site spend at most 6,500 points in any UTC hour, a tenth of the whole app's pool. Before a schedule reads, Jira is asked how many issues its grid holds, which is one request. The pages of that many, up to the ceiling, plus a tenth for the calls around them, are set aside out of the hour. A schedule that does not fit waits for the next hour, and is not written down as failed.
A schedule that counts cell by cell
A grid that only counts issues can be answered with one count per cell instead of a read. That holds only where those counts come to fewer than a third of its issues. It sets aside the most counts that could take, never more than a read at the ceiling would. Where Jira does not list an axis's values itself, it counts over the groups of the last kept grid. Where the cells do not add up to the total, the grid is read after all. Its pages are then taken out of the hour once the read is done.
Spreading reads out inside an hour saves nothing. The pool is refilled at the top of every UTC hour rather than a little at a time, so the only wait that helps is one past the hour. The first 429 stops every schedule on the site until the hour turns, or for as long as Jira asked. So does an answer whose RateLimit header carries a remaining count for the app's pool. Jira sends that count only once about four fifths of the pool is gone. A grid Jira cut short is not kept at all. It holds whatever the hour happened to leave, and is kept whole once there is room.
Its read ends for the first four of the five reasons. In place of the fifth, a schedule whose read would not fit in what is left of the schedules' tenth this hour does not start, and waits for the next hour. One cut short by this app's own limits is kept and marked as cut short, as Keep this keeps one. Schedules have one rule a press of Keep does not have: a weekly grid holding under half the issues of the last one kept is not kept, in case the read went wrong. That rule applies only to a read that finished. A read cut short holds fewer because it stopped, and on a board past the ceiling that is every week. A monthly grid is not held to it. One month's work can be half the last one's, as a December can be half a November, and a month skipped is a month's report missing. A monthly grid is never kept again from two counts, below: that is for the weekly schedule only.
Said on the grid
Whichever it was, the grid says the read was cut short. A partial total shown as though it were complete is the failure this product exists to remove. Somebody takes the number to a meeting and it is wrong by an unknown amount, which is worse than no gadget at all.
Showing today’s figures. Each cell now holds a total.
Story point estimate by Status and Issue Type, in All work — a partial read
| To Do | ||||
|---|---|---|---|---|
| Ready for Development | ||||
| In Progress | ||||
| BA in Progress | ||||
| In Review | ||||
| Ready to Merge | 0, Ready to Merge and Story. 1 issue here carries no Story point estimate, and adds nothing to this figure. There is nothing behind this figure to open. | 0, Ready to Merge, every column. 1 issue here carries no Story point estimate, and adds nothing to this figure. There is nothing behind this figure to open. | ||
| In Testing | ||||
| Ready for QA | 0, Ready for QA and Task. 1 issue here carries no Story point estimate, and adds nothing to this figure. There is nothing behind this figure to open. | |||
| Done | ||||
| Blocked | 0, Blocked and Bug. 1 issue here carries no Story point estimate, and adds nothing to this figure. There is nothing behind this figure to open. | |||
| Canceled | ||||
| Total |
The smaller figure beside each total is the number of issues it adds up.
So far this grid holds 11713 issues, totaling 31936. 23 epics and 1164 sub-tasks were not counted, with 81 in Story point estimate between them.
Each of these carries the table itself: every figure with its headings and totals, and a note of what the grid is of, when it was read and what it left out.
Keep this stores the grid on screen under today’s date, for whoever kept it - these figures, not a fresh read of the same filter. It is how a number quoted at a meeting can be shown again months later.
How this grid was read, and what it leaves out
Read at Nov 2, 2026, 10:31 AM. Read with your permissions, so another reader may see a different total. A deeper fill means a larger figure among the others in this grid, not a larger figure in general: the shading ranks the cells rather than measuring them. The corner total covers only the 7072 issues that carry Story point estimate. A grid of another field covers other issues, so subtracting one of these totals from the other does not give the difference between them. An empty cell has no issues in it. A cell showing 0 has issues whose Story point estimate adds up to zero.
Showing today’s figures. Each cell now holds a total.
Story point estimate by Status and Issue Type, in All work — a partial read
| To Do | |||
|---|---|---|---|
| Ready for Development | |||
| In Progress | |||
| BA in Progress | |||
| In Review | |||
| Ready to Merge | 0, Ready to Merge and Story. 1 issue here carries no Story point estimate, and adds nothing to this figure. There is nothing behind this figure to open. | 0, Ready to Merge, every column. 1 issue here carries no Story point estimate, and adds nothing to this figure. There is nothing behind this figure to open. | |
| In Testing | |||
| Ready for QA | |||
| Done | |||
| Blocked | 0, Blocked and Bug. 1 issue here carries no Story point estimate, and adds nothing to this figure. There is nothing behind this figure to open. | ||
| Canceled | |||
| Total |
The smaller figure beside each total is the number of issues it adds up.
Showing the 2 biggest of 3 columns. The rest hold 11% of the total, and their figures are in it.
So far this grid holds 11713 issues, totaling 31936. 23 epics and 1164 sub-tasks were not counted, with 81 in Story point estimate between them.
Each of these carries the table itself: every figure with its headings and totals, and a note of what the grid is of, when it was read and what it left out.
Keep this stores the grid on screen under today’s date, for whoever kept it - these figures, not a fresh read of the same filter. It is how a number quoted at a meeting can be shown again months later.
How this grid was read, and what it leaves out
Read at Nov 2, 2026, 10:31 AM. Read with your permissions, so another reader may see a different total. A deeper fill means a larger figure among the others in this grid, not a larger figure in general: the shading ranks the cells rather than measuring them. The corner total covers only the 7072 issues that carry Story point estimate. A grid of another field covers other issues, so subtracting one of these totals from the other does not give the difference between them. An empty cell has no issues in it. A cell showing 0 has issues whose Story point estimate adds up to zero.
Showing today’s figures. Each cell now holds a total.
Story point estimate by Status and Issue Type, in All work — a partial read
| To Do | ||
|---|---|---|
| Ready for Development | ||
| In Progress | ||
| BA in Progress | ||
| In Review | ||
| Ready to Merge | 0, Ready to Merge and Story. 1 issue here carries no Story point estimate, and adds nothing to this figure. There is nothing behind this figure to open. | 0, Ready to Merge, every column. 1 issue here carries no Story point estimate, and adds nothing to this figure. There is nothing behind this figure to open. |
| In Testing | ||
| Ready for QA | ||
| Done | ||
| Blocked | ||
| Canceled | ||
| Total |
The smaller figure beside each total is the number of issues it adds up.
Showing the biggest of 3 columns. The rest hold 38% of the total, and their figures are in it.
So far this grid holds 11713 issues, totaling 31936. 23 epics and 1164 sub-tasks were not counted, with 81 in Story point estimate between them.
Each of these carries the table itself: every figure with its headings and totals, and a note of what the grid is of, when it was read and what it left out.
Keep this stores the grid on screen under today’s date, for whoever kept it - these figures, not a fresh read of the same filter. It is how a number quoted at a meeting can be shown again months later.
How this grid was read, and what it leaves out
Read at Nov 2, 2026, 10:31 AM. Read with your permissions, so another reader may see a different total. A deeper fill means a larger figure among the others in this grid, not a larger figure in general: the shading ranks the cells rather than measuring them. The corner total covers only the 7072 issues that carry Story point estimate. A grid of another field covers other issues, so subtracting one of these totals from the other does not give the difference between them. An empty cell has no issues in it. A cell showing 0 has issues whose Story point estimate adds up to zero.
Drawn by the gadget itself, on an invented board. The figures are counted by the product rather than typed here; the controls are not live on this page.
Answering from two counts
Jira will say how many issues a search holds for two points, where reading them costs about a point an issue. On a mature board, most of what a read reads has not moved since the last one. So in two places, a grid read to the end is not read again when two counts say nothing in it has moved, and in one of them a grid stopped at the ceiling is not either:
- the search still holds as many issues as the read returned. For a read the ceiling stopped, that is as many as Jira counted in the search at the time;
- none of them was updated after a moment five minutes before the read.
An issue that joined the search was edited to get there, and so was one that changed a figure or moved between groups. One that left changed the count. The five minutes are a wide margin for the time a count takes to see an edit, not a measurement. On the development site, a label added and one removed were counted within two and a half seconds: two edits on a quiet site. Bulk edits were not measured.
The two places:
- A reload after five minutes. The grid a reader was given is answered for five minutes without asking Jira anything. Past them, it is asked about. Where the two counts say it has not moved, it is answered again for another five, still dated by the read it came from. Otherwise it is read. A read the ceiling stopped is held the same way. It has nothing left to finish, and reading it again costs the whole ceiling, in one read on a fast site or over the presses of Finish this read it took on any other. A read of time logged in a month is the exception, and is not held. A read stopped for any other reason is not held, because the next load may stop somewhere else.
- A weekly keep. The grid kept last in the same history must have been kept by the weekly schedule itself and read to the end, and the two counts must say it has not moved. Then it is kept again under today's date, still dated by its read. The schedule sets aside the counts rather than the pages of a read. A grid kept by hand is not used: it is what was on the reader's screen, sent from the browser, not a read the schedule made. Nor is a grid kept when a sprint closed, which holds only that sprint's issues. Where the newest grid in the history is either, the board is read. Where Jira refuses a count because the app's hourly allowance is spent, the keep waits until the allowance returns.
What is checked beside the counts
Each also asks for the filter's own JQL, because a saved filter can be edited under the same id. Where an axis is drawn from the board's columns, it asks for those too, because a status can move to another column without an issue being touched. Either one changed, and the grid is read.
Neither does renaming a field or changing how Jira writes a length of time touch an issue. So the grid is also read where a field it names is now called something else or has gone, and, for a metric in time, where the site's time format or working day and week are no longer what the grid was written in. The weekly keep asks Jira for the field names afresh for this, since no settings form is opened in the background to refresh them.
A grid is never answered this way for:
- a search whose answer moves while no issue does: one that names now, a relative date such as
-1d, or any function, such asopenSprints(),currentUser(),membersOf()and the rest, including ones not listed here; - a search that names watchers, votes, another filter or a list of issues;
- a duration measured up to the moment of the read;
- the sprint scope axis;
- a grid kept when a sprint closes;
- a field whose value on one issue moves when another is edited: the aggregate fields, progress, votes, watches and Rank, whatever custom field id your site gave it.
What the counts cannot see is said rather than fixed:
- One issue leaving and another joining with no edit to either, such as a permission changed, a status moved to another category or an issue archived. That keeps the count and has no edit to find.
- A value renamed, such as a status, a component or a version. That changes a heading without touching an issue.
Both are bounded by the same rule: no grid is answered this way four weeks after the read it came from.
A field renamed is seen. Beside the counts, a grid past its five minutes is checked against the site's description of the fields: the one any of the reader's gadgets asked Jira for in the last hour, not the copy kept for up to a week. An older one is asked for again. A grid that calls a field by a name the description no longer gives it is read again. A press of Read again does that as soon as the grid's five minutes are out; a reload does it once the description is newer than the rename, which is within the hour. Inside the five minutes a grid is held for, the description the reader already has is compared too, without asking Jira. Once the settings form has been opened after a rename, the next render reads the grid again under the new name. It does not wait for the hold to end. A field on an axis or behind the metric that the description no longer carries at all is read again the same way. That is a field moved to the trash, or out of the reader's sight. The read then says the gadget cannot use it, rather than drawing the figure it had. The two dates behind a duration are not compared, by name or by absence.
Totals of old finished work
Most issues on a mature board were finished long ago. Without these totals, a weekly keep and every render would read every one of them again. So each person has, under each setting, the grid's own totals of finished work resolved before the start of the current month, in their own time zone:
- the month before this one, on its own;
- the six before that, a month each;
- then four quarters;
- then whole years.
As months age they are added into their quarter, and quarters into their year, without asking Jira. The next keep or render reads the rest and adds it to what is held. The rest is open work, this month's, and finished work Jira has no resolution date for. The totals are the same ones a read continued across sittings adds to, so the grid is the same arithmetic as one read.
What is held is believed on the two counts of the section above. Only the periods that moved are read again.
How the periods are checked
The month before this one is checked on every read. Everything older is checked under one pair of counts. Where that pair fails, it is halved until the one period that moved is found. Jira is asked at most four counts at once.
Where Jira refuses a count because the app's hourly allowance is spent, nothing is read after it. The gadget shows the same message as for any refused read, and a weekly keep waits until the allowance returns.
The record of finished work has four rules:
- It is built only from a read that reached the end. A read cut short writes nothing.
- The whole board is read again at least every four weeks.
- A record nobody wrote for thirty-five days is not used, and is deleted by the read that finds it.
- A record too large to store is replaced by a mark saying so. Those settings are read whole until the mark lapses.
It is not used where the totals would not add up to the grid of one read:
- an axis of several values per issue past the hundred groups it draws, where which values are pooled depends on what was read together;
- a date axis whose grain nobody chose.
Both are found after a read, and those settings are then read whole. A keep reads them whole at once. A render shows what it read and holds none of it for five minutes. The next render reads them whole.
A median is no reason to read whole. These totals hold no values, so a grid that uses them offers no Median, and says why. Nor are the totals used:
- where finished work is left out;
- where no grid is answered from counts;
- for a grid Jira may count cell by cell or counts whole, which is counted rather than read.
A render keeps these totals too: your own, never a schedule owner's, because your search may return what theirs does not. The first time you open a grid it is read whole. After that, old finished work is read again only where Jira says some of it changed. So a large board opens with less of Jira's hourly allowance spent. Checking that takes at most half of the read's fifteen seconds, and what it takes comes off the read. Where it would take longer, the grid is read whole.
Totals are kept only where there is enough old finished work to be worth it. Deciding what is still true costs a few requests and a second or so before the read: the filter, the board where an axis needs it, the zone, the counts. It saves a page of a hundred issues, about a third of a second, for each hundred finished issues it does not have to read again. So where a whole read finds fewer than 500 finished issues resolved before this month, five pages, it keeps no totals. It keeps only a mark saying so.
How a mark lapses, and what a continued read adds
Until the mark lapses after thirty-five days, those settings are read whole without asking Jira anything first. The read after that checks again. Settings marked as not adding up, too large to store or naming the Rank are treated the same way. The mark is checked before Jira is asked anything, and the grid is read whole.
After that read, a mark is checked against the filter, the board and the zone the read asked. It is let go of where any of them is another one. A mark of too little work is also let go of where the read returned 500 issues or more beyond the mark's. Either way, the next read asks again.
The first read of settings nobody has a record or a mark for still asks, once, because that read is what writes one. A read stopped early and continued adds the totals once, to its first sitting. The sittings after it read only the rest, and nothing they read is written down. A grid shown again within five minutes, or again after two counts, is the grid of the read it came from. It has the totals in it already.
It has the blind spots of the counts: an issue leaving and another joining with no edit to either, and a field or a value renamed. It has the same bound of four weeks. And it has one of its own. An old issue reopened in the seconds between the counts and the read is counted twice in that one read. The next read finds its period moved and reads it again.
One more costs reading, not figures. A weekly keep looks only at the newest grid in the history. So a grid kept by hand after it costs one week's read of the board.
What the method cannot see
Stated here rather than left for a reader to find.
It cannot tell you whether the estimate is any good. It adds up what the field says. A board where half the numbers were typed in a hurry produces a tidy total of hurried numbers.
It cannot see work that is not in the filter. The population is the one chosen in the form. Every figure is a figure about that population and no other.
It cannot tell two components with the same name apart by name. Components and versions are per-project. So a filter spanning two projects that both have a component called Auth has two different components in it. They are kept apart, and the two headers say so. But they are two columns. A reader expecting one will find their component apparently cut in half until they read the heading.
It cannot order an axis Jira gives no order to. Status and issue type carry their order in the issue itself, and a sprint orders itself by when it ran. Priority is drawn in the order your site gives its priorities, read from Jira rather than guessed from their ids. Where that list cannot be read, the grid says so and draws priorities the way it draws every other axis with no order of its own, such as labels, components and epics: the group holding the most issues first, so the largest are the first you see. The alphabet only settles a tie.
It cannot know what a label means. A total broken down by a label your organisation chose is a total broken down by whatever your organisation meant by it.
When the arithmetic changes
Anything on this page that changes will change here first. The page is built from a document in the app's own repository. The test suite holds its claims against the code. The views, the axis rule, the three settings and the exports are read out of the product rather than typed here. A claim that stops being true fails the build.