The moment that matters most in Patron is the one right after you tap stop. A stylist finishing a balayage, a nail tech setting the last gem, a lash artist peeling off the tape — they want the notes for that appointment now, in the breath before the next client sits down. So the question that quietly governs the whole capture pipeline is: how long is that wait?

Early on, the answer depended on a thing it absolutely should not have depended on: how long the appointment was. A quick fifteen-minute fill returned notes almost instantly. A three-hour color correction made you wait. The more involved the service — the kind most worth remembering — the longer you stared at a spinner. The wait scaled with the session, and it scaled the wrong way.

Why the wait grew

The naïve shape of an audio-notes pipeline is to do everything after the stop:

  1. You tap stop.
  2. The app uploads the whole recording.
  3. The server transcribes the whole recording.
  4. It turns the transcript into notes.

Steps 2 and 3 are the problem. The time to upload and the time to transcribe both scale with the length of the audio. A three-hour session has three hours of audio to push and process — all of it queued up after the stop, while a real person waits. When we measured it, the time from stop to notes-ready was linear in session length: every extra minute you recorded added a roughly fixed chunk of waiting at the end. Short sessions felt instant. Long sessions felt broken.

The appointments most worth remembering were the ones that made you wait the longest. The cost was highest exactly where the value was.

The move: do the work while there's still work happening

Here's the realization that reframes the whole thing. At the moment you stop, almost all of that audio already existed — minutes, even hours ago. We were waiting until the end to process something that had been sitting there, finished, the entire time. There was no reason the transcription had to wait for the stop. It only had to wait for the audio, and the audio arrives continuously.

So we moved it. The recording is now also written as a stream of small sealed segments that upload during the session. As enough of them accumulate into a chunk, the server transcribes that chunk in the background, while the appointment is still going. By the time you tap stop, the only audio left to transcribe is the short tail you just recorded. Everything before it is already done.

STOP BEFORE Recording Transcribe the entire session Notes ready wait after Stop — grows with the session → AFTER transcribed as you go ↑ tail short & flat — any length
Before: all transcription happens after Stop, so the wait grows with the session. After: chunks are transcribed during the recording, so at Stop only a short tail remains — and the wait barely moves no matter how long you record.

The part we're quietly proud of

The elegant bit isn't the streaming. It's that we didn't have to build a second brain for it. We already had machinery that transcribes long sessions in chunks and resumes from a checkpoint — built originally so that a crash or a dropped connection halfway through a long appointment could pick up where it left off instead of starting over.

Mid-session transcription writes into that exact same checkpoint. So at stop, the normal stop-time transcriber does what it always did: load the checkpoint, skip everything already marked done, transcribe only what's left. It has no idea some of those chunks were finished an hour ago, mid-appointment, instead of two seconds ago after a crash. To the pipeline, doing the work early and recovering from a crash are the same shape — and so the speedup rode in on code that was already tested and trusted, with almost no new surface to break.

The before / after

The headline result: the time from stop to notes went from linear in session length to roughly flat. The transcription you pay for at stop is now bounded by the tiny tail, not by the whole recording. Concretely, on a representative half-hour session the post-stop wait dropped by more than 60% — and crucially, the win widens with length, because the old path kept growing and the new one doesn't.

A few specifics that fell out of it:

New speed, old safety net

One principle made all of this shippable without fear: fallback-first. The proven, boring path — do it all at stop — stays fully intact in the code and reachable at runtime. Every new piece of the streaming path degrades onto it automatically. A segment fails to upload? A chunk won't assemble cleanly? The encoder won't initialize on some device? The session silently falls back to the old way of doing things, drops a breadcrumb in our telemetry so we can see it happened, and the user gets a complete, correct session — just at the old speed.

You never get a broken result because the fast path hiccuped. The worst case is the previous best case. That's the trade we want every time: the optimization is allowed to fail, but it is never allowed to take correctness down with it.

The lesson

When a wait scales with the size of the input, the instinct is to reach for a faster engine. Usually the better move is to stop measuring from the wrong moment. The transcription wasn't slow — it was just all stacked up at the end, where someone was standing there waiting for it. The fix wasn't to make the work faster. It was to move the work earlier, into the minutes when the person is still busy and isn't waiting on anything at all.

The stylist is mid-foil. The phone is mid-transcribe. They finish together — and the notes are there the instant the work is done, whether that work took fifteen minutes or three hours.

More from the team → Patron Engineering. Related: never losing a second of that audio in the first place. Building Patron with us? Get in touch.