AWS Builder Center
How I Built a Weather Risk Engine That Thinks in Three Time Horizons - Amazon S3

How I Built a Weather Risk Engine That Thinks in Three Time Horizons - Amazon S3

A farmer doesn't need one weather forecast. She needs three. Tomorrow's storm needs a firm, immediate warning. Next week's rain needs a heads-up she can plan around. Next month's drought needs a probability, not a promise. Treating all three the same is how weather apps end up either crying wolf or saying nothing. This is the second post about Kisan Mausam , a Hindi-first Android app that gives Indian farmers weather hazard warnings and crop advice.

The idea: forecast confidence changes with time
Weather forecasts get less certain the further out you look. A 2-day forecast is usually reliable. A 40-day forecast is a statistical tilt, not a prediction. So the engine splits the future into three horizons, each with its own data source and its own honesty level.
Horizon
Days
Confidence
What it uses
H1
1–3
High
Open-Meteo forecast
H2
4–10
Medium
Cumulative totals and ensemble spread
H3
10–46
Seasonal outlook
ECMWF SEAS5 / EC46 seasonal data plus the live NOAA ENSO phase
Each warning stores which horizon it came from, so the app can word it differently. "Heavy rain expected, act now" and "Wetter than normal month likely" shouldn't sound the same.

Horizon 1: Short-term warnings (days 1 to 3)

For the first three days I use the thresholds the India Meteorological Department (IMD) already uses for its warnings, so farmers hear the same language as official bulletins.
  • Heavy rain: a day with 64.5 mm or more triggers a  WARNING . 115.5 mm or more triggers an  EMERGENCY .
  • Heatwave: a maximum temperature of 40°C or more on the plains, or a +4.5°C anomaly during flowering or grain-fill.
  • Frost and cold wave: a minimum temperature of 4°C or less, with an earlier cold-stress advisory at 10°C.
  • Hail and squalls: WMO weather codes 96 and 99, or wind gusts of 50 km/h or more.
The last rule has a twist: for tall, lodging-sensitive crops, the wind threshold drops to 40 km/h. A gust that a short crop shrugs off can flatten a tall one.
That's the main reason the engine isn't just "temperature above X." The same weather can be a minor note for one field and an emergency for another, depending on the crop and its growth stage.

Horizon 2: The medium range (days 4 to 10)

By day 4 or later, a single "64 mm on Thursday" number is too precise to trust. So this horizon looks at:
  • cumulative rainfall deficits and surpluses over several days,
  • how much the ensemble members disagree (the spread), which I use as a probability signal.
The output is softer on purpose: "a wet spell is likely," not "it will rain 70 mm on Friday."

Horizon 3: The seasonal outlook (days 10 to 46)

For the long range, the engine uses Open-Meteo's seasonal forecast models (ECMWF SEAS5 / EC46) to estimate 30-day rainfall and temperature anomaly probabilities, then combines them with the live NOAA CPC ENSO phase: El Niño, La Niña, or Neutral.
ENSO matters because it shifts monsoon odds across India. The app turns the Oceanic Niño Index (ONI) into a plain Hindi or English summary and shows it on a gauge on the home screen, so a farmer doesn't need to know what "ONI +0.8" means.

Severity and probability

Every alert carries:
  • a risk type (heavy rain, heat wave, frost, hail, drought),
  • a horizon (H1, H2 or H3),
  • a severity:  ADVISORY ,  WATCH ,  WARNING  or  EMERGENCY ,
  • a probability from 0.0 to 1.0,
  • a Hindi title, message and action line based on ICAR mitigation guidance.
Severity says how bad it could be. Probability says how sure we are. Keeping them separate lets the app say "an EMERGENCY-level event is possible, but only 30% likely" instead of hiding that uncertainty.

Why the thresholds live in JSON

I could have hardcoded  if rain >= 64.5 . I put the numbers in  risk_thresholds.json  instead, for three reasons:
  1. Tunability. IMD guidance and local conditions differ. A hill district and the Gangetic plains shouldn't share every cutoff. Changing a number shouldn't need a code change.
  1. Reviewability. A scientist or agronomist can read a JSON file. They can't easily audit scattered  if  statements.
  1. Testing. The test suite can load known thresholds and check that the engine fires the right severity at the boundary.
A simplified illustration of the idea (replace this with your real file):
JSON
{
"heavy_rain": {
"warning_mm": 64.5,
"emergency_mm": 115.5
},
"heat_wave": {
"plains_max_c": 40,
"anomaly_c": 4.5
},
"frost": {
"min_c": 4,
"cold_stress_min_c": 10
},
"wind": {
"gust_kmh": 50,
"tall_crop_gust_kmh": 40
}
}
[ADD A SHORT SNIPPET FROM YOUR REAL  risk_engine.py  SHOWING HOW A THRESHOLD IS READ AND A SEVERITY IS CHOSEN]

Keeping the farmer from being spammed

A correct warning can still be a bad experience if it arrives five times. Alerts use a SHA-256 deduplication hash with a 6-hour cooldown, so the same hazard for the same farm doesn't buzz a phone repeatedly.

How I tested it

The backend has a test suite for the three-horizon risk engine alongside the auth, DPDP compliance, AI grounding and crop recommender tests.

What this engine can't do (yet)

  • The thresholds follow IMD guidance, but I haven't validated them against local historical crop-loss data.
  • Open-Meteo and the seasonal models are forecasts. Warnings are only as good as the data behind them.
  • Crop-stage sensitivity is only as detailed as the rules I've written so far.
  • [ADD ANY OTHER LIMITS YOU'VE NOTICED]

What I'd like to do next

  • Compare warnings against past events to see how often they would have fired.
  • Add region-specific threshold profiles.

Try it

Next in this series: how the app keeps working when the server and the network go down.
If you work with agrometeorology data: which hazard would you add first?
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article