The PDC evaluation chapter recommended against integrating the Pacific Disaster Center’s Hazards API, and set an explicit condition for revisiting that call: the next non-manual cyclone in the feed. At the time there was exactly one cyclone available — Tropical Storm Sinlaku, hand-entered by an analyst after the storm had already dissipated, with no track and zero exposure. Every conclusion rested on that single unrepresentative record.
The 2026 Northern Hemisphere season has now supplied the missing evidence. This chapter re-runs the comparison against an automatically-ingested cyclone and revises the recommendation.
The technical reference remains docs/pdc_api.md. The snapshot behind this chapter is pinned by scripts/cache_pdc_dolphin.py into book/_cache/11-pdc-2026-season/ (tracked in git), because PDC drops storms from its feed as soon as they end.
Probing /hazards?types=CYCLONE on 2026-08-03 returned three cyclones rather than one, and critically, two of them carry category = EVENT — the automatically-ingested flavour that chapter 08 had never observed.
Typhoon Dolphin
Post-Tropical Cyclone Genevieve
Tropical Storm Bavi
category
EVENT
EVENT
RESPONSE
Ingestion
automated
automated
PDC Manual Hazard
issuer
JTWC
NHC
—
sourceRecordId
WP122026
EP072026
internal UUID
Forecast positions
9
7
0
Exposure
1.42M (JPN)
none (offshore)
396.8M (CHN/TWN/JPN)
This settles the first of chapter 08’s eight open questions. Manual entry is not the standard path for cyclones; it is one of two paths. Automated ingestion from official forecast centres exists and is the norm for live storms. Sinlaku was the exception, not the rule, and chapter 08 generalised from it because it had nothing else.
The sourceRecordId for both automated storms is an ATCF identifier — WP122026 is Western Pacific storm 12 of 2026. Chapter 08 listed the absence of any such identifier as the blocker for joining PDC to IBTrACS. It is not absent for automated storms.
7.2 PDC and GDACS ingest the same bulletin
Typhoon Dolphin is also a GDACS event (1001297, DOLPHIN-26). Both systems were on advisory 31 at capture time, which allows an exact like-for-like comparison rather than an approximate one.
Table 7.1
Field
GDACS
PDC
Valid time
2026-08-03 12:00:00
2026-08-03 12:00:00+00:00
Latitude
25.00
25.00
Longitude
145.70
145.70
Max wind (kt)
90
90
34 kt radii NE/SE/SW/NW (nm)
[230, 170, 160, 210]
[230, 170, 160, 210]
50 kt radii NE/SE/SW/NW (nm)
[120, 90, 50, 100]
[120, 90, 50, 100]
64 kt radii NE/SE/SW/NW (nm)
[80, 30, 30, 70]
[80, 30, 30, 70]
Every value matches — position, intensity, and all twelve quadrant wind radii. Neither system is modelling the storm; both are relaying the same JTWC bulletin unaltered.
That is a more useful finding than it first appears. It means any divergence in the exposure numbers below is attributable entirely to the exposure computation, not to differing meteorology. The two systems are a controlled comparison: identical geometry, different population engines.
It also means PDC carries quadrant wind radii at the same 34/50/64 kt thresholds the repository already uses for pop_34kt / pop_64kt. The geometry is directly compatible with existing code, including gdacs.wind_radii_polygon().
7.3 Where they diverge: exposure
Table 7.2
Source
Population
PDC total (Japan)
1,420,000
GDACS 34 kt buffer (Japan)
1,319,839
GDACS 64 kt buffer (Japan)
1,125,265
For Japan the two agree closely: PDC’s 1.42M sits about 8% above GDACS’s 34 kt figure of 1.32M, and comfortably within the range bounded by the 34 kt and 64 kt buffers. Given entirely independent population rasters and swath definitions, that is good agreement.
The disagreement is in which countries appear at all:
Table 7.3
iso3
country
GDACS 34 kt
PDC
CHN
China
30,624,622
—
JPN
Japan
1,319,839
1,420,000
MHL
Marshall Islands
not computed
—
TWN
Taiwan
11,993,417
—
GDACS reports 30.6M exposed in China and 12.0M in Taiwan; PDC reports neither. It is tempting to explain this as a difference in how far ahead each source integrates, but that is wrong: the two forecast tracks are identical, position for position, out to +120 h, including the legs that carry the storm into the East China Sea. Neither source is looking further ahead than the other.
The difference is the footprint drawn around that shared track, and the threshold that defines it.
Forecast leg
34 kt swath reaches west to
64 kt swath reaches west to
+96 h (125.8°E)
121.0°E
124.3°E
+120 h (124.1°E)
119.6°E
122.6°E
Taiwan spans roughly 120–122°E and the Chinese coast 118–122°E. So the 34 kt swath reaches both; the 64 kt swath reaches neither. PDC’s impactGeometry — the polygon its exposure is computed on — has a western edge at 122.8°E, sitting on the 64 kt envelope rather than the 34 kt one.
That is exactly what a damage model should do. GDACS’s 34 kt is a wind criterion; PDC’s is a damage criterion. 34 kt is tropical-storm force, about 63 km/h, which causes essentially no structural damage — PDC’s lowest band is “Minor Damage; power out”. A damage footprint is therefore necessarily tighter than a 34 kt wind swath, and the gap is widest exactly where the storm is weakest and furthest out.
PDC is not unaware of the risk further west: its alertGeometry reaches 115.1°E, well into mainland China. It simply declines to attribute exposure there, separating “area to be alert about” from “area where damage is modelled” and computing population only on the second. The same mechanism explains the 109 people PDC reports for China on advisory 32 — that is the footprint edge clipping the coast, not an error.
The practical consequence is a caution about reading the GDACS figure. “109,834,366 exposed in China” does not mean 109.8M people are about to be harmed; it means if a four-day-out forecast verifies, 109.8M people may experience ≥34 kt winds. Two conditionals the number itself does not carry. When GDACS reports a nine-figure total and PDC reports approximately zero, that divergence is itself the signal — it marks a far-lead, low-threshold artifact rather than an imminent catastrophe, and a monitor showing only the GDACS number gives the reader no way to tell those apart.
Marshall Islands appearing as -1 in GDACS is the documented “not computed” sentinel, covered in chapter 09; it is not a zero.
7.3.1 Damage bands are discrete, not cumulative
Table 7.4
Level
PDC description
Population
1
Minor Damage; power out
17,100
2
Moderate Damage; 5% of value
834,000
3
Widespread Damage and Above
577,000
The three bands sum to 1,428,100 against a reported total of 1,420,000 — equal within PDC’s own rounding. So the bands are discrete, like ADAM’s 60/90/120 km/h bands, rather than cumulative, like GDACS’s pop_34kt / pop_64kt. Chapter 07’s harmonisation logic already handles that conversion.
One caution: PDC labels these bands by expected damage (“Moderate Damage; 5% of value”), not by wind threshold. They are not the 34/50/64 kt rings relabelled — that hypothesis is tested and refuted in Where PDC’s numbers come from below, along with what the bands actually are.
7.3.2 The bands are also split by country
exposureLevels[].data carries its own nested totalByCountry, so exposure is available per (country, band) rather than only as one national number:
Table 7.5
Band
Description
Country
Population
1
Minor Damage; power out
JPN
17,100
2
Moderate Damage; 5% of value
JPN
834,000
3
Widespread Damage and Above
JPN
577,000
That makes PDC’s exposure grain country × damage band — the structural analogue of GDACS’s pop_34kt/pop_64kt and ADAM’s 60/90/120 km/h bands, keyed on expected damage instead of wind speed.
7.3.3 But there is no sub-national breakdown
The detail object has a totalByAdmin array with admin1 and admin2 slots, which reads like a sub-national breakdown. It is not one. Those fields are never populated, and the array duplicates totalByCountry.
We tested this against the whole live feed on 2026-08-03 — 974 hazards across 21 types, sampling up to three per type so that every type was covered, 57 hazards fetched in total:
Hazards with any exposure rows
54 / 57
With a non-null admin1 or admin2
0
Where totalByAdmin differed from totalByCountry
0 of 54 — identical countries and values
This is not a cyclone-specific gap: the sample spans wildfire, flood, earthquake, volcano, extreme temperature and conflict.
What it does not establish is why. The published PDF documents totalByAdmin as an admin breakdown and the fields are structurally present, which fits either “not computed” or “not exposed at our API tier” equally well. Our test cannot separate those, and it is the single most consequential thing to ask PDC.
The consequence either way is that PDC is adm0-only for this book’s purposes. It cannot participate in the adm0 = Σ adm1 conservation check of ADR 0002, and any plan that needs PDC sub-nationally is blocked on that answer. Its only sub-national-ish axis is the damage bands above, which slice by severity rather than geography.
7.4 Where PDC’s numbers come from
Everything above treats PDC’s exposure as a black box. It is worth opening, because what is inside changes how much of it we can use and who we have to ask about the rest.
Two sources of evidence: fields inside the API payload itself, and the layer metadata exposed in PDC’s DisasterAWARE application (read from a logged-in session on 2026-08-04, since none of it is in the API or the public documentation).
flowchart TD
FC["Official forecast advisory<br/>NHC · CPHC · JTWC<br/><i>issuer field, verified</i>"]
KC["<b>KineticCast™</b><br/>Kinetic Analysis Corporation<br/><i>subscription service to PDC</i>"]
RES["60 arc-second grid<br/>~1.85 km<br/><i>taosArchive filename</i>"]
WIND["Estimated Wind Impacts<br/>= the damage bands"]
SURGE["Estimated Still Water<br/>Storm Surge"]
RAIN["Estimated Rainfall"]
POP[/"Population grid<br/><b>NOT DOCUMENTED</b><br/>age bands, vulnerable,<br/>households"/]
FAC["Facility inventory<br/>OSM/HOT + HIFLD + NDPBA<br/>+ national sources"]
OUT["exposure.data<br/>totalByCountry · exposureLevels<br/>capital.school / .hospital"]
FC --> KC
KC --> RES
RES --> WIND & SURGE & RAIN
WIND --> OUT
POP -.-> OUT
FAC --> OUT
classDef api fill:#d9f5d9,stroke:#2a8a2a,color:#000
classDef da fill:#e8f4ff,stroke:#2166ac,color:#000
classDef gap fill:#f5f5f5,stroke:#888,color:#444,stroke-dasharray: 5 5
class FC,RES api
class KC,WIND,SURGE,RAIN,FAC,OUT da
class POP gap
Figure 7.1: Provenance of the exposure figures PDC serves. Green is verified directly from the API payload; blue is documented in DisasterAWARE layer metadata; the dashed grey box is the one link we have not been able to establish. Note that the impact model is a third-party commercial product PDC subscribes to, not something PDC computes.
7.4.1 The impact model is a third-party commercial product
PDC does not compute the cyclone impact estimates. All three impact layers carry the same statement:
Estimated Wind Impacts are calculated using (KineticCast™ Model) model and provided as a subscription service to PDC by Kinetic AC.
Kinetic Analysis Corporation is Charles Watson’s company, and TAOS (“The Arbiter of Storms”) is his model — a numerical model producing maximum sustained surface winds, still-water surge heights and deep-water wave heights, first installed at CIMH in 1994 and adapted as TAOS/L for the OAS Caribbean Disaster Mitigation Project. KineticCast is its commercial descendant.
That lineage is preserved in the payload. Every cyclone record carries a taosArchive field, and its filename decodes cleanly:
kinetic_60as_1785769547237_4307099.zip
│ │ │ └── global job counter
│ │ └── model run time (epoch ms)
│ └── 60 arc-seconds ≈ 1.85 km at the equator
└── Kinetic(Cast)
The 60as resolution is constant across every record we have captured, for both NHC- and JTWC-sourced storms — so the method is uniform globally, and there is no reason to expect Atlantic/East-Pacific exposure to be computed differently from the Western Pacific storm we observed. The run timestamp also explains the publication timing: the hazard record updates 18–41 seconds after the model run completes, so the ~2.5 h gap after the synoptic hour is model runtime, not ingest lag.
The practical consequence is about who can answer questions. Methodology questions belong to Kinetic AC, not PDC, and a subscription contract is a plausible reason the inputs are not published.
7.4.2 The damage bands are damage ratios, which is why they are not wind bands
The band labels give it away once you read them as a modeller would: “Moderate Damage; 5% of value” is a damage ratio — percent of capital value lost. That is the output of a damage function, not a wind threshold.
This matters because the obvious hypothesis — that the three bands are just the 34/50/64 kt rings relabelled — is tempting and wrong. It is also testable, because impactGeometry contains three separate polygons, one per exposureLevel. Comparing each against a swath built from PDC’s own quadrant radii along the same track:
Band
Description
Band area
Paired swath
Swath area
ratio
1
Minor Damage; power out
23.3
34 kt
205.8
0.11
2
Moderate Damage; 5% of value
31.0
50 kt
82.4
0.38
3
Widespread Damage and Above
56.6
64 kt
35.3
1.60
Three independent refutations. The areas run backwards — “Widespread Damage” has the largest footprint and “Minor Damage” the smallest, when 64 kt must be innermost and smallest. The bands are not nested — band 1 does not contain band 2, so they are not concentric rings at all. And overlap is poor: IoU of band 1 against the 34 kt swath is 0.104, when that pairing should be the strongest.
One coincidence nearly sold it. For Japan the GDACS/PDC population ratio at 64 kt is 1.95, and the circle-versus-quadrant area ratio at 64 kt is also 1.95 — which looks like confirmation that band 3 is the 64 kt figure computed on a quadrant polygon while GDACS sweeps a max-radius circle. The geometry says otherwise. It is worth recording precisely because it is the kind of number that would justify shipping a wrong mapping into an operational alert.
So PDC exposure cannot be placed in a 34/50/64 kt column, and no additional storms will change that — the refutation is structural, not sampling noise.
7.4.3 The facility counts are a merged inventory of uneven coverage
capital.school and capital.hospital come from PDC’s own global layers rather than from Kinetic AC. The schools layer states:
PDC Global School data… uses various public sources such as OpenStreetMap (HOT) and merges it with the best available National and NDPBA data sources.
with tags confirming HOT/OpenStreetMap, HIFLD and NDPBA. That is a merged inventory whose completeness varies substantially by country: a low school count in a poorly-mapped country reflects poor mapping, not few schools. Per-feature provenance does survive — the lineage note says data and geometry sources are retained as feature attributes — but the aggregate count in exposure.data does not carry it.
Two flags for anyone thinking of publishing these numbers. The layer carries a “For non-commercial use only” usage constraint, the first hard licence restriction we have encountered in this source; humanitarian use is very likely fine, but the constraint attaches to data that would be redistributed. And it is unclear whether capital.school aggregates all three school sub-layers (colleges, elementary/secondary, preschools) or only one.
7.4.4 The population input is undocumented
The layer that matters most is the one we have not been able to pin down. population.total, the five-year age bands, vulnerable and households — every figure we would actually consider using — come from a population grid that is named nowhere: not in the API payload (a search for LandScan, WorldPop, GPW, GHSL, HRSL, CIESIN and others returns nothing), not in PDC’s published documentation, and not in the impact-layer metadata, which describes only the hazard products.
What the output structure implies, without confirming: five-year age bands to 100+ and an age-split vulnerable figure require an age-structured population product, which rules out plain LandScan Global; households requires a household-size or household-count layer. And the 60 arc-second grid is twice as coarse as the common 30 arc-second global products, consistent with aggregating a ~1 km grid for speed — which would rule out the 100 m products as a direct input.
Both are inferences from the shape of the output, not evidence. The answer is one layer-metadata panel away in DisasterAWARE (Global Data > Population Density), and it is worth getting before any PDC population figure is published, because the choice of grid is the single largest determinant of whether PDC’s numbers should agree with GDACS, ADAM or CHD at all.
7.5 The structural limitation is real, and different from what we thought
Chapter 08 identified the absence of an archive as disqualifying. That holds. But the live data shows the problem is sharper than “no back-catalogue”.
A PDC cyclone record contains no track history at all. Dolphin was on advisory 31, having formed on 27 July, yet the detail object carries nine positions of which the earliest is the present synoptic hour. Advisories 1 through 30 are absent. GDACS, queried at the same moment, returned all 31 actual advisories plus its forecast leg.
Figure 7.2: Typhoon Dolphin at advisory 31. GDACS (purple) holds all 31 actual advisories back to formation on 27 July. PDC (red) holds only the forecast leg from the current synoptic hour forward — the two overlap exactly where both have data, and PDC simply has no record of the preceding week.
The operational consequence is that a PDC historical record cannot be backfilled even for storms currently in the feed. It can only be accumulated forward, at the advisory cadence, by polling. That is why scripts/poll_pdc_cyclones.py runs every three hours rather than daily: a daily poll would silently discard roughly three of every four advisories, and those are unrecoverable.
7.6 An incidental finding about our own GDACS loader
Locating Dolphin in GDACS exposed a bug on our side worth recording.
gdacs.get_active_cyclones() leaves the alertlevel parameter unset by default, documented as “Default: all levels”. GDACS does not treat an omitted alertlevel as “all”:
Every one of the 19 events in the unfiltered response is Orange or Red. Omitting the parameter silently restricts results to those two levels, so the function drops Green events — and Dolphin, a Category 2 typhoon with 1.3M exposed in Japan by GDACS’s own reckoning, is Green. Any monitoring that relies on the default is blind to storms in this category.
7.7 Revised recommendation
Chapter 08’s recommendation was do not integrate, resting on three supports. Two have now failed:
“PDC’s only observable cyclone is a manual response snapshot with zero exposure.” — No longer true. Automatically-ingested cyclones exist, carry full forecast tracks with standard quadrant wind radii, and compute per-country exposure.
“PDC has no path to IBTrACS.” — Resolved. Automated cyclones carry an ATCF ID, which joins exactly to IBTrACS USA_ATCF_ID. This is a stronger link than the GDACS side has: gdacs.py matches on name plus season and needs a hand-maintained exceptions list for unnamed storms, which the ATCF key handles natively.
“No archive, so no backfill to CERF’s 2006 baseline.” — Still true, and worse than described. There is no track history even for live storms.
The conclusion that follows is not “integrate PDC” but a change in what PDC is for. It was assessed as a historical exposure source, and as that it remains unusable — nothing will ever backfill it. What the live data shows is a competent real-time product: same bulletin as GDACS, same wind geometry, an independent exposure estimate that agrees with GDACS to within 8% on the country both cover, and a clean storm identifier.
That makes PDC a candidate corroborating source for real-time monitoring, in the ds-storms-pipeline / ds-storms-alerts lane, and not a candidate for the historical harmonisation this book is otherwise about. Two independent exposure estimates over identical geometry is exactly the kind of cross-check that makes an alert more trustworthy, and the incidental GDACS finding above is a concrete illustration of why depending on a single source is fragile.
Concretely, the position this chapter supports:
Keep capturing. The poller is running every three hours. The archive only exists going forward, so the cost of waiting is permanent, and it is small.
Do not integrate into the historical pipeline. Nothing here changes the 2006-baseline problem.
Integrated into the daily GDACS monitor email, which is where that re-assessment landed. See What happened next.
7.8 What happened next
Written a day after the rest of this chapter, because two things changed quickly enough to make the recommendation above out of date.
The landfall fields populated. They were null on every capture until Typhoon Dolphin’s advisory 35, when they filled in with Japan, 72 hours out, Category 3. That was the condition this chapter set for re-assessing PDC for alerting, and it arrived within two days. The fields are exactly as useful as hoped: the monitor previously said nothing about when or where a storm comes ashore, and that line is what turns an exposure count into a deadline.
PDC now ships in the monitor email. The per-country strip plots were replaced by a ridgeline panel — a density ridge per wind threshold showing that country’s storm history, a dot for the current storm, and PDC as a stacked damage-class bar anchored to its total on the shared population axis. PDC is deliberately not a dot on a ridge, for the reason established above: its classes are a damage ratio, so a dot would assert a wind mapping that does not exist.
The framing that made PDC composable with an email built on history is simple. GDACS answers how many and, with 25 years behind it, how unusual. PDC answers how bad — and that question needs no history at all, so PDC could join immediately and will simply gain its own return period once a season has accumulated.
The clearest thing the panel does is make the China divergence legible without prose. GDACS reports 149M exposed there; PDC reports 94,900, of which 99% is its minor class. On the panel that is a 34 kt dot far out in the right tail, “not reached” at 64 kt, and a PDC bar three decades to the left. A monitor showing only the 149M gives a reader no way to see that.
Two implementation notes worth carrying forward. The email queries PDC live rather than reading the capture archive, because PDC publishes at bulletin issuance while the poller runs 3-hourly, so the archive can be three hours stale at send time; the archive’s job is the historical record, which is a different job from alert freshness. And PDC failures fail the run rather than degrading: an earlier version continued without PDC, and a missing API key then produced emails that were indistinguishable from PDC genuinely having no data for the storm.
7.8.1 The discovery window is narrower than we documented
Chapter 08 estimated that /hazards returns active hazards plus those that ended in roughly the last 30 days, and concluded that daily polling therefore had a generous cushion. Re-measuring the live feed shows that cushion does not exist.
The error was in the classification rather than the data. The original count treated every hazard with a real, non-sentinel endedAt as ended — but most of those timestamps are in the future, a projected end for a storm still running. Dolphin carried an endedAt of the next day while it was a Category 3. Across 949 live hazards, 27 carry the “still active” sentinel, 919 have an endedAt in the future, and just three are genuinely past their end — all three by less than a day.
Chapter 08’s own evidence pointed at this and was read the wrong way: the 86-event flood cohort it noted had closed within the last 24–48 hours, which is a one-day window, not a thirty-day one.
What replaces the old rule is less tidy than the rule it replaces. “Still open” is not sufficient either — Sinlaku carries the active sentinel and is nonetheless absent from the feed. Nor is it a staleness cutoff: a hazard last updated 105.9 days ago is still listed while Sinlaku drops out at 107. Some internal deactivation we cannot see governs membership, so the honest operating posture is not to predict what will still be there.
None of this changes the recommendation, but it sharpens why the poller runs 3-hourly rather than daily. The earlier model implied a month-long grace period in which a missed storm could still be picked up. There is no grace period. A storm is discoverable only while PDC keeps it open, and the next section explains why missing that window is permanent.
7.8.2 The archive is a key-value store with no key list
One further finding, because it bears directly on the no-history problem. GET /hazards/{uuid}keeps working long after a hazard leaves the rolling window — Sinlaku and the Puerto Rico flood both still return full detail three and a half months after dropping out of /hazards (107 and 100 days respectively, checked 2026-08-05). So the perishable thing is not the payload; it is discovery.
That does not open a back door to history, because there is no way to obtain keys for anything not currently in the window:
Hazard identifiers are UUID v4 — random, unordered, a 2^122 space. They cannot be enumerated, and they cannot be derived from a storm’s ATCF ID or name.
The API surface is six paths (/hazards, /hazards/{uuid}, /hazards/types, and three /actuator endpoints). There is no search, no query-by-identifier, and no archive endpoint.
So a 2024 or 2025 storm is retrievable in principle and unreachable in practice, unless its UUID was recorded at the time by someone. The practical consequence is unchanged and worth restating plainly: the archive begins the day polling begins, and every advisory before that is gone. It also means a UUID is worth more than it looks — capturing the list view is what buys future access to the detail, and a UUID salvaged from any other system that touched PDC is a genuine recovery.
The remaining open questions from chapter 08 that this chapter does not settle are the exposure-compute trigger in full, the RESPONSE category lifecycle, and PDC’s endedAt semantics — Bavi still carries the “active” sentinel three weeks after its GDACS counterpart ended, and reports 396.8M exposed at a single coarse band, which is reason enough to treat the RESPONSE tier as unfit for quantitative use.