Methodology

How Bay Area Swim decides whether a beach is safe, caution, unsafe, or inconclusive — and what that label does and does not mean.

The four labels

How we compute the score

The risk macro evaluates these rules in priority order. Whichever rule fires first determines the label.

  1. HAB Danger Advisory in effect → unsafe (overrides everything; this is a real-time agency advisory, not a sample-based signal).
  2. No data at all (no bacteria, no rain, no advisory) → inconclusive.
  3. Last bacterial sample > 30 days old → inconclusive. The water has had a month of mixing, runoff, sun, and microbial die-off; the reading is no longer load-bearing.
  4. Off-season + sample > 14 days old → inconclusive. Some agencies stop sampling Nov–Mar; we don't pretend their last summer reading still applies.
  5. Bacterial exceedance on the most recent sample → unsafe.
  6. Heavy 48 h rain (more than 1.0 in / 25.4 mm) at an enclosed or storm-drain-adjacent beach → unsafe.
  7. HAB Caution Advisory in effect → at least caution.
  8. Meaningful 72 h rain (more than 0.5 in / 12.7 mm) → caution.
  9. Otherwise → safe.

EPA bacterial thresholds we use

Source: U.S. EPA Recreational Water Quality Criteria, 2012.

The recent rainfall caveat

A "safe" label is based on the most recent sample. If that sample was taken before a recent storm, the water you see today may not match what was tested. When more than ~0.2 in of rain has fallen in the past 72 hours, every beach page surfaces a small "recent rainfall may have changed water quality" banner under the status. The label itself doesn't change — sample-based scoring stays sample-based — but you can factor the storm in yourself.

What we deliberately don't model

Limitations

FAQ

How fresh is this data?

Most sources update weekly. The pipeline checks every source daily and re-publishes the snapshot whenever any source has changed. The /status page shows the exact last-update time for each source.

Why does this beach show "Inconclusive"?

Either no recent monitoring data exists for it, or the most recent sample is more than 30 days old. A 60-day-old "exceeded" reading is no longer a useful indicator of swimmer safety, so we degrade to inconclusive rather than confidently flag unsafe.

What does "Caution" actually mean?

A real but secondary risk signal — typically meaningful recent rainfall (above the 0.5 in / 72 h threshold) without a confirmed bacterial exceedance, or a HAB (harmful algal bloom) Caution Advisory from the local agency. Use your own judgment; pay attention to the explanation below the status badge.

Why does it say "Safe" even though it rained yesterday?

When recent rain (more than ~0.2 in in the last 72 hours) has occurred but the official sample predates the storm, we keep the safe label but show a rainfall caveat directly under the status. The sample-based status is unchanged; the caveat lets you weigh the staleness yourself.

Can I trust this for medical decisions?

No. This site aggregates public monitoring data with our own risk thresholds; we are not a public health agency, do not collect samples, and do not make medical claims. When in doubt, check the agency's official advisory page (linked from every beach detail page) or call the local park / beach office.

How do I report a discrepancy or a wrong location?

Open an issue on GitHub at github.com/patrickbeekman/bay-area-swim. Pull requests welcome — every data source and the risk macro are in the open repo.

Open source

Every source fetcher, dbt model, and risk threshold is in github.com/patrickbeekman/bay-area-swim. The risk-scoring rules above live in dbt_project/macros/compute_risk_status.sql; if you think the logic is wrong, open an issue or a PR.

Information provided for general guidance only. Conditions change rapidly. Swim at your own risk. Not medical advice.

Information provided for general guidance only. Conditions change rapidly. Swim at your own risk. Not medical advice.