Embracing the 3-Month Rule: A Practical Approach to Unscalable Solutions
In the tech world, Paul Graham’s mantra of “do things that don’t scale” is widely recognized, yet few delve into the specifics of its implementation, especially in software development. As I continue to build my AI podcast platform over the past eight months, I’ve established an effective framework to navigate this concept: every unscalable workaround I deploy has a lifespan of exactly three months. At the end of that period, I evaluate its effectiveness for potential further development or decide its fate.
It’s common for engineers to focus on scalable solutions from the outset—design patterns, microservices, distributed systems—essentially constructing grand architectures meant for massive user bases. However, in the startup environment, prioritizing scalability often leads us down the path of costly procrastination, as we’re trying to optimize for hypothetical users and address issues that may not even arise. My 3-month rule encourages me to create simple, straightforward solutions that can be quickly launched while providing invaluable insights into what users truly need.
Current Infrastructure Hacks: Strategic Decisions with Purpose
1. One Virtual Machine for Everything
I run my entire stack—database, web server, background jobs, and Redis—on a singular $40/month virtual machine. While it lacks redundancy and necessitates manual backups, this setup has afforded me remarkable insights into my real resource requirements within just two months. I discovered that my AI platform reaches peak usage at 4GB of RAM, and the complex Kubernetes system I nearly implemented would have been managing idle containers instead.
Having witnessed system failures (twice so far), I gathered actionable data on what truly breaks—often surprised by the results.
2. Hardcoded Configuration
Every configuration in my code is hardcoded, with no reliance on external config files or environment variables. While this may seem counterintuitive, it allows me to locate any variable across my codebase rapidly. Tracking changes is straightforward through git history, and I’ve only needed to update configuration values three times over the past three months, resulting in a mere 15 minutes of redeployment compared to the potential 40 hours of engineering required for a fully-fledged configuration service.
3. Utilizing SQLite for Production
Currently, I’m employing SQLite for what would typically be a multi-user application. With a database size of just 47MB, it adeptly handles up to 50 concurrent users. This experience has clarified my access patterns—