Novo Nordisk, and the number that was true twice
What a reporting layer for Novo Nordisk, built on AstratoFor finance and supply planningProblem one quarter’s sales were up and down at once, depending on a basis no screen showed
A reporting layer for a company whose sales both rose and fell in the same quarter, where the honest answer depends on a basis nobody was showing.
18 min read · 9 min skimmed
Five systems modelled across, because none of them could be touched. Drag one.
A reconstruction. The engagement was real and delivered on Astrato; the company figures are public, the data in the product is fictional, and no outcome is claimed.
Open the semantic layer, drag the five validated systems around, then switch the basis and watch every figure restate itself, including the three of the four that change sign.THE PRODUCT, NOT A PICTURE
Accessibility: The basis cockpit passes axe-core’s WCAG 2.1 AA rules at desk and phone, in both settings, and in the 11 states this file links into. Not yet tried with a screen reader. The statement
Weight on a first visit: 315 KB of script and 13 KB of style, compressed, against budgets of 330 and 15 KB. The build fails if a product passes its budget. React Flow loads only when the Model sheet is opened.
The states around it, each one a link: the warehouse not answering, where nothing is extracted and so no figure is shown, and the withheld group figures above. Each says what is true, names the next step and offers one action.

The cockpit works on a phone, with the matrix as cards and the inspector as a sheet. Open it full screen for the whole cockpit.
Open the cockpit ↗Transcript
- 0:00 The rebuilt basis cockpit, with fictional data, open on reported sales at constant exchange rates.
- 0:03 Switched to adjusted, every figure, the chart and the SQL restate, and the cards whose sign changed say so.
- 0:06 Back to reported.
- 0:07 The bridge walks from one reading to the next, each step named.
- 0:10 Segments, as bars from zero, each labelled at its tip.
- 0:14 Viewed as the US Operations controller, the group figures are withheld with the reason in their place, and the SQL shows the row access policy that limits the rows.
- I owned
- The design of the reporting layer, as lead product designer at Astrato; this file rebuilds it with fictional data
- With
- Astrato’s delivery pods, as their one designer
- Theirs
- The client’s systems and the delivery team’s build; their roles are not part of this reconstruction, so none is claimed here
- Constraints
- Five validated systems that could not be altered and a warehouse billed by the second, so the model had to sit over them, never beside them; and a quarter whose two honest readings pointed opposite ways
- Friction
- One quarter with two honest readings that pointed opposite ways; the screen surfaces the basis instead of choosing one for every reader
Five systems that cannot change, drawn as one
Before the cockpit: the estate end to end from the validated systems to the reader, the gate that no figure may pass without its basis, the targets the rebuild is held to, the evidence under each decision, and the spec that is checked before every release.
Read this plate as text
The estate drawn as five stations on one line: five validated systems that cannot be changed, the FX table that holds the currency basis, the semantic layer v_group_sales where the basis logic lives once, the cockpit, and the reader in finance or supply planning. Between the model and the cockpit sits the basis gate: reported or adjusted, constant or period FX. A return leg says every figure opens to the query that made it.
The gate is the drawing. Reported and adjusted figures on two currency bases produced a quarter that was up 32% and down 4% at the same time, both correctly, and the cockpit’s whole design is that no figure reaches the screen without passing the basis gate and carrying its stamp. Where the basis control sits, what it restates, and how an off-basis tile is marked all follow from where the gate is on this line.
The return leg is the regulated-estate version of trust. A reader in finance had already built the correct logic privately and distrusted anything that could not show its working, so every number opens to the SQL that produced it, under the reader’s own warehouse role.
Read this plate as text
A tree with one root and four branches, all of them design targets rather than measured results. The root is zero figures allowed on the cockpit without a basis stamp. The branches: one act restates the whole screen, every off-basis tile is marked, both segment shapes are kept across the 2025 restructure, and the model shows seven tables read only.
Read this plate as text
Four rows, each running input to finding to decision. The public quarter that was up 32 per cent reported and down 4 per cent adjusted forced the rule that no measure renders without its basis. Five validated systems that cannot change forced modelling across them on the warehouse. The 1 January 2025 segment restructure forced keeping both shapes and drawing the seam. A representative analyst persona, labelled as a pattern rather than an interview, forced the SQL to stay visible at every step.
The spec below holds the rebuilt cockpit to six statements, each written as an acceptance test before the screens were rebuilt, and each verified by a check that runs before every release of this site, named in the right-hand column. It is the only kind of claim this file makes about the product: not that it was adopted, but that it satisfies these sentences, and that something other than my eye confirms it.
NN-01No measure renders without its basis.
Given any sheet, when a basis is chosen from a column header or the control, then the footer states the basis in force and every figure on screen carries it.
The check “a column header sets the basis for the workbook”.THE INTERACTION SUITE, RUN BEFORE EVERY RELEASE OF THIS SITE
NN-02Switching the basis restates the headline, including its sign.
Given the matrix on reported, constant FX, when Adjusted is chosen, then the insight restates from +32.1% to −4.2% and says so.
The checks “insight states +32.1%” and “Adjusted restates the headline to −4.2%”.THE INTERACTION SUITE, RUN BEFORE EVERY RELEASE OF THIS SITE
NN-03The generated SQL recompiles for the basis and for the FX join.
Given the inspector, when the measure basis or the currency basis changes, then the query shows the adjusted measure and the period or base rate join.
The checks “SQL recompiles for the adjusted basis” and “Kroner recompiles the FX join”.THE INTERACTION SUITE, RUN BEFORE EVERY RELEASE OF THIS SITE
NN-04A tile taken off the global basis says so on its face.
Given a tile, when its basis is overridden, then it is marked Off basis where the figure is, not in a panel.
The check “a clicked tile goes off basis and says so”.THE INTERACTION SUITE, RUN BEFORE EVERY RELEASE OF THIS SITE
NN-05The model shows every source, read only, joined once.
Given the Model sheet, when it opens, then seven tables are drawn, the validated ones stamped GxP, with no join label covered or crossed.
The check “the model shows seven tables” and the canvas check over the model.THE INTERACTION SUITE, RUN BEFORE EVERY RELEASE OF THIS SITE · THE CANVAS CHECK, RUN BEFORE EVERY RELEASE OF THIS SITE
NN-06The cockpit works on a phone, in the dark setting as well as the light one.
Given a 390-pixel viewport, when any sheet opens, then four tabs are on screen, nothing scrolls sideways, and the canvas controls take the dark setting.
The checks “novo phone: 4 bottom tabs” and “the canvas controls take the dark setting”.THE INTERACTION SUITE, RUN BEFORE EVERY RELEASE OF THIS SITE
Two brands. One molecule. Two thirds of the company.
Novo Nordisk sells about DKK 309bn a year. Ozempic and Wegovy are DKK 206bn of that, roughly two thirds, and they are the same active molecule, semaglutide, in different presentations for different indications. One API, one supply chain, one patent estate, carrying most of a company that employs around 69,000 people and sells in about 170 countries.
Read this plate as text
Group sales of DKK 309,064m for FY2025, drawn as a single bar. Ozempic is DKK 127,089m of it and Wegovy DKK 79,106m, together DKK 206,195m, or 67 per cent, and both are the same molecule, semaglutide. The remaining DKK 102,869m is every other product, across diabetes care and rare disease. One active ingredient sits behind two thirds of the revenue, and its US exclusivity ends in 2032.
That concentration is the reason this file exists. When one molecule carries two thirds of the revenue, the questions a finance team asks and the questions a supply team asks stop being different questions. "Can we make more" and "what will we book" are the same sentence read from two ends, and they were being answered in two different systems that did not agree.

Sales grew 32%. Sales fell 4%. Both were true.
In the first quarter of 2026 Novo Nordisk reported sales up 32% at constant exchange rates and adjusted sales down 4% at constant exchange rates. Neither figure is wrong and neither is spin. They are the same sales measured on two bases, and the gap between them is a DKK 26.8bn provision reversal with no cash attached to it.
"Which number do I put in the deck?" THE QUESTION THE WHOLE PROJECT IS AN ANSWER TO
Read this plate as text
One quantity, a quarter of sales, read four ways. Reported at constant exchange rates it is up 32 per cent. Reported in kroner it is up about 7 per cent. Adjusted in kroner it is down about 1 per cent. Adjusted at constant exchange rates it is down 4 per cent. Two point up and two point down. The choice is made of two switches, reported against adjusted and kroner against constant currency, and neither switch was visible on the dashboards people were reading. A figure without its basis is not a figure, it is an opinion.
The instinct in a room like that is to pick a default and move on. I argued against it, and the argument is the whole design. A default basis is a silent editorial decision taken by whoever built the dashboard, applied to everyone who reads it, and invisible at the moment it matters most. The company had introduced adjusted measures for 2026 precisely because the reported figures had stopped describing trading. Choosing one on a reader's behalf throws that away.
So the rule the screens enforce is narrow and absolute: no measure renders without the basis it was computed on. The basis is not a filter in a panel somewhere. It sits against the number, in the same visual breath, and it is the one control on the screen that restates everything at once.

Transcript
- 0:00 Reported sales at constant exchange rates: group sales up 32.1%.
- 0:01 Adjusted: group sales turn to minus 4.2%, and the cards whose sign changed say so.
- 0:03 Adjusted, in kroner: minus 1.1%.
- 0:05 Reported, in kroner: plus 7.4%.
- 0:07 Back to constant exchange rates: plus 32.1% again. Every figure, the chart and the SQL restated each time.
Each chart, and what it has to say
A chart is chosen by the relationship it has to show, in the categories of the Financial Times’ Visual Vocabulary. In the rebuild every mark reads at 3:1 against its card or carries its value in print, so no number depends on telling two colours apart.
| Chart | What it has to show | The form, and why |
|---|---|---|
| One measure, every basis | Deviation: four readings of the same quantity either side of zero | Columns from a zero line, signed and coloured by direction; the basis in use solid, the other three quiet, every one with its value printed |
| Group sales growth | Change over time, across a change of definition | Quarterly columns with the segment change drawn as a seam, because a line would join two shapes that do not restate into each other |
| From one reading to the next | Flow: how one figure becomes another, step by step | A bridge, each step named and labelled, so the provision reversal is a bar with a name rather than a gap |
| Segments | Deviation, by segment | Horizontal bars from zero, labelled at their tips |
| Capital projects | Part-to-whole, at magnitude: spent within budget | Bars on one kroner scale, spent solid and what remains outlined; rings would show two schemes at 47% and 67% as comparable when one is three times the other |
You cannot fix the systems. You model across them.
A regulated manufacturer runs on validated systems. Validation means the system was formally proven fit for its purpose and that changing it means revalidating it, so the practical answer to "can we add a field" is usually no, or not this year. The reporting problem has to be solved somewhere else.
Read this plate as text
Five source systems in a row: the ERP holding orders and financials, the manufacturing execution system holding batch records, the laboratory system holding test results, the quality system holding deviations, and a process historian holding sensor readings. Each is validated, meaning it cannot be changed without revalidation. Above them sits a semantic layer that joins across all five and holds the basis logic in one place, so every screen inherits the same definition. Above that, the screens. Everything reads downward and nothing writes back into a validated system.
The second thing the semantic layer had to carry was less obvious and caused more trouble. On 1 January 2025 the company restructured its reporting segments into US Operations and International Operations, replacing the previous North America and International split, with Canada moving across. Any history built against the old shape does not restate cleanly into the new one.
The temptation is to quietly map the old segments onto the new ones and present an unbroken line. That line would be fiction. The model keeps both shapes and the charts draw the seam: before the restructure the series is drawn on the old basis and labelled as such, and the join is a visible discontinuity rather than a smoothed curve. A reader who wants a continuous trend has to ask for a restated one, and gets told what the restatement assumes.

A manufacturer spending a fifth of revenue on concrete
Novo Nordisk spent DKK 60.1bn on property, plant and equipment in 2025, roughly 19% of sales, on API capacity, aseptic production and packaging. At that scale the capital portfolio stops being a finance footnote and becomes an operating system of its own, with its own reporting needs.
Read this plate as text
Two named expansion projects drawn as budget bars with the portion already spent filled in, both on the same scale. Kalundborg in Denmark is budgeted at DKK 49.6bn with DKK 23.1bn spent at the end of 2025, about 47 per cent, due fully operational during 2029. Hillerød is budgeted at DKK 15.9bn with DKK 10.7bn spent, about 67 per cent, due during 2028. Both are multi-year and part spent, so the question is not how much was spent but whether the remaining spend still buys the date.
The fill-and-finish footprint moved from 11 sites to 14 through the 2024 Catalent transaction, adding capacity in Italy, Belgium and Indiana. Three new sites on three regulatory regimes, arriving mid-programme, is the kind of change that quietly breaks a reporting layer: the site dimension grows, the historical series does not, and every chart that was keyed on the old site list silently drops the new ones or silently includes them without saying so.
That is the unglamorous half of this work, and it is most of it. A reporting layer earns trust by being explicit about what changed underneath it, and loses trust the first time a reader finds a total that moved without explanation.

The people who already knew which number was right
The analysts in finance and supply planning were not confused by the basis problem. They had solved it privately, each in their own spreadsheet, and the cost of that was not error so much as duplication and delay.
What a reconstruction can honestly say about research is limited, and I would rather say the limited true thing than a detailed invented one. The pattern across this kind of engagement is consistent and it held here: the people closest to the data had already built the correct logic by hand, and they distrusted any central dashboard that could not show its working. The question they asked of every new screen was not "is this pretty" but "where did this come from, and on what basis".
That is why the SQL stays visible. Astrato Insights generates measures, dimensions and the query that produced them, and the decision I had pushed for on the platform side applies here with more force than anywhere else: the generated SQL is shown and editable at every step, not tucked behind a disclosure after the fact. In a regulated reporting context, a number whose derivation you cannot read is a number you cannot sign.

In the rebuild that position is a setting you can try. View the cockpit as one segment’s controller and the warehouse applies a row access policy before any query sees a row, looking the role up in a mapping table, the mechanism Snowflake documents for exactly this. The segment chart then draws that segment alone, and every group figure, derived across both, is withheld rather than shown without its working, with the reason in its place. Open it as the US Operations controller.
From a validated record to a number someone signs
The path a figure takes, and the two places where a human decision is recorded rather than inferred.
Read this plate as text
Six stages left to right. A validated source system holds the record. It lands in the warehouse unchanged. The semantic layer joins it and applies the basis logic. A screen renders it, always with its basis shown. A reader can open the SQL behind any figure. Finally a person states the basis they are signing on, recorded next to the number. Every query runs on the client's own warehouse under the reader's own role, with nothing extracted and nothing stored. The two marked stages are deliberate friction, and they are where accountability attaches.
Five problems, and the decision taken on each
The design decisions that carried weight, each with the thing that made it necessary.

The same quarter’s sales could be quoted as up 32% or down 4%, and both were correct, because reported and adjusted figures on two currency bases circulated without labels.
No measure renders without its basis. The control is global, sits against the figures rather than in a panel, and restates the whole screen in one act.
The company introduced adjusted measures because the reported ones had stopped describing trading. A dashboard that picks one basis silently throws that distinction away.
An early build let each chart carry its own basis, which produced screens where two adjacent tiles measured different things and looked like a comparison.
Basis went global. A per-chart override still exists, because sometimes you need one, but it visibly marks the tile as off-basis.
Adjacency is an argument. Two tiles side by side assert comparability whether or not the data supports it, and no caption undoes that.
The 1 January 2025 segment restructure meant history did not restate cleanly, and the easy fix was to map old segments onto new ones and draw one smooth line.
The model keeps both shapes and the chart draws the seam. A continuous trend has to be asked for, and arrives with its restatement assumptions stated.
A smoothed line across a definition change is the one chart nobody can audit later, because the discontinuity it hides is exactly what a reviewer would look for.
Capital projects were reported as percentage-complete rings, which made a DKK 49.6bn scheme and a DKK 15.9bn scheme look like comparable progress.
Budget and spend drawn to a common scale, with the operational date on the same row.
Percentage hides magnitude, and magnitude is what the decision turns on. Half of fifty billion and two thirds of sixteen are not the same news.
Going from 11 fill-and-finish sites to 14 mid-programme meant charts keyed on the old site list either dropped the new sites or absorbed them silently.
Dimension changes are first-class events in the model. A series whose membership changed mid-range says so on the chart, at the point where it changed.
A total that moves without explanation is the single fastest way for a reporting layer to lose a reader, and it never gets that reader back.
The honest version of a number is a slower one
| It worked if | Result | Status |
|---|---|---|
| No figure appears without its basis | 0 figures on the cockpit without a basis stamp | |
| One act restates the whole screen | 1 basis change restates every tile, every chart and the generated SQL | |
| An override is never silent | 100% of off-basis tiles marked | |
| Readers adopt it and save time | Not measured, so not claimed |
Every figure in that band is public, taken from Novo Nordisk's own reporting, and none of them is a result of this work. I have not put an adoption number or a time-saved number on this page, because I cannot show you the measurement and a number you cannot check does not belong on a site whose argument is that every number carries its source.
What I will claim is the design position, because it is mine and it is arguable either way. A reporting layer for a business like this one should be slower to assert than the spreadsheets it replaces. The spreadsheets were fast because each analyst had already decided the basis privately. A shared screen cannot make that decision privately on behalf of hundreds of readers, so it has to surface the choice, and surfacing a choice costs a click and a moment of thought. That cost is the product, not a failure of it.
What I would tell another designer taking this on: the instinct to simplify is the enemy here. In a company reporting in one currency and earning in another, through a year with a provision reversal large enough to flip the sign of its own headline, the simplification is the error. The job is not to produce one number. It is to make the four honest ones legible, and to make it impossible to quote one without saying which.

What I would do differently
- Agree the measurement before it ships. This page carries no adoption or time-saved number because I cannot show the measurement. A reporting layer about honest numbers should have shipped with its own.
- Put the click in front of readers early. Surfacing the basis costs every reader a click and a moment of thought. I would have tested that trade with finance and supply planning in the first prototype, not argued it afterwards.
Source notes
- This case file is a reconstruction. The engagement was real and was delivered on Astrato, the Snowflake-native platform described in case file 002. The delivered artefacts, screens, research material and results are covered by confidentiality and are not shown here. What is on this page is a representative account: the problems are real and public, the design decisions are the ones I argue for in this situation, and the screens are rebuilt for this site rather than exported from the work.
- No figure on this page is a measured project outcome. Nothing claims an adoption rate, a time saved or a cost reduced, because that evidence cannot be shown.
- Company figures are from Novo Nordisk's published reporting: FY2025 net sales DKK 309,064m, operating margin 41.3%, Ozempic DKK 127,089m and Wegovy DKK 79,106m (Annual Report 2025 and the FY2025 Form 6-K). Capex on property, plant and equipment DKK 60.1bn in 2025.
- The Q1 2026 contrast between reported sales up 32% at constant exchange rates and adjusted sales down 4% at constant exchange rates, and the DKK 26.8bn reversal of the 340B provision behind it, are from Novo Nordisk's 2026 quarterly reporting. The intermediate kroner readings in FIG. 005 are the same quantity on the other currency basis and are drawn to illustrate the four-way split.
- Kalundborg budgeted ~DKK 49.6bn with DKK 23.1bn spent at 31 December 2025, operational during 2029; Hillerød ~DKK 15.9bn with DKK 10.7bn spent, operational during 2028. From the 2025 annual report's project disclosures.
- The segment restructure into US Operations and International Operations took effect 1 January 2025. The fill-and-finish footprint moved from 11 to 14 sites through the 2024 Catalent transaction.
- The visual identity here is informed by Novo Nordisk's clinical blue, not copied from it. No logo, wordmark or trade dress is reproduced anywhere on this page or in the running product. Novo Nordisk publishes no hex values for its current primary colour.



