Ali Gharehgozloo

Case study 01

Subscription streaming platform

Role

Product design
Front-end
Backend
DevOps & on-call

Timeframe

2025 — 2026
Ongoing

Status

Live, commercial
Confidential client
~10k active users
Team of 3 engineers

Stack

Django / DRF · Next.js
PostgreSQL · Redis
Docker Compose · Sentry
Object storage

A paid video service where people subscribe, watch on-demand and live channels, and the business can see exactly where its money comes from. A three-person team designed, built, deployed, and operated it — I owned the scope below end to end.

The client is confidential, so there are no screens and no product name here. Everything below is a decision I made and can talk through in detail.

Context

The client had content and an audience, and no product. What existed was a plan to sell subscriptions and a three-person engineering team — me and two others — with no dedicated designer and no separate infrastructure role, and no budget to hire beyond that.

That constraint shaped every decision that follows. A larger team can afford a service-per-concern architecture and a person who only watches dashboards. Three of us couldn't. Everything I owned had to be simple enough to hold in my head at two in the morning, and defensive enough that the parts nobody was watching couldn't quietly destroy anything.

My role

Across the three of us, I owned the product end to end: interface design, the Next.js front-end, the Django/DRF backend, the payments and subscription logic, the admin panel, deployment, database tuning, backups, monitoring, and incident response.

What I did not own: the content itself, the catalog editorial decisions, and the commercial terms. The client set what was sold and at what price. I built the machine that sold it.

The problem

A subscription platform is not a video player with a paywall. It is three systems that have to agree with each other at all times: who has paid, what they are allowed to watch, and what the business earned. When those three fall out of sync, you do not get a bug report — you get a customer who paid and cannot watch, or revenue you cannot explain.

On top of that, the assets are the business. The video files, the artwork, the catalog metadata: lose them and there is no product to sell. A single person operating a system that holds irreplaceable data has to assume they will one day run the wrong command at the wrong time.

Decisions

Three that mattered more than the rest. Each one has an alternative I rejected, and the annotation in the margin says why.

Decision 01

A deterministic gate in front of every destructive storage operation

Early in the platform's life, an object-storage incident took media offline. I traced it, restored service, and then sat with the more uncomfortable question: the code had done exactly what it was told, and what it was told was wrong. No amount of care on my part would guarantee that never happened again, because the failure mode was a correct-looking instruction issued against the wrong target.

So I stopped treating it as a mistake and treated it as a missing structure. Every operation that can delete or overwrite media now passes through a gate that verifies the target against expected state before anything is touched. If the check does not pass, the operation refuses and reports; it does not proceed and log a warning. The gate is deterministic code, not a convention, not a runbook step, and not a comment asking the next person to be careful.

Alongside it: encrypted off-site backups on a schedule, and a restore I have actually tested rather than assumed.

Decision 02

Rebuilding the catalog tool on structured APIs after a WAF killed the first version

Cataloguing a large library by hand is the kind of work that quietly eats a launch. I built an AI-assisted tool for it: give it a title, it goes and finds the metadata, and an editor confirms. It worked, until the sources it depended on began sitting behind web application firewalls that correctly identified it as automated traffic and blocked it.

The version that shipped works differently. Metadata comes from structured, permitted APIs — stable schemas, predictable fields, no scraping — and the language model is confined to the part it is genuinely good at: reconciling messy titles, filling gaps, and drafting descriptions in the client's voice. Facts come from the API. Prose comes from the model. The two never swap jobs.

It is a smaller tool than the first one, and it has not broken since.

Decision 03

Passwordless sign-in through a messaging bot, with a permanent audit trail

The audience already lived in a messaging app. Asking them to invent a password for one more video service was friction with no upside, and it would have handed us a credential database to protect — the single worst thing a three-person team with no dedicated security function can be responsible for.

Sign-in happens through a bot in the app they already have open. There is no password to forget, reset, or leak. Every authentication event writes to an append-only audit trail, which also turned out to be the thing that makes support answerable: when someone says they were signed out or charged twice, there is a record of what actually happened rather than a guess.

The admin panel is tiered on top of the same identity layer, so a content editor and a finance user see genuinely different systems rather than the same screens with buttons hidden.

What shipped

A live commercial platform, in production and taking payments.

Viewer

Catalog and browse
Custom adaptive video player
Live channel support
Subscription and renewal
Promotions and discount codes

Admin

Tiered role-based panel
Catalog management
AI-assisted metadata tool
Revenue analytics by revenue type
and payer status

Operations

Docker Compose deployment
Tuned database image
Encrypted scheduled backups
Sentry monitoring
N+1 query elimination

Outcome

The platform serves roughly ten thousand active users and has been continuously live since launch. Payments settle in real time, so the client sees revenue as it arrives rather than in a monthly reconciliation, split by revenue type and by payer status.

The storage incident is the honest part of the record. It happened, it was my system, and the fix is structural rather than a promise to be more careful. Since the gate went in, no destructive operation has reached production media.

What I would change

I would have written the safety gate before the incident, not after it. The reasoning that produced it was available on day one; I just had not asked the question yet. On any system where the assets are the business, that check is part of the initial build now.

I would also have instrumented the product properly from the start. I can tell you the platform works; I cannot tell you which part of the catalog retains subscribers, because I did not put the measurement in early enough to have a year of it.

And I built the AI catalog tool against a source I had not verified I was allowed to depend on. Two weeks of work were spent proving a point I could have established in an afternoon by reading the terms.

Next case study

PriceMate

Why a language model is never allowed to decide whether food is safe for someone with an allergy.