RawData

The hardest part of an ephemeral video is deciding what "leaving" means

A video that deletes when the viewer leaves sounds simple, until a refresh, a cancelled prompt, and a Wi-Fi blip all look like goodbye.

BoomerClip makes one promise: the recording is deleted when the viewer is done watching. Funny enough, deciding to post this blog was bitter sweet.

"When the viewer is done" turns out to be a surprisingly slippery idea. A browser doesn't send a tidy "I'm finished" message. It sends a scatter of events, and several of them mean nothing of the sort.

When I got BoomerClip running again after a year away, manual testing turned up regressions in exactly this part of the app: the viewing flow that decides when a recording gets deleted. Fixing it took a full session, and it changed how I think about the whole feature.

Problem one: a refresh looks like a goodbye

From the server's point of view, a refresh is indistinguishable from leaving. The socket disconnects and the page unloads. So refreshing a recording deletes it, which is correct by the rules, but far too easy to do by reflex.

The fix was to ask first. F5, Ctrl+R and Cmd+R now open a "Refresh and delete this recording?" dialog, with Keep watching as the default button, so a reflexive Enter keeps the video. The browser's own refresh button and closing the tab can't be intercepted by a page's dialog, so those get the browser's built-in "Leave site?" prompt instead.

Problem two: "Cancel" deleted it anyway

That's where the second bug was hiding.

The old code told the server the viewer was leaving the moment the "Leave site?" prompt appeared. But the prompt has a Cancel button. A viewer could press Cancel, stay on the page, keep watching... and find the video already deleted underneath them.

The fix was to move the signal to the right moment. The server now hears about a leave on pagehide, which only fires after the viewer has actually confirmed and the page is really going away. Opening the prompt means nothing, and confirming it is what counts.

Problem three: Wi-Fi isn't intent

While I was in there, a related case came up: what if the connection just drops? A laptop goes to sleep, the train goes into a tunnel, the router hiccups.

Before, any disconnect deleted the recording immediately. A two-second network blip and the video was gone.

Now an unexplained disconnect starts a 15-second grace period. If the viewer reconnects inside it, the timer is cancelled and they keep watching. A confirmed leave, the pagehide case, still deletes at once. The difference is between the viewer telling us they're leaving, and us guessing.

Two smaller bugs made reconnecting unreliable, and had to go too:

Problem four: a pause that looked like a crash

One more, on the player itself. If play() was interrupted, say by a pause or a source change before playback began, the browser rejects the promise with an AbortError. That's normal and harmless. But the player treated it as fatal and replaced the whole video with an error screen. It now ignores that specific case.

Putting it where it belongs

The viewing logic had been scattered across effects inside one large component. It now lives in a single useViewingSession hook that owns the socket and the leave guards, so the rules about what counts as leaving live in one place. The server side tracks the viewers of each recording as a set, validates recording IDs when a viewer joins, and logs why each disconnect happened, so the next time a recording vanishes unexpectedly, the reason is in the log.

The lesson

All of these fixes make the browser better at saying goodbye at the right time. But the code review that followed made the uncomfortable point: the browser shouldn't be the one keeping the promise. A client can be closed without firing any event, can be modified, or can fetch the video in ways that never go through the viewing page at all.

So the piece of work BoomerClip is on now is making deletion a guarantee the server enforces, whatever the browser does. The viewing page's job is to be polite about it, and the server's job is to make sure it happens.

Seen once, then gone should be a fact, not a courtesy.

~ Jer