Public
Cron caches a rate-limited API into blob; HTTP serves it
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.

How do I cache a rate-limited API behind my own endpoint?

Two files: a cron val (refresh.ts) fetches an upstream JSON API every 15 minutes and writes the result to blob storage, and an HTTP val (main.ts) serves that cached blob instantly with an X-Cache-Age header. Your endpoint never hits the upstream on request, so it is fast and your traffic never counts against the upstream's rate limit.

Why a keyed upstream?

On Val Town (or any serverless platform), outbound requests leave from shared egress IPs. Keyless APIs that rate-limit by IP -- Open-Meteo, for example -- count every other user's requests on that IP against "your" limit, so even one polite cron call can come back 429. An earlier version of this template used Open-Meteo and hit exactly that failure: the refresh cron itself got rate-limited by other users' traffic.

The fix is an upstream with a per-key quota. This template uses OpenWeatherMap: the quota belongs to your API key, so nobody else on the shared IP can drain it. The cron-to-blob cache then keeps your own usage to one upstream call per interval, no matter how much traffic your endpoint gets.

Files

  • refresh.ts - cron, runs every 15 minutes, fetches OpenWeatherMap current weather and writes { fetchedAt, data } to the blob key cache
  • main.ts - HTTP endpoint, reads the blob and returns the data with X-Cache-Age (seconds) and X-Cache-Fetched-At headers; returns 503 if the cache is empty

Setup

  1. Remix this val
  2. Get a free API key at https://openweathermap.org/api
  3. Set the OPENWEATHER_API_KEY environment variable

šŸ‘‰ Add OPENWEATHER_API_KEY here: https://www.val.town/x/templates/cached-api-proxy/environment-variables?key=OPENWEATHER_API_KEY

  1. Run refresh.ts once (Run button) to populate the cache, or wait for the first cron run
  2. Hit the main.ts endpoint URL - check the X-Cache-Age response header to see how fresh the data is

To adapt it to your own API: change the URL in refresh.ts and adjust the cron interval to taste. Keep reading the key with Deno.env.get() - it stays server-side and is never exposed to your endpoint's callers.