# Caches

Nothing is cached unless you add it. A cache keeps a copy of data in a
Redis store, so busy pages read it quickly. You can cache single records,
on an entity, or a query's results, on the query:

```jadpo
entity Product {
    ...
    caches: {
        records: {
            store: cache
            keep: 1h
        }
    }
}

query category_page(category_id: Category.id, page: PageRequest) -> Page<ProductCard> {
    from: Product
    where: Product.category_id == category_id
    cache: {
        store: cache
        keep: 10m
    }
}
```

`caches: { records: }` on an entity caches single products, looked up by
`id`. `cache:` on a query caches that query's results. Each names its
`store:`, a Redis store declared in `app.jadpo`, and `keep:`, the oldest
an entry can be.

- **Writes always go to the database**, never to the cache, and code never
  names cache keys.
- **The running app keeps caches current.** Jadpo generates the code that,
  after every committed change, clears each cached entry the change could
  affect. A change to a `Product` clears every cached result of every
  query that reads products: some extra database reads, but never a stale
  list.
- **Only pages read caches.** Reads inside actions, policy checks and
  sign-in always read the database, so a decision is never made from a
  stale copy.
- **A cache that can't be reached never fails a request**, anywhere in the
  language. Reads go to the database after a short timeout, a clear that
  fails is retried in the background, and `keep:` bounds how stale an
  entry can get meanwhile. Readiness ([Health](health.md)) doesn't
  depend on a cache.
- **Permissions apply on every read.** Cached results are keyed by tenant
  and by the details policy depends on, so one user's results are never
  served to another. Erasing personal data clears cached copies at once.
- **Each entry is stored as one JSON value**, the same JSON the API sends,
  so every Jadpo type maps cleanly: money as `{"amount": 1250, "currency":
  "GBP"}`, large integers as strings, sets as arrays, enums tagged. Money
  has one shape, its minor units and its currency's code, here as on the
  wire ([Money and payments](money-and-payments.md)).

A record that lives in Redis, rather than being copied there, such as a
cart or a sign-up in progress, is an entity in a Redis store instead
([Entities in Redis](entities-in-redis.md)). Which services can hold a cache
(Redis-compatible ones, or `Driver.memory` with a warning), and what a
cache may and may never hold, are in
[Caches: drivers and what they hold](caches-drivers-and-what-they-hold.md).

Not built yet: caches. Clearing only the affected entries, for example
the category pages a product moved out of and into, isn't designed yet.
