Work / Case study

Planetary science · 2026

B.E.A.C.O.N

Same objects. Source values, side by side.

B.E.A.C.O.N

JPL and ESA can both be looking at the same rock and still not print the same numbers. That is ordinary. Independent orbit determination, overlapping but non-identical arcs, different software, different epochs. What is not ordinary is how much work it takes to notice.

Three public systems, no shared desk

Near-Earth object monitoring is not one database. JPL Close Approach Data, JPL Sentry, and ESA NEOCC (Aegis) each fit orbits from the observations they trust. The pages are public. The comparison is not. If you want to know whether 2025 CL3 has the same cumulative impact probability in Pasadena and at the NEO Coordination Centre, you open two sites and you hope you are holding the same designation, the same flyby, the same aggregation window.

I got tired of doing that by hand. B.E.A.C.O.N — Bayesian Earth-impact Assessment & Cross-source Observation Network — retrieves all three feeds, matches records that refer to the same object, and puts the original values on one row. It does not merge them. It does not average them. It does not invent a house risk score and call it science.

A difference is a fact, not a verdict

Independent centres will not, in general, report identical values. Treating every mismatch as an error in one of the institutions is a category mistake. The useful move is to keep each source’s number, say when they diverge past a rule that fits the field, and stop there. If an orbit-determination person wants to argue with the rule, the rule is on a page.

The matching key is a normalised IAU designation. 1979 XB and 1979XB are the same object. Version 0.2.0 had to learn that ESA numbered objects should match on the permanent designation, not on whatever string happened to be in the row. That sounds small. It is the difference between a cross-match and a ghost.

One cutoff would have been lazy

Fields in this domain do not share a scale. Miss distance and relative velocity wander between routine orbit fits; those use a relative tolerance. Close-approach dates are compared as calendar dates, because the sources do not share time granularity. Cumulative impact probability spans many orders of magnitude, so a relative percentage is meaningless: the rule is a ratio, with a floor so two negligible numbers do not scream. On the live instance that ratio is 2×, with a floor of 10⁻⁷. Palermo is already logarithmic; the threshold is an absolute delta of 0.5. Torino is a coarse integer. Any difference is worth showing.

Two counts are published, on purpose. totalFieldDivergences is every flagged field, including distance, speed, and date. significantDivergences is the subset where a risk-bearing field — impact probability, Palermo, or Torino — crossed its line. Both, with the underlying rows, are at /api/debug/divergences. Anyone can check the arithmetic. I would not trust a dashboard that refused to show its work.

The boring reliability work

0.2.0, 4 August 2026, was mostly honesty. JPL CAD and ESA now share a 365-day close-approach window, so coverage is not an artefact of two different horizons. Relative velocity is compared at ESA’s reporting precision of 0.1 km/s; the 1% check runs after JPL is rounded to that precision. Displayed values stay raw. Miss distance and speed only compare when the two dates fall within two calendar days of the same flyby. Wider gaps still raise the date flag and stop. Unequal risk-year windows are shown as context. They do not invent a third kind of risk flag, and they do not suppress the cumulative thresholds.

Cache hits keep the original fetchedAt. A degraded reconcile is not cached. A malformed ESA body is unhealthy, not an empty success. Transient 408, 429, and 5xx are retried with a cap on Retry-After. None of this is glamorous. All of it is the difference between a demo and a feed you can leave open.

What it refuses to be

BEACON does not predict impacts. It does not replace NASA, JPL, or ESA. It does not decide which source is correct. It does not compute a proprietary or aggregate risk score. It is not an operational warning system. The three-dimensional panel is a miss-distance sketch, not a Keplerian propagation. There is no database: each source is fetched, parsed, validated with Zod, and held in memory for fifteen minutes; reconcile for five. On Windows, Node needs the system certificate store to speak to ESA TLS. ESA’s format is not a versioned API. It can change without notice.

The live instance is novabeacon.vercel.app. Filters are all, multi, divergent, and risk. The stack is Next.js 16, React 19, TypeScript, Tailwind 4, Vitest, a little Three.js. Data is published by NASA/JPL CNEOS and the ESA NEO Coordination Centre. BEACON is not affiliated with, or endorsed by, either. If you cite it: NovaCoding (2026). BEACON. v0.2.0. The file is CITATION.cff.

Still open: NEODyS/Clomon2 as a third independent source, a cache that survives the instance, a history of how a value moved. Those are research problems. The comparison layer is the product.

BEACON does not predict impacts, replace NASA/JPL/ESA systems, or compute a proprietary risk score.

Live close approaches

A small slice of public JPL CAD data. The full product compares JPL and ESA values for the same designation.

JPL CAD · next 7 days · dist ≤ 0.05 AU

ObjectClose approachDistance (AU)v_rel (km/s)
2026 PX2026-Aug-23 20:590.006296.76
2026 QN12026-Aug-23 21:270.0111913.14
2214552026-Aug-28 15:470.0239619.00
2026 PP2026-Aug-28 15:210.025176.72

Source values only, from NASA/JPL CNEOS CAD. This is not an alert system and is not affiliated with NASA, JPL, or ESA.