twin memory

Idempotency & retries

Why retrying any request is safe, and how to name items so that a retried add never adds anything twice.

Networks fail. A request can time out after the server committed it. twin memory is built so that sending the same request again changes nothing the first one did not.

The item id is the identity

An item's id decides which item it is. Sending an item with an id memory already holds is the same item, not a second one:

  • the same content again changes nothing;
  • different content is an edit.

So the simplest rule is: give every item a stable id from your own system, such as your message id, and retry freely.

Items without an id

If your items have no ids, send an Idempotency-Key header with the add:

curl https://api.twinmemory.dev/v1/memory/add \
  -H "Authorization: Bearer $TWIN_MEMORY_API_KEY" \
  -H "X-Twin-Account: user_42" \
  -H "Idempotency-Key: batch-7" \
  -H "Content-Type: application/json" \
  -d '{ "items": [{ "text": "hello there" }] }'

Each item without an id is then named by the key and its place in the batch: the first is batch-7:0, the second batch-7:1, and so on. A retry with the same key and the same items in the same order is the same items again.

{
  "items": [{ "id": "batch-7:0", "event_id": "ev_4e787041d539c3d4", "landed": false }],
  "queued": 1,
  "pending": 1
}
  • Items that have an id keep it; the key does not rename them.
  • The key is trimmed and cut to 200 characters.
  • Use a new key for each new batch, such as a UUID made when the batch is built, and reuse it only to retry.

Without an id and without a key, an item with an at is named by its words, author, session and time, so the same words at the same time are the same item. An item with neither an id, a key nor an at gets a random id, and a retry adds it twice.

No stored replies

twin memory does not store responses to replay them. A retried request runs again. Because it names the same items, it changes nothing, and its response describes the same items with the same event_ids.

Retrying other routes

  • Reads (search, grep, read and the rest) change nothing. Retry them freely.
  • forget of something already forgotten erases nothing more. The second receipt counts zero events. If a receipt says "queue": null, call forget again to clear the queue.
  • correct of a record already retracted answers 404, because the record is no longer held. Treat that as done.

Times and offsets

An item's time is part of its identity when it is first stored. Once memory holds an id, later sends keep the first time, whatever at they carry.

For items without an id, the time is part of the name. 09:00+09:00 and 00:00Z are the same instant but not the same text, so they name two items. Send stable ids and this cannot happen.

When to retry

StatusRetry?
503Yes, after Retry-After seconds when present, otherwise with backoff.
Network error or timeoutYes.
400, 401, 403, 404, 413, 422No. Fix the request. A 404 on a read means the end user has no memory yet.
  • Items: every field, and how ids are made.
  • Errors: every status and message.

On this page