VicroCode
Make Code Create Value
VicroCode is a lightweight online platform for publishing, running, sharing, and monetizing code projects. Launch HTML, Python, SQLite, AI agents, management tools, games, and more without server setup.
Please wait while VicroCode loads. You can also explore the AI programming guide
Loading...

AI MARKET GUIDE

Catching zombie sessions before the bill does: a stale-resource reconciler you can actually run

One dev's RealtimeKit billing mess is a blueprint: poll a vendor's API for what it thinks is 'live', log every scan, and hand-correct the drift.

There's a bug class that never shows up in your own logs because it lives entirely inside someone else's system. You migrate off a service, your clients are gone, your dashboards are clean, and the vendor keeps counting you as active. The meter runs on state you can no longer see or touch.

A developer running an open-source WebRTC project hit exactly this with Cloudflare RealtimeKit. I want to walk through what they reported, because the interesting part isn't the video stack or the refund. It's the reconciliation move they made when nothing added up, and how cleanly that move maps to something you can stand up yourself.

What actually happened

The short version, from their write-up: RealtimeKit was in Beta, the pricing page said Beta usage was free, and then a participant-usage charge showed up on the bill. They opened an urgent support case, the cost kept climbing, and rather than wait on an investigation with no ETA, they moved production off RealtimeKit to Cloudflare Serverless SFU over a weekend. After the cutover, production traffic no longer went through RealtimeKit.

The usage kept accruing anyway, roughly $28 to $29 a day.

So they did the thing most people skip: they called the vendor's own API and scanned the entire app's state. The scan came back with 2,440 Meetings and 2,609 Sessions. Every Meeting was INACTIVE, the production clients were long gone, but 12 Sessions were still marked LIVE, holding 10 live participants between them. Some had been hanging for days, the oldest dating back to the start of the month.

Then the arithmetic that made it click: 10 participants × 1,440 minutes × $0.002 came out to $28.80/day, against an actual recorded day of about $28.76. The developer was careful here, and so am I: that's a strong correlation, not proof that those specific stale participants generated the charge. Treat the causal link as unverified. They ended up calling the official active-session/kick-all endpoint themselves to clear the remaining participants, after which the count went to zero.

Cloudflare later confirmed the Beta usage shouldn't have been billed and refunded two invoices, $143.53 and $147.68, for $291.21 total. On the technical side the outcome was murkier: they acknowledged the stale LIVE sessions weren't expected behavior and that a cleanup mechanism hadn't triggered as intended, but a month of engineering review didn't pin down a platform defect or a clear root cause. Take that as the vendor's stated conclusion, not an independently confirmed one.

The reusable idea buried in the incident

Strip away the specifics and you're left with a pattern worth keeping:

A managed service holds state on your behalf. Its idea of what's "live" can drift from reality, and when it does, the drift is invisible to you until it lands on an invoice or a quota. The only reliable way to see it is to ask the service directly, on a schedule, and compare its answer against what you know should be true.

That's three parts. Poll the vendor's own API for its live view. Write every scan to a store you can read and correct by hand. Surface the gap between what should be active and what the vendor still counts. None of that is exotic. The reason people don't have it is that it feels like overhead until the one day it would have saved you a month of back-and-forth.

It generalizes well beyond video. Any usage-metered resource with a lifecycle you don't fully control fits: background jobs, webhook subscriptions, provisioned workers, seats, sessions. If the vendor exposes a "list what's active" call, you can reconcile it.

Building it on confirmed VicroCode capabilities

Here's how I'd assemble a stale-resource reconciler with what the platform actually supports.

The poller is a scheduled Python job. You can run Python online to hit the vendor's list endpoints, normalize the response into rows, and stamp each row with a scan timestamp. Keep it dumb on purpose: fetch, flatten, write. No cleanup logic in the poller itself, because the whole point is to observe before you act.

Each scan lands in a SQLite table, one row per resource per scan, with the vendor's reported status alongside a column for what you believe the status should be. That second column is the hinge of the whole design. Being able to open a SQLite editor and mark a session as "should be dead" by hand is what turns a passive log into a reconciliation record. When the vendor says LIVE and your annotation says dead, that row is drift, and drift is the alert.

The view layer is a small dashboard. You can run HTML online to render the current scan: a count of resources the vendor calls active, how many you've flagged as stale, and the age of the oldest one. In the RealtimeKit case that panel would have shown 12 LIVE sessions against zero legitimate clients, with the oldest reaching back weeks. Seeing that number sit above zero, day after day, is the whole product.

For the parts that need to be callable, API Endpoint Hosting and in-platform tool calls let you expose the reconciler's output as an endpoint another script or a teammate can query, and file management keeps scan exports and credentials organized. If you build it once and it's useful, project publishing and monetization are there if you want to hand it to other operators.

Where the boundary is, honestly

Be clear about what this does and doesn't do. VicroCode can host the poller, the store, and the dashboard. It does not run inside Cloudflare or any other vendor, and it can't reach into a service and change its internal session lifecycle. The reconciler reads the vendor's API and shows you the gap. Acting on the gap, calling something like kick-all, still happens against the vendor's own endpoint, and any destructive cleanup call deserves a human hand on it rather than a blind scheduled trigger. The developer in the source case was actually advised to run kick-all on a schedule and chose not to, partly because engineering wanted the app preserved for investigation. That instinct is right. A tool that force-clears resources on a timer can do real damage if your "should be dead" logic is wrong.

So scope it as an observer first. Detection and an editable record of what's stale is the high-value, low-risk core. Automated remediation is a separate decision you make later, per resource, with eyes open.

Why it's worth the afternoon

The money in the RealtimeKit story came back. What didn't come back was the time: an emergency production migration, a manual review of two thousand-plus sessions, and a support case that dragged for over a month with no incident owner tying billing, product, and engineering together. A standing reconciler wouldn't have fixed the vendor's cleanup gap, but it would have handed the developer the exact evidence, faster, and turned "why is this still charging me?

into a screenshot of drift on day one.

That's the trade I'd take. Good developer experience and mature production operations are two different things, and the seam between them is precisely where a resource you thought you'd killed keeps quietly billing you. A poller, an editable table, and a page that shows the gap is a cheap way to watch that seam.