# Caching and max_age

Every result is stored in our database. When a fresh enough copy exists, you get it straight away,
and a company or domain lookup costs less. A "no such company" answered from the cache is free.

## Defaults

Without `max_age`, a lookup takes our copy when it is at most this old, and fetches fresh otherwise:

| Endpoint | Oldest copy used by default |
|---|---|
| `POST /v1/company` | 7 days |
| `POST /v1/domain` | 7 days |
| `POST /v1/person` | 24 hours |
| `POST /v1/search` | 24 hours |

## Check before you buy

[`POST /v1/cache`](/docs/cache) is free. Send it the body of a company or domain lookup and it tells you
how old our copy is, whether the lookup would be answered from the cache, and what it would cost, from
the cache and fetched fresh. Then choose your `max_age`.

## Choosing freshness with `max_age`

`max_age` is the oldest answer you accept, in seconds.

- Leave it out to use the defaults above.
- `max_age: 3600` accepts answers up to an hour old and fetches anything older.
- `max_age: 31536000` accepts anything up to a year old. There's no upper limit: we serve any copy we
  still hold, at the cache price.
- `max_age: 0` always fetches fresh.

Company profiles are kept for good. Search results are kept for 30 days, and a person's profile for 30
days after its last lookup, so older ones are fetched fresh whatever `max_age` says.

## What each response tells you

`meta.cache` on every result, and the matching headers:

| Status | `X-Cache` | Meaning |
|---|---|---|
| `hit` | `HIT` | Served from our database. |
| `miss` | `MISS` | Nothing usable was cached; fetched now. |
| `refresh` | `REFRESH` | A cached copy existed but was older than your `max_age`; fetched now. |

`meta.cache.age_seconds` (and the `Age` header) is how long ago we fetched the data,
`meta.cache.fetched_at` is when, and `meta.cache.max_age_seconds` is the window that applied.

## One company, one cache entry

Every form of a company (URL variants, letter case, old slugs, the numeric id, the URN) reaches the same
entry. Look up `stripe` and then `2135371`, and the second call is a hit. A domain you looked up
leads to its company's entry too: after `stripe.com`, `POST /v1/company` for `stripe` is a hit.

## Knowing when data changed

`meta.content_hash` is a hash of `data`. If it's unchanged since your last copy, so is the data, and you
can skip your own processing.
