DEV Community

Super Funicular
Super Funicular

Posted on

Build-in-Public, Week 10: Impressions Fell From ~40k/Week to Under 10k — and the Cause Wasn't the Algorithm

There was no Week 8 update. There was no Week 9 either. This post is the explanation, and it doubles as the most useful postmortem this series has produced so far — useful precisely because the cause turned out to be boring.

Quick context for new readers: I build Background Camera RemoteStream, a free Android app that records with the screen off, stores everything locally, and can stream to an unlisted YouTube Live feed — no account, no cloud, no subscription. The marketing for it is an experiment I've been running in public since May: a largely agent-automated content pipeline, built the same way the app was built (75+ Claude Code sessions), publishing daily and reporting real numbers here every week. Week 7 was the last installment. Then the streak broke.

The headline numbers, stated plainly

As of this morning, measured directly against the dev.to API and my internal tracker:

  • 115 articles published on dev.to, 1,641 total views, 7 reactions, 21 comments — all-time
  • Cross-channel impressions (mostly X and Threads, per my internal tracker): a peak of roughly 40k/week in mid-June, falling to under 10k/week by early July — a ~75% drop in about three weeks
  • 22 dev.to articles shipped in the last two weeks — that lane never stopped
  • The 10 pieces published since July 13 have 20 dev.to views between them — feed distribution here remains close to zero; what compounds is search (my all-time top article, a no-subscription listicle, sits at 122 views, nearly all search)

Sit with the tension in those numbers for a second, because it's the whole story: one lane kept shipping daily the entire time, and total reach still collapsed 75%.

The postmortem: output collapse, not audience loss

When the impressions line fell off a cliff, every instinct said algorithm change, shadow throttle, audience gone. The actual diagnosis, once I audited the pipeline end to end, was that the social lane — the one carrying most of the impressions — had quietly stopped publishing for almost three weeks (June 26 to July 15) while the blog lane's daily output masked the silence. Nothing dramatic broke. Several boring things stacked:

  1. The content queue silted up. Roughly 40% of the pending queue was drafted for platforms I couldn't actually post to anymore (deprecated formats, channels without working auth, one platform that needs an account type I don't have). The generator refused to make new content while the queue looked "full" — full of unpublishable dead stock. Purging it took the queue from 191 items to 119 and unblocked generation instantly.
  2. The selection bandit was sampling fantasy arms. The picker that decides what to publish next was choosing from a blind cross-product of ~365 platform×format×topic combinations — and about 93% of its draws were unsatisfiable (no inventory, or a platform that was closed). It "ran" every day and published almost nothing. The fix was one embarrassing filter: only sample arms that have pending inventory on a platform that actually works.
  3. The measurement layer undercounted. Manually published pieces weren't being logged to the same table the scorecard reads, so the collapse looked even deeper than it was — which pushed the diagnosis toward "audience loss" instead of "output loss" for longer than it should have.

None of these would have survived a single honest glance at one number: pieces actually published per day, across all lanes. I wasn't tracking it. The lane with a daily human-visible artifact (a blog post I could see) felt like proof the system was healthy. The lane without one failed silently.

The fixes that shipped

  • A hard output floor: ≥8 published pieces per day, total, across all lanes. Not a target — a floor that every publishing task is required to check. It was met for the first time on July 17 (11 pieces). It was missed on July 18 morning (5) because of a tooling outage, which at least proves the floor is now measured.
  • Dead-stock purge + honest platform list. Content only gets generated for channels that verifiably work today.
  • The bandit filter described above.
  • One ledger. Every publish — automated or manual — writes to the same log the scorecard reads. If it isn't logged, it didn't happen.

The Week 10–12 experiment: two always-on native lanes

The restoration plan I'm testing for the next two weeks is a two-live-lanes cadence: the dev.to canonical article every day (this lane), plus a native LinkedIn post at least 5 of every 7 days — with X and Threads volume layered on top rather than treated as the foundation.

Why LinkedIn gets promoted to a lane of its own: back in Week 3, the same piece of content did 34 impressions as a native LinkedIn post on a 4-follower account and 0 Day-1 views as a dev.to post. That ratio has held directionally ever since — native text on LinkedIn gets distributed to strangers; dev.to's feed gives me almost nothing, but its articles keep paying search rent for months. So: LinkedIn for reach-now, dev.to for reach-later, and neither lane is allowed to go dark silently again.

Targets on the record, so future-me can be graded: 25k impressions/week by July 31, 100k/week by August 31. Those are recovery targets, not projections — Week 13's post will report the real line.

What's still honestly not working

  • 7 reactions across 115 articles. dev.to's feed has never adopted this catalog, and ten pieces in five days earning 20 combined views says it still hasn't.
  • Bluesky: 22 followers, zero engagement. Parked.
  • The app's Play Store listing converts around 5.5% over a trailing 7 days (early-July measurement) — decent for cold traffic, but the input volume is the bottleneck, which is the entire point of this postmortem.

Three takeaways if you're running your own pipeline

Instrument output before you diagnose audience. A reach collapse has two possible causes, and only one of them is fashionable to blame. Check "did I actually ship?" first — per lane, not in aggregate.

Floors beat goals for systems that run without you. A goal fails silently; a floor that must be checked every run fails loudly, which is the only useful way to fail.

A healthy-looking lane will hide a dead one. If one channel produces a daily visible artifact and another doesn't, your intuition about "the system is running" is being formed entirely by the visible one.


The app this experiment funds with attention: Background Camera RemoteStream on Google Play — records with the screen off, local-only storage, built-in LAN web viewer, unlisted YouTube Live streaming from anywhere. Free, no account, no cloud. More at superfunicular.com.

Related reading: yesterday's night-before checklist for watching your home while traveling, and the engineering side of this project in Storage, Not Heat, Is the Real Limit on 24/7 Android Recording.

Top comments (4)

Collapse
 
paw_dev6789 profile image
Paw

the missing week 8 and 9 with the honest explanation is more useful to me than the graph going up. i keep wondering how i'll write the weeks where nothing good happened.

Collapse
 
superfunicular profile image
Super Funicular

The down weeks turned out to be easier to write than the up weeks, once I had a rule for them: report the number, name the one thing I think caused it, and label it a guess when it is a guess. Weeks 8 and 9 went missing because I did not have that rule yet and could not make myself type "I don't know." It is a perfectly good sentence, and nobody has ever complained about reading it.

Collapse
 
paw_dev6789 profile image
Paw

"nobody has ever complained about reading it" made me exhale. i've skipped my own down weeks because typing "i don't know" felt like admitting something. turns out it's just a normal sentence.

Thread Thread
 
superfunicular profile image
Super Funicular

That reflex is worth naming, because "I don't know" and "I didn't check" read identically to the writer and completely differently to the reader. The first is a finding. The second is the one worth avoiding — and the fix is small: before you write the week up, spend twenty minutes trying to falsify your best guess about the number. Usually you fail, and then "I don't know" is earned rather than avoided. Occasionally you find the cause, which is how Week 10 happened.

Are you logging the raw weekly numbers somewhere private already, or does the number only get written down when a post gets written?