The 3-Month Experiment: A Practical Approach to Unscalable Coding
In the startup community, Paul Graham’s mantra of “Do things that don’t scale” resonates widely, yet the practical application of this philosophy in software development is often overlooked. After eight months of building my AI podcast platform, I’ve designed a straightforward methodology: any unscalable solution receives a trial period of three months. At the end of that duration, we evaluate its effectiveness. If it proves valuable, we refine it; if not, it’s discarded.
As software engineers, our instinct is to focus on scalable architectures right from the start—think design patterns, microservices, and robust systems that can accommodate millions of users. While this approach is valid, especially for mature companies, it can lead to unnecessary complications for startups. Pursuing scalability prematurely can often result in a complex and expensive procrastination, addressing hypothetical user needs rather than actual ones.
My three-month strategy encourages me to create straightforward and even “imperfect” code that delivers results and reveals user behaviors.
Current Infrastructure Strategies: Smart Choices in Simplicity
1. Consolidated Operations on a Single VM
I’ve streamlined everything onto a single $40/month virtual machine—this includes the database, web server, background jobs, and caching. While this setup lacks redundancy, it has provided invaluable insights into my usage requirements. Through two crashes, I’ve gathered real-time data on actual system failures, which has highlighted unexpected weaknesses and taught me about my resource demands. The complex Kubernetes infrastructure I considered implementing would have likely resulted in empty resources.
2. Hardcoded Configuration Management
Constants like PRICE_TIER_1 = 9.99
and MAX_USERS = 100
are embedded directly in my codebase, eliminating the need for configuration files. This approach may seem rudimentary, but it allows me to track changes efficiently. With just a simple command, I can search my entire code for configuration values, track price alterations in git history, and ensure every update undergoes a review process, albeit self-imposed. Investing a week to create a configuration service was unnecessary; I’ve only modified these constants three times in the last three months, saving a tremendous amount of engineering effort.
3. Using SQLite for Production Needs
Believe it or not, I’m relying on SQLite for my multi-user application. With a compact 47MB database, it comfortably manages 50 concurrent users. This has taught me that my access patterns are predominantly