On a Monday morning in Lagos, a governance pipeline returned an empty array. Not a timeout. Not a 500. Not a rate-limit rejection dressed up as an outage. A perfectly well-formed JSON object, arriving exactly on schedule, with null sitting precisely where the treasury utilization figure should have been. The dashboard downstream of it rendered that null as a flat line. And a flat line, in every chart library I have ever used, is indistinguishable from stability.
Eleven hours later, a proposal to raise the protocol's borrowing cap passed with 61% quorum. The number that should have constrained that vote had never arrived. Nothing looked broken. The pipeline was green. The dashboard was green. The vote was green. And a decision worth eight figures had been made on a value that did not exist.
I have spent sixteen years watching this industry build consensus engines capable of surviving a hostile nation-state, and data pipelines that cannot survive a column rename. That asymmetry is the subject of this essay. Not the exploit. Not the crash. The blank field.
The Stack Nobody Audits
Every number that reaches a governance forum travels a path, and that path has more hops than most people who vote on it have ever counted.
It begins at a node โ yours, or more likely someone else's. It is read through an RPC provider. It is decoded by an indexer. It is shaped by an ETL job, joined against a reference table, aggregated into a rolling window, cached, and finally rendered into a chart. Then a human being looks at the chart and raises their hand.
Count the hops. I count seven before the human. Each one is a trust boundary, and each one is a place where a value can disappear without anyone raising an error.
The industry has spent a decade obsessing over two of those hops. Consensus at the front โ the part we call "trustless." Custody at the back โ the part we call "self-sovereign." We have an entire profession built around reading Solidity for a reentrancy bug. We audit bridges, we audit upgrade proxies, we audit token vesting cliffs. But the ingestion layer, the transformation layer, the semantic layer โ the machinery that converts chain state into the numbers people actually act on โ is almost entirely ungoverned. There is no auditor for a broken ETL job. Nobody writes a post-mortem for a null.
I learned the shape of this problem before I had language for it. In 2017, during the first ICO wave, I was a junior compliance analyst at a Lagos fintech startup preparing to issue a utility token. While my colleagues chased fundraising metrics, I spent eighteen hours a day reading the vesting schedule in our smart contract. I found an integer overflow โ a boundary condition in the arithmetic that would have let a beneficiary claim more than the schedule intended. I refused to sign off on the whitepaper until it was patched. It cost me the job. Three similar projects were exploited weeks later.
I have told that story before, usually as a story about security. But the more useful reading is that a vesting schedule is a data pipeline. Time goes in, a token amount comes out, and the arithmetic in between is a contract about how a number is allowed to change. An integer overflow is a silent failure in a data pipeline โ the same category of error as a null being read as a zero. The difference is that one has a compiler that catches it, and the other has a dashboard that hides it.
Trust is a protocol, not a promise. That is true of vesting schedules. It is equally true of the numbers that feed a treasury decision. And yet we extend the promise to the pipeline while extending the protocol only to the contract.
There is a historical reason for this asymmetry, and it is worth naming because it explains why the problem is getting worse rather than better. Between 2020 and 2023, the industry migrated its indexing layer from a handful of hosted services to a decentralized network of indexers. The migration was correct in principle โ the hosted services were centralized, and centralization at the data layer is exactly the kind of dependency this industry exists to remove. But the migration was executed the way most migrations are executed: quickly, with a deprecation notice and a deadline, and with an implicit assumption that downstream consumers would update their queries before the switch.
They did not. Thousands of subgraphs went dark. The endpoints stayed alive. The HTTP responses stayed 200. And the dashboards built on top of those endpoints kept rendering the last block height they had ever seen, for months, because the dashboards had no mechanism for noticing that a number had stopped moving. The failure was invisible precisely because it was gradual, and gradual failures are the only kind that survive a bull market.
The Grammar of Absence: Null, Zero, and Missing
Before we can talk about failure, we have to be precise about what "nothing" means, because "nothing" has at least four distinct meanings in a data system, and three of them render identically on a screen.
0 is a measurement. Utilization is zero. Borrows outstanding are zero. Volume is zero. Something was observed, and the observation was a quantity of nothing. This is information.
null is the absence of a measurement. Nobody observed anything. The question was asked and no answer came back. This is also information โ arguably more important information โ but it is information of a different type.
undefined, or a missing key, is a schema violation. The question was never asked in a way the system understood. This is an error, but not necessarily a loud one.
A stale value is a measurement that was true at some point and is now being presented as if it were current. This is not the absence of information. It is the presence of misinformation wearing the costume of information.
A chart library will draw all four of these as the same flat line. That is the entire problem in one sentence.
In Solidity, this ambiguity barely exists. A uint256 cannot be null. Zero is zero, a missing value is a compile error, and a stale value is a value that was written in a previous block. The type system is unforgiving, and that unforgiveness is a feature. But the moment state leaves the chain โ the moment it becomes a JSON response, a CSV export, a Postgres row, a pandas dataframe โ it enters a world where types are suggestions and absence is negotiable.
The null is the most expensive value in crypto, precisely because it costs nothing to produce. A missing number requires no gas, raises no exception, triggers no alert. It simply fails to arrive, and the system downstream proceeds as if the question had been answered with "nothing is happening."
That is how you get a vote on a borrowing cap decided by a blank field. Nobody lied. Nobody hacked anything. The information simply did not show up, and the absence was interpreted as calm.
A Taxonomy of Silent Failure
If we want to govern the gray areas between blocks, we need to name the failure modes. Here are the ones I have encountered most often, ordered roughly by how much damage they cause per unit of visibility.
Schema drift. A field is renamed upstream. totalSupply becomes total_supply, or an API version bumps and the response envelope changes shape. The ETL job that referenced the old name does not throw. In most modern data stacks, a reference to a nonexistent column in a flexible schema either resolves to null or drops the row entirely. Downstream aggregations then compute a sum over a subset of rows and present it as a total. The chart is smooth. The chart is wrong.
Deprecation. An indexer or a hosted subgraph is marked deprecated. It continues to answer queries โ sometimes for months โ and then stops syncing. The endpoint stays alive. The status code stays 200. The data simply freezes at whatever block height the maintainers stopped caring. Consumers who never tracked the deprecation notice now read a snapshot as a live feed.
Partial backfill. A pipeline hits a rate limit, retries with exponential backoff, and โ because the retry logic was written by someone optimizing for uptime rather than completeness โ silently drops the windows it could not fetch. The resulting dataset has holes. Holes look like low activity. In a market where "low activity" is a bearish signal, a rate limit can be mistaken for a sentiment shift.
Reorg mishandling. This is the worst of the family, because it is confidently wrong rather than quietly empty. An indexer that reports events without waiting for finality will surface transfers that later vanish when the chain reorganizes. The row exists. The transaction hash is real. The event never happened. Anyone who has ever built a liquidation bot on a single confirmation will tell you what that costs.
Unit and decimal errors. Wei versus ether. Six decimals versus eighteen. Seconds versus milliseconds. These are not exotic. They are the most common bug in every analytics codebase I have reviewed, and they are dangerous precisely because the numbers they produce are plausible. A treasury balance off by a factor of 10^12 looks like a very large treasury balance, not like an error.
Denominator drift. A ratio is only as good as its denominator, and denominators change meaning silently. "Share of total value locked" computed against a total that includes a new chain, a new double-counted pool, or a new category of asset is not comparable to the same ratio computed a month earlier. Nobody updates the definition. The number moves. The narrative follows the number.
Aggregation-layer loss. An average of averages. A median computed over a filtered set that quietly excluded the outliers that mattered. A percentile computed on a sample that was truncated at the API's pagination limit. Each of these is a mathematically valid operation applied to an invalid population, and none of them raises a flag.
Notice what these have in common. None produces an exception that reaches a human. The pipeline reports success. The dashboard renders. The failure is invisible at the layer where the decision is made, because the layer where the decision is made has been carefully designed to show only the last mile.
The Dashboard as a Promise
I want to say something unkind about dashboards, because I have built them, I have trusted them, and I have been wrong.
A dashboard is not a view of reality. It is a promise about reality, and the promise is made by the designer, not by the data. Every visual choice is an editorial choice. Auto-scaling axes make a two percent move look like a cliff. Gap-filling interpolation draws a line through a period where no data existed, which is a lie told in good faith by a library that assumes continuity. Hiding nulls โ the default in most charting tools โ is a decision to render absence as nothing at all, which is to say, as the absence of a problem.
The more polished the dashboard, the more credible the promise. This is the inverse of the relationship we should want. A hand-written query in a notebook forces you to look at the raw rows; a beautiful interface lets you stop looking. The interface is a compression algorithm for trust, and like every compression algorithm, it discards the parts it thinks you will not miss.
Culture compiles where logic fails. The culture of dashboards is a culture of reassurance. We build them to make complex systems legible to non-engineers โ investors, delegates, regulators, community members โ and in doing so we strip out exactly the metadata that would let those readers detect a failure. The provenance of a number is not a visual property. You cannot see a stale feed. You cannot see a schema drift. You can only see a line, and lines do not have error bars unless someone deliberately gave them error bars, which almost nobody does.
So here is a modest proposal for every governance dashboard in this industry: every number should carry its own timestamp, its own source, and its own confidence. Not in a tooltip. Not in a footnote. On the face of the number. A treasury balance should be rendered as a value, a block height, and a last-updated time, and if the last-updated time is older than the block time of the decision, the number should be struck through. That is a design decision, not a technical one, and it would have prevented the vote I opened this essay with.
Silence in the chain speaks louder than noise. We have simply not built the instruments to hear it.
The RPC Layer: Where Trust Is Rented
There is a hop in the stack that deserves its own section, because it is the one the industry has decided not to think about.
Most "decentralized" applications read their state through a small number of centralized RPC providers. The contract is decentralized. The consensus is decentralized. The node that answers the query is a managed endpoint in a data center in Virginia, operated by a company that can rate-limit you, can log your queries, and can, if it chooses, return a different answer than another provider would.
This is not a conspiracy theory. It is an architectural fact, and the reason it matters here is that the RPC layer is a data pipeline, and pipelines fail silently. A provider that is partially synced will return block heights that lag the head. A provider under load will return a truncated log set. A provider whose archive node is behind will return null for a historical query that would have succeeded last week.
None of these failures announces itself. The response arrives. The status code is 200. The JSON is valid. And the application, which has no way to distinguish "this block has no events" from "this provider has not indexed that block," renders the null as an empty state and moves on.
I have started asking a question in every architecture review I participate in, and the question is this: how many independent RPC providers does this system depend on, and what happens to the number it displays when one of them is wrong? The answer is almost always "one," and the second half of the answer is almost always "we don't know." That is not a decentralization claim. That is a decentralization aesthetic. We have decentralized the thing we can verify and centralized the thing we cannot.
Oracles: The Difference Between Stale and Correct
The oracle problem is usually described as a problem of getting data onto the chain. It is more accurately described as a problem of getting data onto the chain and then telling the truth about how old it is.
Consider the two dominant designs. A push oracle updates when a price deviates beyond a threshold or when a heartbeat interval elapses, whichever comes first. A pull oracle lets the consumer request an update and pay for it on demand. Both are reasonable engineering. Both create a category of number that is neither correct nor incorrect, but stale โ and both leave the interpretation of staleness to the consumer.
Here is the subtlety that eats protocols alive. In a push model, if the price stays within the deviation threshold, no update is published. The on-chain value is therefore, by construction, a value the network has decided is "close enough." The timestamp advances only on updates. A consumer that reads the price and ignores the timestamp is treating a bounded-error estimate as a measurement. In quiet markets โ which is to say, in the markets where nothing appears to be happening โ staleness accumulates. Then a gap opens, the price moves, and every protocol that assumed its oracle was live discovers that it was reading a number from six hours ago.
The failure is not that the oracle was wrong. The failure is that the consumer had no way to distinguish "the price has not moved" from "the oracle has not spoken." Once again, absence and zero render identically. Once again, the blank field is the expensive one.
I would go further. The industry's oracle debates have been framed almost entirely around accuracy when the binding constraint is provenance. Accuracy is a property of the value. Provenance is a property of the pipeline. A price with perfect accuracy and no provenance is a rumor with a decimal point. Vision without verification is just hallucination, and a price feed is a vision of the world that has not been verified by the thing that consumes it.
The fix is not more oracles. The fix is that every consumer should be required to state its assumptions โ maximum acceptable staleness, minimum number of independent sources, behavior on violation โ and that those assumptions should be checkable on-chain rather than documented in a README. A protocol that cannot articulate the freshness it requires has not made a decision about its oracle. It has made a wish.
Proof of Reserves and the Audit That Isn't
The same pathology appears, more expensively, in the audit layer. Proof of reserves is one of the most celebrated data innovations of the last cycle, and it is also one of the most precisely misunderstood.
A Merkle-tree proof of reserves demonstrates that a custodian controls the keys to a set of addresses at a specific block height, and that a given user's balance is included in the set. It is a real cryptographic achievement. It is also, as a solvency statement, close to worthless, because it answers a question nobody was asking.
The question was never "does the exchange control these keys." The question was "does the exchange owe less than it holds." A proof of reserves says nothing about liabilities. It says nothing about whether the addresses in the tree were borrowed from a counterparty for the duration of the snapshot. It says nothing about whether the tree's timestamp reflects the moment the auditor looked or the moment the exchange chose to be looked at. And it says nothing about the off-chain claims that constitute most of a large institution's balance sheet.
Here is the data-integrity reading: proof of reserves is a data contract that specifies the wrong schema. It is a pipeline that answers a precisely defined question with a rigorous proof, and the question is a proxy for the one that matters. The user verifies inclusion, feels reassured, and never learns that inclusion is not the same as solvency. This is the most expensive version of the null problem: not an absent answer, but a present answer to a different question, delivered with the full authority of cryptography.
The Fiction of Utilization
I want to apply this lens to something more concrete, because data integrity is easy to discuss in the abstract and hard to see in a lending market.
Consider the interest rate models used by the largest lending protocols. The canonical design is a piecewise curve: a base rate, a slope up to an optimal utilization point, and a much steeper slope beyond it. The parameters are chosen by governance. The curve is smooth, monotonic, and aesthetically pleasing, and it is presented as a market mechanism.
It is not a market mechanism. It is a policy. The interest rate is not discovered by the interaction of borrowers and lenders; it is computed by a function whose constants were selected by a vote. There is nothing wrong with policy โ every central bank on earth runs one โ but there is something wrong with calling it a market, because the naming conceals where the arbitrariness lives.
Now add the data problem. The curve's input is utilization: total borrows divided by total supply. Both quantities are read from the protocol's own state, which is on-chain and therefore relatively trustworthy. But "utilization" as an economic concept is not the same as the on-chain ratio. It ignores the composition of suppliers โ how much is recursive leverage, how much is a single whale, how much is a token that cannot be withdrawn because it is being used as collateral elsewhere. It ignores the fact that a large fraction of deposits in any major market are themselves borrowed from another market in a loop. It ignores the difference between liquidity that exists and liquidity that is available.
The on-chain ratio is a measurement. The economic utilization is an interpretation. When a governance proposal adjusts the optimal utilization point from eighty percent to eighty-five, it is adjusting a curve fitted to an interpretation, using parameters chosen by a vote, applied to a ratio that is itself a simplification. That is three layers of abstraction between the number and the reality it claims to describe, and at no layer does anyone check whether the abstraction still holds.
This is where I part company with the way these protocols are usually defended. The defense is that the parameters are transparent and governable. Transparency is not the same as correctness. A parameter can be publicly visible and still arbitrary. The question is not "can I see the constant?" but "what evidence would change the constant?" For most lending markets, the honest answer is: almost nothing. The constants persist because they work well enough in the regimes that have been tested, and because no one has a compelling framework for replacing them. That is not a market. It is an inherited calibration wearing a market's clothes.
And here is where the data pipeline re-enters. If the curve is a policy, it should be evaluated like a policy โ against outcomes, with error bars, with a feedback loop. That requires historical utilization data that is complete, consistent, and comparable across versions. Which requires an ETL pipeline. Which nobody audits. The parameters of a nine-figure lending market are tuned by people reading a dashboard that someone else wrote, and if that dashboard silently dropped three weeks of data during a migration, the tuning was done on a hole.
The Fragmentation Ledger
The same pathology scales up when we look at Layer 2.
The current count of production rollups and validiums is, depending on how you count, somewhere between forty and seventy. Each of them has a dashboard. Each dashboard reports activity: transactions, active addresses, value locked, fees. Each of these numbers is computed by a separate team, using a separate indexer, with a separate definition of what counts.

I am not going to relitigate whether this is scaling. I am going to point out something narrower and more damaging: the industry is now making capital allocation decisions on a set of numbers that are not comparable to one another, while presenting them side by side.
"Active addresses" means different things on different chains. One team counts unique senders per day. Another counts unique addresses that touched a contract. A third counts addresses that signed a transaction, including failed ones, including those sent by a bot that fans out from a single funded key. "Total value locked" is worse: some dashboards count bridged assets, some count assets deployed in contracts, some count assets that have been double-counted through a recursive lending loop, and some count the same liquidity twice because it is deposited on two chains via a canonical bridge that mints a representation.
When these numbers are placed on the same chart โ which is what every comparison dashboard does โ the chart is not comparing chains. It is comparing methodologies, and attributing the differences to the chains. The noise is presented as signal, and the signal is used to decide where incentives should flow. Dozens of rollups, each with its own definition of a user, competing for a liquidity base that has not grown proportionally to the number of venues competing for it. The slicing is real. The measurement of the slicing is fiction.
I have watched this happen at close range. In 2021, I worked with a collective of Lagos-based digital artists to launch a community-owned gallery on Ethereum, and I was responsible for distributing governance tokens to five hundred participants. The distribution was small by the standards of the day. It was also, deliberately, not anonymous โ we knew who our participants were, we verified that the distribution was equitable, and we ensured that the people who had contributed to the gallery had voting power reflecting contribution rather than capital. The larger, anonymous projects around us were attacked precisely at the point where they could not see their own membership. Their dashboards said they had fifty thousand holders. Their governance said otherwise.
Tokens are the brush, community is the canvas. A holder count is a data point. A community is a measurement of something else entirely โ participation, retention, the willingness to show up in a governance forum on a Tuesday. We have dashboards for the first and none for the second, and then we wonder why the second keeps failing.
Seven Years of Half-Life
I want to say something about the Lightning Network, because it is the cleanest example in this industry of a system whose failures are structural and whose reporting is optimistic.
Lightning has existed in production form since 2018. It is, by any technical standard, an elegant design: bidirectional payment channels, hash-time-locked contracts, onion routing, a gossip protocol for pathfinding. It solves a real problem, and it has real users.
It has also been, for seven years, roughly at the same place. The reasons are not mysterious. They are routing and liquidity management, and both are data problems before they are anything else.
Routing fails. Published failure rates for payments above a few thousand satoshis have been, depending on the study and the measurement method, somewhere between a tenth and a half of attempts. A payment that fails must be retried, and each retry consumes time and liquidity. The failure is probabilistic, which means it is invisible in aggregate and brutal in the individual case. A user who sends a payment that fails does not see a routing graph. They see a payment that did not work, and they do not come back.
Channel management is worse. A channel has inbound and outbound liquidity, and both must be managed for the channel to be useful. A merchant who receives payments accumulates inbound capacity and depletes outbound. A node operator must rebalance โ by circular self-payments, by submarine swaps, by opening and closing channels at a cost. Every one of these operations is a data-intensive decision about the state of a graph that is only partially observable. The gossip protocol does not tell you the liquidity of a channel. It tells you the channel exists. The difference between "the channel exists" and "the channel can route your payment" is the difference between a null and a zero, and Lightning has never solved it.
The result is a network with a small number of professional operators, a large number of dormant channels, and a user experience that punishes anyone who does not understand liquidity. That is not a scaling failure. It is a data-observability failure with a scaling story attached. Seven years of optimistic dashboards โ node counts, channel counts, capacity denominated in bitcoin โ have reported the size of the graph rather than the health of the graph, which is why the numbers can grow while the usability stays flat.
Building cathedrals in the bear market means building the boring parts: the observability, the rebalancing, the failure reporting. We built the cathedral and forgot the plumbing, and then we measured the cathedral and called it progress.
The Vote That Passed on Nothing
Let me return to the vote, because the vote is where all of this becomes governance rather than engineering.
A DAO proposal is, formally, a function of its inputs. The inputs are the numbers in the forum post: treasury balance, runway, utilization, quorum, delegation concentration. The output is a decision. If the inputs are wrong, the output is not wrong in the sense of being malicious โ it is wrong in the sense of being ungrounded. The governance process worked perfectly. It processed a null.
There are three specific places where this happens, and I have seen all three.
The first is quorum computed on a stale snapshot. Delegation is not static. Tokens move between wallets, delegations are revoked, and voting power changes. A quorum threshold computed against a snapshot taken at the wrong block โ or against a token holder set that has since changed โ can be simultaneously satisfied and unsatisfied depending on which block you ask. The proposal passes or fails based on a data-availability question, not a governance question. This is not a hypothetical edge case. It is the ordinary condition of every DAO that has ever grown past a few hundred holders.
The second is treasury valuation. A DAO treasury is not a number. It is a set of positions, each with its own liquidity profile, and the "balance" is a mark-to-market estimate that depends on a price feed, a decimal convention, and an assumption about how much of a position could actually be sold. In the Winter of Silence โ the 2022 drawdown, when the treasury of the DAO I was coordinating fell by roughly sixty percent โ I spent months watching our own reported balance diverge from our realizable balance. The dashboard said we had runway. The order book said we had a fraction of it. The gap between those two numbers was the gap between a measurement and an interpretation, and nobody had labeled which was which. I had been making decisions on a number I could not trace, and the number had been right often enough to be trusted and wrong often enough to be dangerous.
The third is delegation concentration. Governance dashboards report the top holders. They rarely report the effective voting power after delegation, because delegation is a separate data source that must be joined to the holder set, and the join is where the pipeline breaks. A protocol can look decentralized by holder count and be effectively controlled by three delegates, and the dashboard that would reveal this is the dashboard nobody built.
We govern the gray areas between blocks. That phrase has always meant, for me, the space where the chain ends and the human decision begins โ the space where a state transition has occurred but its meaning has not yet been agreed upon. What I have come to believe is that the gray area is not only philosophical. It is operational. It is the ETL job, the schema, the join key, the snapshot block. The gray area is where the numbers are made, and we have been governing as if the numbers were given.
Data Contracts: The Missing Primitive
I want to end the technical portion of this essay with a constructive claim, because diagnosis without a design is just complaint.
The industry has a primitive for enforcing agreements about state: the smart contract. It has a primitive for enforcing agreements about identity: the signature. It does not have a primitive for enforcing agreements about data, and that is the gap.
Data engineering as a discipline has a concept that maps almost perfectly onto this: the data contract. A data contract is a formal, versioned specification of a dataset โ its schema, its semantics, its freshness guarantees, its ownership, and its breaking-change policy โ enforced at the boundary between producer and consumer. If the producer changes a field name, the contract fails loudly. If the producer stops updating, the contract's freshness clause fails. If the consumer requests a field that no longer exists, the contract rejects the query rather than returning null.
Now port that concept into a blockchain context and add the two things the chain gives you that ordinary data engineering does not: verifiability and incentives.
A data contract in crypto would be an on-chain artifact. It would declare: this dataset has this schema, published by this address, with this update cadence, with this attestation method. The publisher would sign each update โ EIP-712 typed data is sufficient, no exotic cryptography required. The consumer would read the contract before reading the data, and would revert if the contract's freshness clause was violated. And because the whole thing is on-chain, the publisher's reputation would be a public, queryable object rather than a line in a README.
The effect would be that a null could no longer masquerade as a zero. The consumer would not merely receive a value; it would receive a value with a provenance proof and a freshness bound, and it would be structurally incapable of treating absence as calm. The pipeline would stop being a promise and start being a protocol.
I will be honest about the cost. This is not free. Signing every update costs gas or a signature service. Enforcing freshness at read time costs a revert path and a fallback behavior. Publishing a schema means you cannot quietly change it, which is exactly the point and exactly what makes it unpopular with teams that ship fast. The reason data contracts do not exist in crypto is not that they are technically hard. It is that they would slow down the exact behavior that bull markets reward.
Which brings me to the part of the argument I have been holding back.
More Data, Less Knowing
Here is the counter-intuitive claim, and I want to state it plainly because it runs against the entire direction of the industry.
The proliferation of data in crypto has made the industry less informed, not more.
This is not a paradox. It is a consequence of the fact that data has a cost โ not a storage cost, but an epistemic one. Every additional metric is another place where a failure can hide, another pipeline that nobody audits, another chart that manufactures confidence. The number of dashboards in this industry has grown by orders of magnitude since 2020. The number of people who can trace a single number from the node to the chart has not grown at all. The ratio between the two is the measure of our ignorance.
The blind spot is structural. We audit code because code has a compiler and a test suite and a culture of adversarial review. We do not audit pipelines because pipelines have a culture of "it's just data" โ as if data were a neutral substance rather than the thing every decision is made of. The most dangerous actor in a bull market is not the attacker. It is the analyst who is confidently wrong because a join key was renamed.
And bull markets make this worse in a specific way. In a bear market, people have time. They read the forum posts, they check the numbers, they argue about methodology. In a bull market, the velocity of capital compresses the time between information and action to the point where verification is a luxury. The projects that ship the most dashboards win the narrative. The projects that ship the fewest bugs win the decade. These are not the same projects, and the market has no mechanism for telling them apart until the drawdown.
There is a second-order effect that deserves naming. When the number of metrics exceeds the number of people who understand them, metrics stop functioning as evidence and start functioning as rhetoric. A chart becomes an argument, not a