Hosting data is hosting a dependency. Once another page fetches it, you have consumers you cannot see and cannot contact.

This guide covers the contract, versioning and caching.
The address is a contract
Consumers hard-code the address into their pages.
Change it and every one of them breaks at once, silently, and you frequently have no idea who they are. A file published for one internal use gets found and used by three other teams within a year.
So treat any published data address as permanent from the first day.
The shape is also a contract
Adding a field is usually safe. Existing consumers ignore what they do not read.
Removing or renaming one is not. A consumer reading a field that disappears gets nothing, and depending on how they wrote it, that is either an empty value on a page or an error that stops their script.
/data/v1/rates.json
/data/v2/rates.json
For a structural change, publish the new shape at a new address and keep the old one serving until you are confident nothing depends on it. If you can, add a note in the old file saying where the new one is.
| Change | Safe | What to do |
|---|---|---|
| Add a field | Yes | Just add it |
| Rename a field | No | New version |
| Remove a field | No | New version |
| Change a type | No | New version |
| Change the address | No | Redirect permanently |
Caching
Consumers see updates when their cache expires, so the lifetime you set decides how stale the data can be.
Match it to reality. Data updated daily, an hour. Data that changes twice a year, a day. Data changing continuously does not belong in a static file.
Put a last-updated value inside the data as well. Then a consumer can display how fresh it is rather than presenting a stale value as current.
{ "updated": "2026-09-19", "rates": { "eur": 1.17 } }
Cross-origin access
A browser will not let a page read a response from a different origin unless the server permits it.
A wildcard means any site can build on your data. For genuinely open data that is the point, and it is worth deciding rather than defaulting into.
For data intended for one site, name that origin specifically.

Everything is public
An unguessable path keeps a file out of search results. It is not access control; addresses leak through histories, referrers and page source.
No personal data, no commercial detail, no keys. If the data needs protecting, it needs something that checks who is asking, which is a server rather than a file.
Where static stops
Three cases.
Faster than you can publish. Live prices, availability, anything second-by-second.
Different per requester. Personalised data cannot be a single static file.
Must not be public. Authentication requires something to authenticate against.
Everything else is a file at an address, and that is a much more reliable thing to depend on than a service.
Two neighbouring cases are worth a look: How to host a JSON file and What is CORS? Why a fetch works locally and fails once published.
Put it at an address
Treat the address as permanent, add fields but never remove them, version the path for structural changes, set the cache lifetime to the real update rate, and put a last-updated value in the data.
Then the consumers you cannot see keep working.