Header now ingests X accounts. Paste x.com/naval into your sources (or click the extension on any tweet), and that account's posts start flowing into your briefings next to your RSS feeds, YouTube channels, and subreddits.

We ingest original posts only. No retweets, no replies. If you follow someone for their thinking, you want the twelve posts they wrote this week, not the two hundred they amplified.

X sources are Pro-only, and the reason is on the invoice: the X API bills $0.005 per post read, so every fetch costs real money. That constraint turned out to be the most interesting engineering of the feature.

When reads cost money, caching stops being an optimization

Our other ingestors treat fetching as free. RSS is a GET request; you can poll it every hour forever and nobody bills you. The X API charges per post returned, which changes what the architecture has to guarantee: never fetch the same post twice, for anyone.

Two decisions fell out of that. The timeline cache is keyed by account, not by source, so when two users both follow @naval, the second user's briefings read posts the first user's fetch already paid for. And fetches are deltas: X post IDs are snowflakes, so we ask the API only for posts newer than the newest one we've cached. A refresh when nothing new was posted returns zero posts, and zero posts cost zero dollars.

Below that listing layer, everything is the pipeline we already had: the same raw-content cache as RSS entries, the same preprocessing cache, the same briefing generator. The only X-specific code decides what to fetch.

The blended result is roughly fifty cents per tracked account per month. Building and verifying the whole feature against the live API cost about thirty cents.

The bug where every tool tells you the config is fine

Beta rollout produced the best bug of the week. The X bearer token worked locally, worked from a shell on the beta box, and returned 401 from the web workers. Config store, generated config file, piku run on the server: all showed the correct value, byte for byte.

/proc/<pid>/environ of the running worker told a different story. Our deploy stack passes env vars through a uWSGI ini file, uWSGI treats % in ini values as its own variable syntax, and X bearer tokens are URL-encoded. The token was being corrupted at the last possible layer, in the one process type that serves traffic, invisible to every inspection tool above it. We now store the token base64-encoded and decode it in code.

Lessons

Per-request billing is an architectural input. We designed the cache layers before writing the ingestor, because "how much does a refresh cost" had to be a property of the system, not a behavior we hoped for. If reads had been free we would have shipped something simpler and wastier and never known.

Verify against the real thing before believing your own code. The ingestor was written from API docs; before calling it done, we ran one real fetch against the live API. That certainty cost two cents.

Trust /proc, not the config store. Four tools showed us a correct token while production served a corrupted one. The environment of the running worker is the only ground truth. The trap is now written into the repo's agent memory, so the next session that touches deploy env vars inherits the scar tissue without the evening we spent earning it.

Add your first X account from your sources page, or install the extension (v0.1.1, shipped today) and click it on a tweet.