Maliik

What I learned building "banned elsewhere" data into recall alerts

by

Shipped a feature called Banned Elsewhere on Nibble (food and drug recall alerts across 13 countries) last week. The pitch: when you open a recall and it mentions an ingredient that's been banned, restricted, or warning-labeled by a foreign regulator, you see a card with the cross-jurisdiction story. Red Dye 3 banned in the EU since 1994. Brominated vegetable oil banned in the UK since 2008. Potassium bromate banned in Canada and Australia in the early 90s. Still permitted in the US.

The first version was wrong in an interesting way.

The algorithm was: for each ingredient detected in a recall's text, return every jurisdiction with a documented restriction, except the recall's own country. Simple. Tested cleanly on a US recall, where the EU/UK/CA/AU chips lit up exactly as expected. Then I ran it against a French recall that mentioned tartrazine, and the card showed "Tartrazine: banned/restricted in EU." Technically true. Practically useless. The EU restriction already applies in France because France is in the EU.

The fix is a one-line edit: when computing what to suppress, treat the recall's country as in-EU if it's an EU member state, or if it's FR/DE/EU itself. Nibble's data model treats FR/DE as first-class countries with their own per-country coverage rather than rolling them up under EU, which is the right call for everything else but breaks here because EU-level bans inherit downward to member states. Code comment for the future:

// For "banned elsewhere" suppression, we still need to treat FR/DE/EU recalls

// as in-EU so EU-level bans aren't shown as redundant chips.

The lesson I keep relearning is: cross-jurisdiction data isn't a list of countries. It's a graph where some countries inherit rules from supra-national bodies (EU member states inherit EFSA decisions), and you have to suppress the parent when you're already inside the child. I would have spotted it earlier if I'd tested with EU recalls first instead of US-first.

Other things that surprised me:

- Synonym lists are where the work hides. Red Dye 3 is also "Erythrosine," "E127," "FD&C Red No. 3," "Red 3," "Acid Red 51," and "C.I. 45430." Miss any synonym and you miss the match. Every ingredient row in the table has a synonyms array, and we still find gaps as we add coverage for new countries.

- The substance with the longest documented regulatory gap I found is rBGH (recombinant bovine growth hormone): banned in the EU, UK, Canada, and Australia in 1999. Still permitted in US dairy in 2026. That's a 27-year gap on the same molecule.

- Restriction levels matter more than I thought. The data has three tiers (banned, restricted, requires_warning), and a "warning required" rule in the EU is genuinely different from a "banned" one. Tartrazine isn't banned in the EU. It just has to carry a label that says it "may have adverse effect on activity and attention in children." Treating those as the same color of chip would be misleading.

Curious for anyone else building cross-jurisdiction data: how do you handle the parent/child suppression problem? EU/member states is the obvious one. Federal/state in the US, federal/provincial in Canada, or central/prefectural in Japan probably have the same structure. Is there a clean pattern or is every dataset its own special case?

If you want to see the feature live, the easiest path: open Nibble, search "tartrazine" or "Red 3" or "BVO," click into any recall that mentions them, and scroll past the AI summary to the amber-bordered card. There's also a longer write-up landing on the /insights blog this week if you'd rather read first.

2 views

Add a comment

Replies

Be the first to comment