Case Study: Reframe — Building an AI Shopify App Solo, From First Commit to Paying Merchants

6 min read
Case Study: Reframe — Building an AI Shopify App Solo, From First Commit to Paying Merchants

Most of what I write here is technical guides. This one is different: it’s a case study of Reframe, the AI Shopify app I built solo and still run — what I decided, what those decisions cost, and what came out the other end. If you’re evaluating whether to trust one engineer with a production AI system, this is the evidence. It’s deliberately not a tutorial; it’s about judgment, not implementation steps.

The product and the problem

Shopify merchants — especially dropshippers and small brands — get product photos from suppliers that look like they were taken in a warehouse, because they were. Studio photography is slow and expensive at catalog scale. Reframe turns those supplier photos into studio-quality product images: AI background removal, scene presets, batch processing across a whole catalog.

That one sentence hides the actual difficulty. The hard part of Reframe was never “call an image model.” It was building something a non-technical merchant trusts with their entire catalog, on infrastructure one person can run, at a cost structure that works when the product is priced for small businesses.

The constraints, honestly

Every architecture decision below traces back to four constraints:

  1. One person. I was the product manager, designer, engineer, and on-call rotation. Anything that needed babysitting was a liability, not a feature.
  2. GPU economics. Image models need GPUs; idle GPUs burn money. The workload is bursty — a merchant shows up with 400 photos, then nothing for hours. That rules out reserved GPU capacity and rules in serverless inference, which brings cold starts.
  3. Merchant trust. The customer doesn’t care about my pipeline. They uploaded photos of products they sell, and they need to know — at a glance — what happened to every one of them.
  4. Shopify’s platform. Webhooks, API rate limits, app review requirements, and an embedded-app UX you don’t fully control.

The decisions and what they bought

A deliberately boring core. Reframe is a Remix app on Postgres, deployed with zero-downtime deploys on Dokku on a VPS. Two processes: the web app and a polling worker. No message broker, no Kubernetes, no microservices. People are sometimes surprised that an “AI app” runs on something this plain — but the boring core is why one person can operate it. Every component I didn’t add is a component that has never paged me. The complexity budget was spent where it earns revenue: the pipeline.

Serverless GPUs, with the cold-start tax engineered around. Inference runs on Modal’s serverless GPUs, which solves the economics — I pay for compute when merchants are processing, nothing when they’re not. The cost is cold starts and concurrency limits, so the pipeline is built to hide them: while one batch’s results upload to Shopify, the next batch is already running inference, so the GPU never idles waiting on I/O. Jobs are split across fast and slow queues with independent concurrency limits, so a merchant’s quick single-photo edit never queues behind someone else’s 400-photo catalog run.

Reliability as a product feature, not an ops concern. This is the decision I’d defend hardest. In an AI pipeline, some jobs will fail — models time out, images are weird, third-party APIs hiccup. A solo-operated product can’t promise failures won’t happen, so Reframe is built so failures are never silent and never cost the merchant anything: every job has a clear visible state; failed jobs trigger automatic credit refunds with no support ticket needed; results sit in a 7-day review queue before archival so merchants can always see what happened to every photo and why; and worker-level error monitoring alerts me when something systemic breaks — before the support email arrives. Most days, the system handles its own bad news.

The unglamorous Shopify layer. Billing through Shopify’s subscription APIs, webhooks for the merchant lifecycle (install, uninstall, plan changes), transactional and lifecycle email via Resend. None of it is interesting to read about, all of it decides whether an app survives on the App Store.

Iterating with evidence instead of opinions

Shipping was the halfway point. What moved the business was treating product iteration as an engineering discipline:

  • Session recordings over speculation. I used PostHog recordings to watch where merchants actually dropped off in onboarding — not where I assumed they did — and reworked that flow until it clicked. Churn fell.
  • Model quality as a tracked metric. Merchants accept or reject each generated image; I track acceptance rates per model. When a model underperforms, that’s data, and it feeds straight into which models run in which presets.
  • Usage-triggered outreach. Automated emails keyed to what a merchant has and hasn’t done in the app, monitored against churn until the numbers improved.

The pattern across all three: instrument first, then change things, then check the metric moved. The same loop I’d run on a client’s system.

Where it is now

Reframe is live on the Shopify App Store, revenue-generating, and processing thousands of merchant photos a month. It runs day to day without me in the loop — the worker retries what’s retryable, refunds what isn’t, and alerts me only for the genuinely new failure modes. It was built from first commit to first paying merchant by one person, and the operational design is the reason that’s sustainable rather than heroic.

There’s also a by-product: the tooling I built for image-model workflows became modl (no relation to Modal above — it’s my own open-source LoRA training and generation toolkit).

What this means if you’re hiring me

The transferable thing here isn’t the Shopify or the image models — it’s the shape of the work. Scope decided against real constraints; a system sized to the team that has to run it; reliability the customer can see; iteration driven by instrumentation rather than taste. That’s the same judgment I bring to a client’s billing system, search infrastructure, or AI pipeline.

If you want a production system built — or rescued — by someone who has run one with their own money on the line, let’s work together.

Related Articles

AI Engineering 13 min read
Automating E-Commerce Photography with AI

Automating E-Commerce Photography with AI

Why generative image editing failed for product photos, and the multi-model architecture that actually works — covering GPU deployment, cold starts, and the Build vs. Buy tradeoff.

AI Engineering 8 min read
Durable LLM Agent Workflows on SQLite — and the Exact Line Where You Graduate to Temporal

Durable Agent Workflows on SQLite — Until You Need Temporal

Multi-step LLM agents fail halfway, wait on slow tools, and pause for human approval — so they need durable execution. The reflex is to reach for Temporal or Inngest on day one. I built crash-safe, resumable, human-pausable LLM workflows in ~200 lines on plain SQLite, then measured exactly where it runs out: a hard crash mid-run replays the finished steps and saves half the tokens, and the durable write ceiling is a flat ~1,000 steps/sec — far more than any LLM workflow needs. The honest conclusion: you graduate for architecture, not throughput.

AI Engineering 11 min read
One Day of LLM Agent Observability: Five Production Bugs, Three JSONL Files

One Day of Agent Observability: Five Bugs Found

I gave my kids' book agent proper logging in a morning — three plain files — and spent the afternoon fixing what the logs immediately caught: 73% of GPU time wasted, books in the wrong language, and two ways the model broke its own tool calls. Real numbers, same-day payback.

AI Engineering 11 min read
Do You Need a Glean? I Self-Hosted Onyx and Rebuilt It on Postgres — Same Corpus, Same Local LLM

Do You Need a Glean? Onyx vs 80 Lines of Postgres

The enterprise-knowledge-search question is really build-vs-buy: pay for Glean, self-host the open-source Onyx, or build RAG on the Postgres you already run. Instead of a feature table, I stood up the full Onyx platform AND wrote the entire Postgres alternative in ~80 lines, pointed both at the same local Qwen 27B over the same company knowledge base, and asked the same questions. Both gave accurate, cited answers. The difference isn't quality — it's eleven containers and a connector marketplace versus one container and a prompt you own. Here's how to choose.