Compound Labs
Get the newsletter
THE STANDUPAnthropic fixes Claude 5.1 error spikesERROR SPIKES, FIX DEPLOYEDCOMPOUND MASTODONSkillWorks records inactive files beside their roster status22 INACTIVE FILES STILL LOADCTXWINDOWContext Window tracks AI lab changes and filters their evidenceFILTERS KEEP EVIDENCE TOGETHERAGENTWIREmicrosoft/agent-governance-toolkit - AI Agent Governance ToolkitPOLICY ENFORCEMENT FOR AI AGENTSCOMPOUND FACEBOOKCompound Portfolio restores its sweep after a missing module stops desk dataSWEEP RESTORED, DESK DATA WRITTENBLOCKDEXBlockDex shows no destination for captured rows with rejected slash names31 ROWS, NO DESTINATIONCONTEXT WINDOWOpenAI adds 1024p image pricing: $0.50 and $0.251024P IMAGE, $0.50 AND $0.25COMPOUND BLUESKYCompound Labs renamed job labels so job-run finds breaker stateBREAKER STATE, NOW FINDABLECTXWINDOWContext Window tracks document changes but failed mobileMOBILE WORKFLOW, ONE COLUMNAGENTWIREMineDojo Voyager: Open-Ended Embodied AgentOPEN-ENDED EMBODIED AGENTFOUNDER BLUESKYdeploy.sh now fails false Vercel production landingsFALSE LANDINGS NOW FAILCOMPOUNDlast known fixes redirect tracking after migrationSTUDIO SOURCES NOW SAY COMPOUNDCONTEXT WINDOWOpenAI adds sora-2-pro pricing720P VIDEO, $0.15, $0.30FOUNDER LINKEDINdeploy.sh now stops failed promotes from marking production landedFAILED PROMOTES NO LONGER LANDUSINGITUPUsing It Up records a receipt fixing a wobbling wooden tableONE RECEIPT, TABLE STAYED LEVELCOMPOUNDpnpm v12.4.2POSIX BIN SHIMS REPLACEDFOUNDER PEERLISTCompound Labs' deploy runner rejects failed promotesFAILED PROMOTES NO LONGER LANDTRUSTDESKTrustDesk fixes host migration redirects while keeping /api/ outOLD HOST, 308; API STAYS LIVE
Independent product R&D labFounded and run by Isaiah Kim, @kyisaiah47Newest commit Sep 16, 2026, AgentwireNewest writing Sep 16, 2026Site changelog Sep 16, 2026
StackTabAug 21, 20264 min read

StackTab rechecks 64 vendor prices nightly and rewrites none

A price you copied off a vendor's pricing page in July can stop being true in August, and nothing in your spreadsheet will look any different. StackTab records 64 plans across 29 services, covering database, auth, payments and hosting, and every night at 02:20 it reads all of those vendors' pricing pages again to ask one question: are the figures we published still on the page?

The hour is deliberate. Vendors ship pricing changes during their working day, so the small hours are the quietest time to read thirty marketing pages, and it leaves the whole morning for a changed row to be caught before anyone quotes a number off it.

Every price carries the sentence it came from

Each plan in the catalogue stores probes: the literal strings that must still be present on the vendor's own page for that row to count as checked. Supabase Pro carries five. "$25" for the monthly fee, then "$0.00325", "$0.09", "$0.125" and "$0.0213" for the four overage rates it charges on users, egress, database disk and file storage. Across the whole catalogue there are 139 of those strings.

A run sorts every row into one of three states. Verified, every probe found. Drifted, the page read fine and something the row claims is no longer on it. Unreadable, the page would not fetch, or came back with under 500 characters of text.

What the job will not do is rewrite a price. Pulling a fresh number out of a marketing page and trusting it enough to print it as somebody's bill is how a cost calculator ends up lying with confidence. A drifted row keeps its old figure and, more importantly, keeps its old date. That date is the last moment the row was actually true, and the site shows it rather than pretending the number is current.

$25 is inside $250

The check itself is a text match, which is where most of the sharp edges live.

// A plain substring test is wrong for money: "$25" is a substring of "$250",
// so a plan whose price moved from $25 to $250 would still read as verified.
// Any probe ending in a digit therefore has to be followed by something that
// is not a continuation of the number.
export function matchProbe(text, probe) {
  const p = normalise(probe);
  const tail = /\d$/.test(p) ? '(?![\\d]|[.,]\\d)' : '';
  return new RegExp(esc(p) + tail).test(text);
}

Stripping the page down to readable text has the same problem in reverse. The stripper breaks lines on block elements only, and deliberately not on a span, because vendors wrap the digits of a price in their own span to animate them like an odometer. Split on that and "$25 per developer/month", which is exactly the string Clerk's row is checked against, becomes three separate lines and the check fails on a price that never moved. Table cells are out for the same reason one level up: a pricing table row reads as one fact, "Starter $7/month 512 MB", and cutting it per cell breaks anything that spans the row.

Then there is language. A vendor that negotiates language off the request will happily serve a different one to a client that states no preference, and firebase.google.com/pricing has answered with a partly Indonesian render, "GB tersimpan", "GB terdownload". To a text check, a page in another language is indistinguishable from a page whose prices changed. Every request now asks for English, and any page that fails a probe is fetched a second time, uncached, before the row is called drifted at all.

What the stance costs

Three things, and none of them are free.

The nightly job cannot fix anything it finds. A drifted row is a note that a person has to go back to the vendor's page and re-author the entry by hand.

Adding a vendor is more work than typing a number. The deploy refuses to ship if any plan carries a monthly fee that no probe mentions, because a figure no probe mentions is a figure nothing is watching, and it would pass every nightly check clean for ever.

And the calculator sometimes declines to give you a total. Firebase Auth stops at 50,000 users and points at Google Cloud pricing. Auth0's per-user scale lives behind a slider. Stytch's overage rate is only inside its own calculator widget. Those are recorded as unknown, never as zero, so a stack that needs one of them comes back with a blank where the total goes and a line naming the vendor that did not publish.

Which number in your own pricing model came off a page nobody has reread since it was written down?

The rule that generalises off all of this: when you publish a figure you read on someone else's page, store the sentence you read it in, right next to the number. The number on its own can never tell you when it stopped being true.

StackTab is live at stacktab.thecompound.tech.

---

One shipped product, taken apart, once a month. What it does, what it cost to build, what the pipeline behind it looks like, and what the numbers did, read off the repository and the live site, not written from memory. Join the list.

All writing