← All postsOctober 8, 20249 min read

How We Serve a Global Weather Model on a Budget

PRPriya Raman
Head of Data

How We Serve a Global Weather Model on a Budget

Forge processes 50,000 weather requests per day. Each one needs sub-100ms latency and geographic accuracy within 5 kilometers. We could solve this by calling a raw weather model API for every request, but that's expensive and slow. Instead, we built a smart caching and interpolation system. Here's how.

The Naive Approach (And Why It Fails)

If we queried our underlying weather data provider for every Forge request, costs would be prohibitive. A free-tier user making 100 requests per day would cost us more than they paid. We needed a different model, one that amortizes the cost of data fetches across many user requests.

Grid-Based Storage

Weather data doesn't change smoothly—it has discontinuities at fronts and edges. But over small distances, it's relatively uniform. We discretize Earth's surface into a regular 10-kilometer grid and cache weather predictions at grid points. For the continental United States and Europe, we cache every 4 hours. For less-trafficked regions, every 8 hours.

Grid points are stored in a columnar database (we use DuckDB for this). Each column is a variable: temperature, humidity, wind speed, etc. Each row is a time-location pair. This structure makes time-series queries fast and enables efficient compression.

Interpolation on the Fly

When a user queries a specific latitude and longitude, we:

  1. Find the four nearest grid points (forming a square around the coordinate)
  2. Perform bilinear interpolation between those points
  3. Return the interpolated result

Bilinear interpolation is cheap—a few floating-point operations per request. It gives us the illusion of having weather data at infinite resolution without storing it. For a request at (51.515, -0.131), we interpolate from grid points at (51.51, -0.13), (51.51, -0.14), (51.52, -0.13), and (51.52, -0.14).

For time-domain interpolation (e.g., requesting weather for 3:15 when we only have data for 3:00 and 4:00), we use linear interpolation. Temperature and humidity change smoothly over time, so this works well.

Smart Caching

Our three-tier cache strategy:

Most requests never leave memory. A request that misses L1 but hits L2 takes 8ms. A cache miss to L3 takes 35ms but happens infrequently.

Grid Generation Pipeline

Every 4 hours, our ingestion pipeline:

  1. Fetches raw data from upstream weather models (NOAA, ECMWF)
  2. Resamples it onto our 10km grid
  3. Computes quality metrics (confidence, source)
  4. Writes to DuckDB
  5. Notifies all edge servers to invalidate their L1 cache

This whole process takes 90 seconds for a global dataset, running on two c6i.4xlarge instances.

Handling Sparse Coverage

Antarctica and the Pacific Ocean have less weather data. We handle sparse regions by increasing grid spacing there. Antarctica uses a 50km grid instead of 10km. We also blend satellite data with model predictions to fill gaps.

Accuracy Trade-offs

How accurate is our interpolation? We validate quarterly using real-world weather station observations. Our median error is 1.8 degrees Celsius for temperature, 7% for humidity. The trade-off is worth it—users get instant responses, and our costs stay reasonable.

Cost Breakdown

For 50,000 weather requests per day:

That's $0.0024 per request, with our profit margin built in. It works because interpolation and caching eliminate redundant data fetches.

Future Work

We're experimenting with machine learning to improve sparse-region predictions and with finer-grained spatial resolution in high-traffic areas. We're also exploring different interpolation methods for wind direction (which has circular boundary conditions) versus temperature.

Serving global data at scale is a hard problem. We're proud that Forge does it without requiring users to think about any of this complexity.