Something went wrong. Try again.
GET /xrpc/tech.waow.typeahead.searchActors typeahead.waow.tech
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>typeahead — costs</title><meta name="color-scheme" content="dark light"> <meta name="theme-color" content="#0a0b0a" media="(prefers-color-scheme: dark)"> <meta name="theme-color" content="#f2f3ef" media="(prefers-color-scheme: light)"> <script>(function(){try{var t=localStorage.getItem('ta.theme');if(t==='dark'||t==='light')document.documentElement.dataset.theme=t}catch(_){}})()</script><style> :root { --bg: #0a0b0a; --panel: #101211; --panel-2: #161917; --hover: #1a1d1b; --line: #212523; --line-2: #2b302d; --text: #d9dedb; --bright: #f2f5f3; --muted: #8a938e; --dim: #59615c; --faint: #3d423f; --accent: #44aa99; --accent-dim: #2c6e63; --blue: #58a6ff; --violet: #bc8cff; --amber: #e5a04b; --red: #e06c75; --tip-bg: rgba(16, 18, 17, 0.96); color-scheme: dark; } @media (prefers-color-scheme: light) { :root:not([data-theme="dark"]) { --bg: #f2f3ef; --panel: #fafbf8; --panel-2: #eceee8; --hover: #e6e8e2; --line: #d8dbd3; --line-2: #c8ccc3; --text: #2c322e; --bright: #131614; --muted: #5d665f; --dim: #8a938c; --faint: #b4bab2; --accent: #14795f; --accent-dim: #4c9c88; --blue: #2465c2; --violet: #7a4bc9; --amber: #a86a1c; --red: #b13540; --tip-bg: rgba(250, 251, 248, 0.97); color-scheme: light; } } :root[data-theme="light"] { --bg: #f2f3ef; --panel: #fafbf8; --panel-2: #eceee8; --hover: #e6e8e2; --line: #d8dbd3; --line-2: #c8ccc3; --text: #2c322e; --bright: #131614; --muted: #5d665f; --dim: #8a938c; --faint: #b4bab2; --accent: #14795f; --accent-dim: #4c9c88; --blue: #2465c2; --violet: #7a4bc9; --amber: #a86a1c; --red: #b13540; --tip-bg: rgba(250, 251, 248, 0.97); color-scheme: light; } * { margin: 0; padding: 0; box-sizing: border-box; } html { -webkit-text-size-adjust: 100%; } body { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; background: var(--bg); color: var(--text); font-size: 14px; line-height: 1.6; min-height: 100vh; -webkit-tap-highlight-color: transparent; } button, a { touch-action: manipulation; } a:focus-visible, button:focus-visible, [tabindex]:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; } ::selection { background: var(--accent); color: var(--bg); } /* signature: the wordmark carries a live caret — search happens at the caret */ .wordmark { color: var(--bright); font-weight: 700; text-decoration: none; } .wordmark::after { content: ""; display: inline-block; width: 0.5em; height: 1em; margin-left: 0.12em; background: var(--accent); vertical-align: text-bottom; animation: caret-blink 1.1s steps(1) infinite; } @keyframes caret-blink { 50% { opacity: 0; } } /* one caret of attention: while the user holds a real text caret, the wordmark's goes quiet and steady — it hands off rather than compete */ .wordmark.quiet::after { animation: none; opacity: 0.3; } @media (prefers-reduced-motion: reduce) { .wordmark::after { animation: none; } * { transition: none !important; } } .theme-btn { background: none; border: 1px solid var(--line); border-radius: 6px; color: var(--dim); font: inherit; font-size: 0.7rem; padding: 0.3rem 0.6rem; cursor: pointer; min-height: 32px; } .theme-btn:hover { color: var(--muted); border-color: var(--line-2); }
body{padding:1.5rem 1rem 3rem}.container{max-width:760px;margin:auto}header{display:flex;align-items:center;justify-content:space-between;gap:1rem}h1{font-size:1.1rem;font-weight:400;color:var(--muted)}a{color:var(--accent);text-underline-offset:4px}nav{display:flex;gap:1.4rem;margin:1.5rem 0 2rem;font-size:.85rem}nav a{color:var(--muted);text-decoration:none}nav .active{color:var(--bright);border-bottom:2px solid var(--accent);padding-bottom:.3rem}.budget{padding:1.8rem;background:var(--panel);border:1px solid var(--line);border-radius:10px}.eyebrow{font-size:.8rem;color:var(--muted)}.price{display:flex;align-items:baseline;gap:1rem;margin:.7rem 0 .8rem}.price strong{font-size:clamp(4rem,12vw,6rem);font-weight:500;line-height:1;letter-spacing:-.07em;color:var(--bright)}.price span{color:var(--muted)}.scope{font-size:.8rem;color:var(--muted);max-width:62ch}.strip{display:flex;height:13px;border-radius:3px;overflow:hidden;gap:3px;margin:1.7rem 0 1rem}.strip span:nth-child(1){background:var(--accent)}.strip span:nth-child(2){background:var(--blue)}.strip span:nth-child(3){background:var(--violet)}.vendors{display:grid;grid-template-columns:repeat(3,1fr);gap:1rem}.vendor{border:0;background:none;text-align:left;color:var(--text);font:inherit;cursor:pointer;padding:.5rem 0}.vendor strong{display:block;font-size:1.4rem;font-weight:500}.vendor small{font-size:.75rem;color:var(--muted)}.vendor i{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:6px}.note{color:var(--amber);font-size:.75rem;margin-top:1.5rem}.activity{margin:2rem 0}.section-title{font-size:.85rem;font-weight:400;color:var(--muted);margin-bottom:1.1rem}.numbers{display:grid;grid-template-columns:repeat(3,1fr);gap:1.5rem}.numbers strong{display:block;font-size:1.7rem;font-weight:400;color:var(--bright);font-variant-numeric:tabular-nums}.numbers span{font-size:.75rem;color:var(--muted)}.numbers small{display:block;font-size:.7rem;color:var(--dim)}details{border-top:1px solid var(--line);padding:1rem 0}summary{cursor:pointer;color:var(--text);font-size:.85rem}details p{font-size:.8rem;color:var(--muted);margin:.8rem 0;max-width:72ch}table{width:100%;border-collapse:collapse;margin:.8rem 0;font-size:.75rem}td,th{text-align:left;padding:.7rem .4rem;border-bottom:1px solid var(--line);vertical-align:top}th{color:var(--muted);font-weight:400}.footer{font-size:.7rem;color:var(--dim);margin-top:1.5rem}.bar{display:flex;align-items:center;gap:1rem;margin:.9rem 0;font-size:.8rem}.bar .track{flex:1;height:6px;background:var(--panel-2);border-radius:3px}.bar .fill{height:100%;background:var(--accent);border-radius:3px}.bar b{font-weight:400;min-width:4rem;text-align:right}.bar span:first-child{width:7rem;color:var(--muted)}@media(max-width:500px){.budget{padding:1.2rem}.numbers{gap:.7rem}.numbers strong{font-size:1.25rem}.vendor strong{font-size:1.15rem}header{align-items:baseline}.theme-btn{font-size:.65rem}.price{gap:.6rem}}</style></head><body><main class="container"><header><h1><a class="wordmark" href="https://typeahead.waow.tech/">typeahead</a> stats</h1><button class="theme-btn" id="theme-toggle">theme: auto</button></header><nav aria-label="stats"><a href="https://typeahead.waow.tech/stats">traffic</a><span class="active" aria-current="page">costs</span><a href="https://fly-metrics.net/d/typeahead-health/typeahead-c2b7-service-health?orgId=877152">health</a></nav><section class="budget"><p class="eyebrow">monthly cost · attribution in progress</p><div class="price"><strong>~$30</strong><span>/ month identified</span></div><p class="scope">Fly only. Typeahead’s share of shared services is still being calculated; this is not the total operating estimate.</p><div class="vendors"><button class="vendor" data-detail="fly"><small><i style="background:var(--blue)"></i>Fly</small><strong>~$30</strong></button><button class="vendor" data-detail="turso"><small><i style="background:var(--accent)"></i>Turso</small><strong>shared</strong></button><button class="vendor" data-detail="workers"><small><i style="background:var(--violet)"></i>Workers</small><strong>shared</strong></button></div><p class="note">Account subscriptions are not assigned wholly to Typeahead. R2, Logfire, and home power also remain unattributed.</p></section><section class="activity"><h2 class="section-title">what that runs · 24 hours ending Sep 5, 23:00 UTC</h2><div class="numbers"><div><strong>261.2k</strong><span>Worker invocations</span><small>7.84M / 30 days at this rate</small></div><div><strong>17.4 min</strong><span>CPU consumed</span><small>31.27M CPU ms / 30 days</small></div><div><strong>3.70×</strong><span>outbound fetches / invocation</span><small>966.5k fetches in this window</small></div></div></section><details id="turso"><summary>Turso · Typeahead usage within a shared account</summary><p>The $45.40 September invoice covers the whole account, including the standard site index and other services. It is excluded from Typeahead’s estimate until costs are attributed.</p><table><tr><th>Database</th><th>Rows read</th><th>Rows written</th></tr><tr><td>typeahead</td><td>523,390,116</td><td>19,902,224</td></tr><tr><td>leaf</td><td>296,327,134</td><td>480,272</td></tr><tr><td>marvin-threads</td><td>404,071</td><td>0</td></tr><tr><td>foo</td><td>0</td><td>0</td></tr></table><p>Per-database values from the supplied screenshot. Reads and writes are different meters; their shares are not shares of the invoice.</p><p>The earlier 11.3 / 24 GB sync figure is account-wide. We still need per-database storage, sync bytes, billing dates, and overage line items.</p><p>Keep direct overages separate from an explicitly chosen share of the base subscription. Incremental cost asks how much lower the account bill would be without Typeahead; allocated cost also includes a share of the subscription.</p></details><details id="fly"><summary>Fly · current spending rate</summary><p>$6.97 across both apps for Aug 30–Sep 5 × 30 / 7 = $29.87. This window includes architecture changes and may include a partial billing day, so the estimate is approximate.</p><p>Search: 4 shared CPUs, 2 GiB memory, 60 GB volume. Ingester: 1 shared CPU, 256 MiB. The measured spend includes volumes and backups.</p></details><details id="workers"><summary>Workers · usage-based estimate</summary><p>The $5 Standard plan base is shared and is not assigned to Typeahead here. At this day's rate: 7.84M monthly invocations and 31.27M CPU ms. Against an otherwise unused paid allowance, CPU overage would be about $0.03; request usage stays below 10M.</p><p>This is a shared account: other Workers may consume the included usage. KV and observability charges still need attribution. <a href="https://developers.cloudflare.com/workers/platform/pricing/">Pricing and allowances</a>.</p></details><details><summary>engineering opportunities</summary><p>Request accounting currently issues two logical SQL statements for a cached search and four for a successful origin search. Attribute those writes before replacing them with batched counters or Analytics Engine.</p><p>Measure export bytes per build and retry, retained index sizes, and overlay apply time. Rebuild frequency trades export cost against overlay size and search performance.</p></details><details><summary>sources & assumptions</summary><p>Cloudflare GraphQL analytics, Sep 4 23:00–Sep 5 23:00 UTC. Sampled estimates for all Worker routes, including ingestion. Hourly totals reconcile with the full-window query. Traffic and CPU projections multiply that window by 30; they are scenarios, not invoices.</p><p>CPU quantiles: P95 7.71 ms, P99 13.06 ms. Zero reported runtime errors. Invocation wall time includes background work and is not search response latency.</p><p><a href="https://developers.cloudflare.com/workers/observability/metrics-and-analytics/">Cloudflare metric definitions</a> · <a href="https://fly.io/dashboard/nate-nowack/billing/cost-explorer?end_date=2026-09-05&start_date=2026-08-30&view=breakdown">Fly cost explorer</a> · <a href="https://app.turso.tech/">Turso invoices</a></p></details><p class="footer">Preview for /stats/costs · saved measurements · September 5, 2026</p></main><script> (function() { var btn = document.getElementById('theme-toggle'); if (!btn) return; function current() { try { return localStorage.getItem('ta.theme') || 'system'; } catch (_) { return 'system'; } } function label(mode) { return { system: 'theme: auto', dark: 'theme: dark', light: 'theme: light' }[mode]; } function apply(mode) { if (mode === 'dark' || mode === 'light') document.documentElement.dataset.theme = mode; else delete document.documentElement.dataset.theme; btn.textContent = label(mode); } btn.addEventListener('click', function() { var next = { system: 'dark', dark: 'light', light: 'system' }[current()]; try { next === 'system' ? localStorage.removeItem('ta.theme') : localStorage.setItem('ta.theme', next); } catch (_) {} apply(next); }); apply(current()); })();
for (const button of document.querySelectorAll('[data-detail]')) { button.addEventListener('click', () => { const detail = document.getElementById(button.getAttribute('data-detail')); if (detail instanceof HTMLDetailsElement) { detail.open = !detail.open; if (detail.open) detail.scrollIntoView({block:'nearest'}); } });}</script></body></html>