Skip to content

Writing/AI

Running a long AI job from a phone

Video generation takes minutes, and a phone can be backgrounded, killed or lose signal at any point in them. So the phone cannot be the thing that owns the job.

ISIonuț Sandu30 Jun 2026 · 8 min readAIFirebaseArchitecture

I have been building an app that turns a selfie and a prompt into a short generated video. The generation takes minutes rather than seconds, and in those minutes the phone can be backgrounded, killed by the operating system, put on a train or run out of battery. That single fact decides the whole architecture.

The version that does not work is an HTTP request from the app to a generation endpoint, awaited. It demos perfectly and fails constantly, because the client is the least reliable participant and you have made it the one holding the job.

The database is the job queue

So the client does three things and then stops being important: it uploads the seed frame to storage, it creates a document describing the job, and it subscribes to that document. A backend worker picks the job up, calls the generation provider, and writes progress back to the same document.

“The phone is a subscriber to the job, never its owner. Once that is true, closing the app is not an event worth handling.”

The progress channel is a document subscription rather than polling or a socket, which means reconnection is somebody else's problem. Kill the app mid-generation, reopen it ten minutes later, and the library shows a finished video, because the job never depended on the app being there. No resume logic was written to make that true.

Cancel has to mean refund

Generation costs money per run, so the app meters it. That makes cancellation a financial operation rather than a UI one. A cancel button that only navigates away leaves the worker running, the provider billing, and the user's balance spent on a video they will never see.

So cancelling marks the job cancelled, stops the worker, and returns the credit in the same operation. The rule I would apply anywhere: if starting something spends a resource, the stop path has to be as carefully written as the start path, and it is usually written in half the time.

Anonymous first, and a mock of everything

Two decisions that cost little and paid for themselves. Auth is anonymous first, so somebody can try the thing before being asked to make an account, and the account upgrade preserves the work they already did rather than starting them over.

And the entire generation pipeline has a mock mode behind an environment flag. Interface work, animation timing and every failure state can be built without spending a cent or waiting three minutes for each attempt. On a product whose core action is slow and paid, that is not a developer convenience, it is what makes iterating on the interface possible at all.

Ionuț Sandu — 30 Jun 2026Copy link

NEXT · 29 JUN 2026 · 10 MIN READ

Liquid Glass in React Native

Apple's native effect on iOS 26, a fallback everywhere else, and how to make one component decide which is which.

Taking on new projects

Tell me what you’re building.A written scope and a fixed quote before any money moves.

I reply to everything within one working day. If I’m not the right person for it, I’ll tell you straight away rather than three weeks in.