FlightFinder

Aviation Safety Database

Visit Website
August 21, 2026 I merged 124 aviation accident archives, then found 74% of my own severity column says "unknown"

FlightFinder pulls accident and incident records out of the national investigation bodies — NTSB, AAIB, BEA, CENIPA, ATSB, MAK, TSB and about 120 more — and puts them behind a flight number, an aircraft type, an airline. 283K occurrences going back to 1902.

This week I was preparing the corpus for public release and ran coverage stats on my own tables for the first time in months. Three things I had been quietly assuming turned out to be wrong.

  1. "severity is 100% populated" meant nothing. It is non-null on every single row. It is also the literal string "unknown" on 74.4% of them. Fatal is 21.7%, hull loss 3.5%, everything else rounds to noise. Any chart I had drawn treating non-fatal as "not fatal" was really a chart of which authorities bother to classify.

  2. 41.5% of rows had a field filled in by a language model, and I was the one who put it there. We extract structure from narrative prose where the source publishes no structured field. That is fine, and it is why coverage is decent at all. What is not fine is that until this week the flag saying so was an internal column nobody filtered on. It matters most for casualty counts, which is exactly the number people quote.

  3. A column can be worse than empty. manufacturer was populated on 0.4% of rows. Not missing enough to notice, not present enough to use — the worst possible state, because it silently invites a GROUP BY that returns a confident, wrong answer. I dropped it from the export rather than ship it.

The fix in all three cases was the same, and it was not technical: publish the coverage table next to the data, and ship the provenance flag as a first-class column so filtering it is the user's decision instead of my hidden one.

If you run anything data-backed, the cheap version of this is one query per column: count(col) / count(*). Mine took ten minutes and changed what I am willing to claim on my own landing page.

12 Comments

  1. 1

    The manufacturer example is the one that got me. 0.4% populated is exactly the kind of column that can quietly produce a very convincing nonsense chart.

    Feels like FlightFinder could be pulling in a lot more organic traffic than it is right now. Especially with 283K occurrences and that level of provenance detail while you're preparing the public release.

    Have you found any other field where the coverage story completely changed what you thought you had?

    1. 1
      Yeah, that column is why I now gate every aggregate on a minimum coverage before it can render. At 0.4% manufacturer doesn't produce a chart at all in the current build — below the threshold it shows as a labeled gap, not a bar. Same failure mode bit me earlier on a different field: an 8%-populated column was quietly producing "trends" that were pure sampling artifact. Coverage-gating before aggregation was the fix.
  2. 1

    The strongest part is the provenance discipline. Discovering that “populated” didn't mean “usable” turns data quality from a hidden technical issue into a product-level trust problem.

    1. 1
      That's the shift that took me longest to internalize: "populated" and "usable" are different columns. What helped was making provenance visible per record instead of trusting the merged view — anything that can't be traced to a structured source now carries that status rather than silently averaging into a headline number. It did turn a backend hygiene problem into a user-facing trust decision, which is uncomfortable but correct.
      1. 1

        That’s an interesting distinction. I’d be curious to see how users respond to that provenance layer as the product develops.

        1. 1

          Too early for an honest user read — traffic on those pages is small enough that anything I claimed about "how users respond" would be noise. The internal effect I can report: coverage-gating killed several charts outright, and rebuilding them as labeled gaps took longer than the original feature did. The signal I'm actually waiting on is whether anyone clicks through to the source record when a field is marked unverified. If they don't, the provenance layer is just honesty for my own benefit — fine, but not a product.

          1. 1

            That’s a more interesting signal to wait for. The difference between a useful provenance feature and something that’s simply good data hygiene should become clearer once you have that behavior.

            1. 1
              Agreed, and the part I want to get right is picking the threshold before the data arrives - otherwise I'll read whatever number comes back as confirmation. Where I've landed: the provenance layer earns a place in the UI if source-record clicks on unverified fields run meaningfully above the click rate on ordinary outbound references on the same pages. Below that line it's hygiene I keep, not a feature I surface. The trap I'm watching for in myself is using "nobody clicked" as permission to quietly drop the labels. The labels stay either way - what the behaviour decides is whether they get real estate on the page or just live in the data.
              1. 1
                That’s a thoughtful way to frame the test. I’d be interested in continuing the conversation beyond the thread — would you be open to sharing the best email to reach you on?
                1. 1
                  Or denys@himaxym.com, if that is easier. Whatever the question is, the answer will be the same in either place.
                  1. 1
                    Thanks! I’ve just sent it over. Looking forward to hearing your thoughts whenever you have a chance.
                2. 1
                  Happy to keep it here. The thread is the useful part - anyone else building on messy public datasets can read it, which a DM does not give them. If there is a specific question behind it, ask it in the open and I will answer properly.

About

The safety record behind a flight sits in a dozen investigation archives that don't talk to each other. I pulled 283K occurrences from 128 official sources into one lookup, and made every number show its work.