1Password Rate-Limit: Diagnosis, Game Plans & Payment Breakdown

riles-fleet credential infrastructure · Sage (ultrathink) × Codex (adversarial review) · 2026-06-19
313 rate-limit hits / 3 days 23 hard outages root cause = architecture, not the vendor yes, it can be made never-again
The one-paragraph version. The whole fleet shares a single 1Password service-account on a small plan. The secret-fetching code fans out — 10 agents, Codex, 32 crons, and 4 MCP servers each call op independently, through three separate caches that don't coordinate, with the failover token unset, retry logic that retries the very error it should back off from, and a warm-up job that fires into an active outage. So we blow through the daily read limit and everything 429s until the 24-hour window rolls.
And the good news. This is fixable so it never recurs — and the fix is mostly code we already own. The vendor is not the root cause: with proper caching + a single shared rate governor, the fleet needs on the order of ~100 reads/day, which fits even the smallest 1Password plan. Adding a modest tier upgrade turns that into 100–1000× headroom. Switching vendors without fixing the architecture would just move the same outage onto a new bill.

1. What is actually happening

Every time a fleet process needs a secret (a Cloudflare token to deploy, a Brevo key to send email, ChiroHD login for stats), it shells out to the 1Password CLI (op). Under load op returns HTTP 429 "Too many requests". When that happens and nothing has cached the secret yet, the work fails outright — that is what took down the Athena front-desk chat and repeatedly blocked deploys today.

313429s / 3 days
148429s Jun 19
189dead failovers
119warm-in-storm
23hard outages

Source: /tmp/fleet-cred-get.log pattern counts (independently re-verified by Codex). "Hard outage" = COLD-MISS-FATAL: secret needed, cache empty, op capped.

2. The hard ceiling: how 1Password rate-limits work

Plan tierRead / hour (per token)Write / hourCombined / 24h (whole account)
Individual / Families1,0001001,000
Teams1,0001005,000
Business10,0001,00050,000
The killer is the account-wide DAILY cap. It is a rolling 24-hour window shared across every service account on the plan. Once hit, everything 429s until it rolls — and a second token does not raise it, because the daily cap is account-wide, not per-token. (A second token only buys more hourly headroom.)
Tier is not yet proven. op whoami returns url: https://my.1password.com (the default host, suggestive of Individual/Families), but whoami does not expose the plan tier, and Codex's independent check hit a transient network error. Action: confirm the tier in the 1Password account UI. It is the single fact that decides upgrade-vs-migrate. Working hypothesis: Families, ~1,000/day.

3. Root causes

Six layered causes. RC1 is the ceiling; RC2–RC6 are why we hit it so easily and recover so badly. Verdicts in brackets reflect Codex's independent file-level review.

RC1

Plan ceiling likely too low partially confirmed — tier unverified

If Families, ~1,000 reads/day shared across the entire fleet is nothing. Outage mechanism confirmed; exact tier still needs UI confirmation.

RC2

Uncoordinated fan-out, no single-flight confirmed

Every caller hits op independently; nothing coalesces concurrent requests. Five agents needing the CF token in the same second = five API calls for one secret. vault-load bulk-fetches many secrets in one burst.

RC3

THREE caches that don't coordinate corrected by Codex

Sage initially said two. Codex corrected: ~/.secrets/.op-cache is a fresh-op-binary copy (a separate dyld-wedge fix), not secrets. The real secret stores are three: macOS Keychain fleetcred (fleet-cred-get), ~/.secrets/.vault-cache (vault-get), and ~/.secrets/cache files (cred-cache-lib). Good news: cred-cache-lib already shares the fleetcred Keychain — so the real fragmentation is vault-get's separate cache. Plus a real bug: the Keychain key is item::field with no vault, so it can collide across the Automation and Codex/Claude vaults.

RC4

The 429 failover is dead confirmed

OP_SERVICE_ACCOUNT_TOKEN_B is unset everywhere (env, launchctl, keychain). 189 "would have failed over but couldn't" log lines. The headline resilience feature has never once engaged. (Caveat: a 2nd token only raises the hourly limit, not the daily cap.)

RC5

Warm-up job amplifies storms confirmed

warm-all refreshes 24–25 creds in sequence with no health-probe gate, so it fires all of them even when op is already capped — 119 such skipped attempts logged.

RC6

Retry logic re-hits capped calls partially correct

op_retry retries on "nonzero exit + empty stdout" — and a 429 (printed to stderr, which is discarded) looks exactly like that, so it gets retried (3 total attempts). It does not inspect the 429 text. Narrower than first stated: fleet-cred-get itself does not use op_retry (it detects rate-limit text and backs off), but vault-load and others do.

Amplifiers Codex caught that Sage missed

4. Can it ever happen again? The math

The decisive question. The current broken system attempts far more than 1,000 reads/day (uncached fan-out × retry tripling × stampedes × warm-in-storm). After the architecture fix, the fleet's steady-state demand collapses:

Source of op reads (post-fix)Reads / day
One health-gated daily warm of the critical-cred list (25 creds)~25
Refreshes as 24h TTLs expire (mostly covered by the warm)~10–25
Cold misses for non-warmed secrets, coalesced by single-flight~10–40
Agent / MCP / cron restarts reading from a warm shared cache (0 op calls if cache is fresh)~0–30
Realistic steady-state total~50–150 / day
1,000Families cap
5,000Teams cap
50,000Business cap
~100our real need
Answer: yes — but the tier upgrade is headroom, not the guarantee. Steady-state ~100 reads/day fits even Families (10× headroom). The danger is the worst-case spike, and the spike is not ~100 — it is multiplied. The dead token-B (×2 attempts) × the op_retry wrapper (×3) is a ×6 retry multiplier on every call. A ~247-read cold-start storm becomes ~1,482 requests/storm; if it repeats every 5 min during op-binary / auth churn, ~17,784/hr — which blows past even Business's 10,000/hr-per-token limit. So Business buys headroom; it does not make this never-again on its own. The actual guarantee = a global circuit-breaker + single-flight + killing the ×6 multiplier. Do that and the spike never forms; the tier is just insurance on top. tier = headroom · the de-amplify + circuit-breaker = the guarantee — see §8

5. The game plans

Three plans. The architecture fixes (unify caches, single-flight, governor, 429-safe retry, kill the stampede, one health-gated warm) are mandatory in all three — they are the actual root-cause fix. The plans differ only in where the secrets live and how much headroom we buy.

Plan A — Keep 1Password, harden + upgrade to Business recommended

Do the full architecture fix, then upgrade the plan to Business for 50,000 reads/day of headroom.

Never-again? Strong yes — ~100/day need vs 50,000/day cap = 300–1000× headroom. Effort: architecture work (needed anyway) + ~1–2h to upgrade billing. Net new cost: 1Password Business seats (see §6).

~ Plan B — Migrate to Infisical

Same architecture discipline, but move secrets to Infisical and run the Infisical Agent. Note: persistent local Agent caching is currently Kubernetes-only — the documented Agent caching is for dynamic-secret leases, and the Agent also retries failed requests 3× by default (same failure class as ours unless explicitly tuned). So the Agent is not a free fix.

Never-again? Yes if self-hosted, but only because we'd still do the same architecture fix — and we'd add a new self-hosted server + the Agent as fresh single-points-of-failure. Effort: ~10–20h migration. Risk: lateral — new vendor, new failure surface.

Plan C — Minimum: architecture fix only, stay on current tier ($0)

Do the architecture fix, buy no upgrade, governor sized to the current (small) cap.

Never-again? Risky — on Families' 1,000/day, a bad spike (mass restart + cache wipe) can still graze the ceiling. Relies on caching being perfect with thin headroom. Good as the free first step, not the final answer.

6. Payment breakdown

Option 1 — 1Password (keep)

PlanPriceDaily read capFit for the fleet
Families (likely current)$4.49/mo billed annually (~$54/yr, up to 5 people)1,000/dayWorks only with perfect caching; thin headroom
Teams Starter Pack$19.95/mo flat (10 members, billed annually)5,000/dayComfortable — 33–100× headroom
Business recommended$7.99/user/mo billed annually50,000/day (10k/hr)Bulletproof — 300–1000× headroom

Business cost depends on seat count. A handful of seats ≈ $8–$40/mo. Well within the under-$50/mo fleet budget. No code changes required for the upgrade itself.

Option 2 — Infisical (migrate)

PlanPriceLimitsNotes
Self-hosted (OSS)$0 software (we host it)Up to 5 machine identities, 3 projects/envs (free-tier feature gating); no vendor read cap when self-hostedCheapest on paper; real cost is our hosting + maintenance + a new SPOF
Cloud Free$05 identities, 3 projects/envs, 10 integrations; 120 secret-ops/min (200 reads/min)Per-minute cap is tighter than 1P's hourly window — a burst trips it faster, not slower
Cloud Pro$18/mo per identity12 projects/envs, rotation, SSO, 90-day audit; 300 secret-ops/min (350 reads/min)Per-identity pricing adds up fast; per-minute cap still tighter than 1P hourly on a spike
EnterpriseCustom quoteDynamic secrets, gateways, KMIP, 99.99% SLAOverkill for now
Infisical does not automatically solve the problem. Infisical Cloud has its own API rate limits, and self-hosted Infisical adds a server + the local Agent as new single-points-of-failure. The thing that makes "never again" true is the architecture fix (caching + single-flight + governor) — which we have to do regardless of vendor. So Infisical only wins if we specifically want to eliminate the per-read ceiling via self-hosting and are willing to own the ops.

7. Codex review — round 1 (verification)

CONFIRMED: the log pattern counts (189 / 119 / 23), the fan-out with no single-flight (RC2), the dead token-B failover (RC4), and the mistimed warm-all (RC5).

CORRECTED: RC3 — .op-cache is a fresh-op-binary copy, not a secret store; the real secret caches are three (Keychain fleetcred, .vault-cache, ~/.secrets/cache), and cred-cache-lib already shares the fleetcred Keychain. Plan tier is UNVERIFIED — whoami can't prove it. RC6 is narrower than stated.

ADDED: the recovery stampede (op-reset-detector), vault-get's double-call on miss, the item::field cache-key vault collision, and several uncached direct-op callers (MCP wrappers, vault-load, send-chat.sh).

8. Codex review — round 2 (adversarial attack on the game plans)

Codex attacked the plans and changed the headline. The big correction: a tier upgrade is headroom, not a guarantee. The guarantee is the circuit-breaker + single-flight + killing the retry multiplier.

The hit that matters: "Business = never again" is false

Codex built the worst-case spike from real config. The retry amplifier is the killer: dead token-B (×2 attempts) × op_retry wrapper (×3) = ×6 on every call. A cold-start storm of ~223 live reads then becomes ~1,338 requests in one hour; if it repeats every 5 minutes during op-binary / auth churn, ~16,000/hr — which blows past even Business's 10,000/hr-per-token limit. So buying Business does not, by itself, make this never-again. De-amplifying (kill the ×6) + a circuit breaker is what makes it never-again.

Other confirmed holes

Infisical, attacked

Codex's verdict (agrees with the recommendation, sharpens it): Keep 1Password, fix the architecture, upgrade to Business only as headroom. The single highest-leverage fix: one global live-op circuit breaker + single-flight — on the first 429, write a shared "capped-until" flag, serve stale/cache-only everywhere, and allow exactly one governed refresh path. "Anything else is decorating the blast crater."

9. Recommended path

  1. Confirm the plan tier in the 1Password UI (5 minutes) — decides everything downstream.
  2. Ship the one highest-leverage fix first: a global live-op circuit breaker + single-flight. On the first 429, write a shared "capped-until" flag, serve stale/cache-only everywhere, and allow exactly one governed refresh path. This single change kills the stampede, the ×6 retry multiplication, and the warm-in-storm fan-out at once — with no new infrastructure. Then complete the rest of the architecture fix (unify caches, vault-aware cache key, 429-safe retry incl. the unit test, kill the recovery stampede, one health-gated warm, wrap the remaining direct-op callers). Mostly code we own; low-risk and reversible.
  3. Upgrade to 1Password Business (Plan A) as headroom insurance, not the fix — 300–1000× daily headroom on top of the de-amplified architecture. Cheapest durable path, no migration, fits budget.
  4. Hold Infisical (Plan B) in reserve — only pull the trigger if we decide we want to own a self-hosted, no-ceiling secrets layer and accept the ops burden.