I’ve been wanting to build something with SQLite in production for a while now, ever since the conversation around it shifted from “SQLite is a toy database for local development” to “SQLite is a legitimate choice for production if your architecture fits.” The problem was finding a project that actually fit those constraints. Most of the applications I build for work need to scale horizontally, which rules out SQLite’s single-writer model. But for a side project that processes images and doesn’t need multiple application servers writing concurrently? Perfect fit.
The project itself is straightforward: Digital Passport Photo Online takes a photo you upload, automatically crops and resizes it to meet official passport photo requirements for different countries, and lets you download the result. No accounts, no payment, no tracking—just a simple tool that does one thing. The kind of utility that should exist but often doesn’t because there’s no obvious business model. I built it partly because I needed passport photos for my kids and was annoyed at how much photo services charge for what’s essentially automated image processing, and partly because it gave me a concrete reason to try technologies I’d been reading about but hadn’t used in practice.
SQLite with LiteStack turned out to be exactly as simple as advertised. The entire database is a single file that lives on the server, backed up to S3 every few hours. No connection pooling to configure, no replication to set up, no separate database server to maintain. The application and its data are deployed together as a single unit, which makes deployment trivially simple. There’s a mental shift required if you’re used to Postgres or MySQL—you can’t just throw more database servers at scaling problems—but for an application that’s mostly CPU-bound from image processing, the database is never the bottleneck anyway. The clarity of having fewer moving parts was worth more than the theoretical ability to scale the database separately from the application.
Hotwire Streams handled the real-time updates without needing WebSockets or a separate message queue. When a user uploads a photo, the server processes it and streams the result back as it becomes available, updating different parts of the page progressively. This is one of those features that feels like it should be complicated but Hotwire makes straightforward—you’re just sending HTML over the wire, not managing client-side state or coordinating updates between frontend and backend. The user experience is smooth because the page updates feel instant, but the implementation is simpler than equivalent approaches using JavaScript frameworks.
The deployment tool, Kamal 2, was the real revelation. I’ve been deploying Rails apps for years using a combination of Capistrano, Docker, and various hosting platforms, and it’s always involved more configuration than felt necessary. Kamal reduces the entire deployment to a single command that builds a Docker image, pushes it to a registry, pulls it on the target server, and swaps traffic over with zero downtime. The configuration file is maybe fifty lines of YAML, most of which is just specifying the server address and which Docker image to use. I deployed the entire application to a $5/month VPS, including SSL certificates via Let’s Encrypt, in less time than it usually takes to configure a traditional deployment pipeline.
What made this project valuable wasn’t the application itself—passport photo processing isn’t a novel problem. It was the excuse to combine three technologies I’d been curious about and see how they worked together in practice. Reading documentation and tutorials only gets you so far. You don’t really understand the trade-offs until you’ve deployed something real and watched how it behaves under actual usage. SQLite’s simplicity, Hotwire’s progressive enhancement approach, and Kamal’s opinionated deployment process all align around the same philosophy: you don’t need complex infrastructure if you’re solving a problem that doesn’t require it. The application serves thousands of photo conversions per week from a single server, costs almost nothing to run, and requires basically no maintenance. That’s the kind of efficiency you get when the architecture matches the problem.
P.S. The site is now closed due to Google Nano Banana 😉