Guides

Retries and Timeouts

Auto-retry on 429, how to tune it, and when to back off yourself.

The SDK retries rate-limited (HTTP 429) requests automatically. Everything else is up to you.

What the SDKs retry

  • 429 responses, up to the max_retries / maxRetries count with exponential backoff.
  • If the response includes a Retry-After header, the SDKs wait exactly that long.
  • Otherwise they wait 1s, 2s, 4s, … (Node uses 2 ** attempt seconds with the defaults; Python uses retry_backoff * 2 ** attempt).

What they don't retry

  • 4xx responses other than 429. These raise/throw immediately.
  • 5xx responses. These surface as MemsyAPIError; retry them yourself if appropriate.
  • Timeouts and connection errors. These raise MemsyConnectionError.

Tuning retry behaviour

import os
from memsy import MemsyClient

client = MemsyClient(
    base_url=os.environ["MEMSY_BASE_URL"],
    api_key=os.environ["MEMSY_API_KEY"],
    max_retries=5,       # try up to 5 times on 429 (default: 3)
    retry_backoff=2.0,   # base backoff, doubles per attempt (default: 1.0)
    timeout=60.0,        # per-request timeout in seconds (default: 30.0)
)

When to increase max_retries

For background workers and batch jobs where latency doesn't matter but making forward progress does.

When to decrease max_retries

For user-facing request paths where you'd rather fail fast and show an error than hang the request while the SDK sleeps.

retry_backoff

Tune if you're sharing one API key across many workers and want to spread retries out. In most single-client setups the default is fine.

What happens after retries are exhausted

The SDK raises a rate-limit exception with the Retry-After value populated if the server provided one.

from memsy.exceptions import RateLimitExceeded

try:
    client.search("preferences")
except RateLimitExceeded as e:
    print(f"Still rate limited after retries; try again in {e.retry_after}s")

Idempotency considerations

  • search() and status() are read-only and always safe to retry.
  • ingest() is safe to retry within a rolling 60-second window. The platform hashes (actor_id, session_id, kind, content) and collapses identical tuples to a single stored event, returning the original event_id for duplicates so subsequent status() calls still work. Dedup is best-effort — under platform degradation you may still see fresh event_ids for duplicate submissions, so for retries outside the window or cross-process exactly-once needs, keep a client-side log of submitted hashes.
  • clear() is currently a stub that returns 501 Not Implemented — it does not delete anything. A real actor-scoped delete is being designed; until then, calling clear() will raise MemsyAPIError (Python) / MemsyAPIError (Node). Avoid calling it in production paths.

Timeouts

timeout is passed straight through to httpx. It covers the full request lifecycle — connect + read + write. If a single call can take longer, raise it. Timeouts raise MemsyConnectionError, not RateLimitExceeded.

Next