# Production checklist

> What to set before your app goes live, with the page that explains each item.

Go through this before real users reach your app. Each item links to the page that explains it.

## Keys

- Make a key for production, name it after where it runs, and keep it in your server's environment. Never
  put it in a web page or a mobile app: whoever holds it can read every memory it reaches.
  See [Keys](https://docs.geniffy.com/keys-and-spaces#keys).
- Use a different key for staging and for your own laptop, and keep their data in spaces of their own,
  such as `test_user_1`. Keys tell callers apart, not data.
- Know how you will rotate it: make a new key, put it where the old one was, then revoke the old one. A
  revoked key stops working within seconds.

## Spaces

- Bind a client to a space for every request that belongs to one of your users, at the edge of your
  request handling, and use only the bound client below it. A call that names no space writes to your
  own memory. See [The one mistake to avoid](https://docs.geniffy.com/keys-and-spaces#the-one-mistake-to-avoid).
- Name spaces after your own stable user ids, such as `user_8841`: up to 128 letters, digits, dots,
  dashes or underscores.
- Wherever your app deletes a user, or a user asks to be forgotten, call `forget_space` for their space.
  It takes everything held for them, and only that, and it cannot be undone.

## Adding

- Save a conversation as your framework already holds it; there is nothing to convert. See
  [Conversations](https://docs.geniffy.com/add-memories/conversations).
- Catch `UnreadableError` where people upload files or paste links. `error.source.error` says why in
  plain words, so you can show it to them.
- You do not have to wait for learning before you answer. When you do need to, `sources.wait(id)` returns
  the moment learning ends.

## Recall

- Put the block `context()` returns into your prompt as it is. It is never empty: when nothing is known
  it tells your model to say so, so do not add a fallback of your own.
- Use `search()` only where you want ranked memories with no judgement on them. See
  [Recall](https://docs.geniffy.com/recall).

## Errors and retries

- Let the SDK retry. It retries reads on network errors, 408, 429 and 5xx, and adds only when the
  request never reached Geniffy or on 429, so a retry never saves a note twice.
- Catch `AuthenticationError`: a wrong or revoked key. See [Errors and limits](https://docs.geniffy.com/errors).
- Log the request id of every failed call next to your own log line. See [Request ids](https://docs.geniffy.com/request-ids).

## Watching it

- **Requests** in the Geniffy app shows every call your keys make for 30 days: which key, which space,
  what was asked, what came back, how long it took, and which SDK sent it.
- **Spaces** in the Geniffy app warns you when memories arrive through the API with no space named.

Source: https://docs.geniffy.com/production-checklist
