Embracing the 3-Month Rule: A Practical Approach to Building Without Over-Engineering
In the startup world, the advice from Paul Graham to “do things that don’t scale” is often echoed, but few delve into practical implementations, especially in the realm of coding. After eight months of developing my AI podcasting platform, I’ve established a straightforward framework: any unscalable solution is given just three months to prove its value. If it doesn’t, it’s time for a reevaluation or removal.
As developers, we’re frequently conditioned to create scalable solutions from the outset. This usually manifests in complex architectures—think microservices, distributed systems, and intricate design patterns—all designed for maximum user load. However, in the initial stages of a startup, these scalable solutions can often lead to delays and inefficiencies. They can become a costly form of procrastination, wasting time on optimization for potential users that don’t yet exist.
My 3-month rule helps me focus on writing straightforward, sometimes “messy,” code that I can deploy quickly. This approach allows me to gather real user feedback and understand their needs more effectively. Here are some of the current “hacks” I’ve implemented, and the rationale behind them:
1. Consolidated Infrastructure on a Single VM
Currently, my entire setup—database, web server, background jobs, and Redis—operates on one $40/month virtual machine. While this decision lacks redundancy and relies on manual backups, the benefits have been enlightening. In just a couple of months, I’ve gained insights that no capacity planning document could provide. For instance, I’ve learned that my resource peak only reaches 4GB of RAM, indicating that an elaborate Kubernetes architecture would have been wasted effort. Each time the system crashes (which has happened twice), I gather concrete information about the failure points—often surprising.
2. Hardcoded Configuration Values
Instead of utilizing configuration files or environment variables, I’ve opted for hardcoded constants scattered throughout the codebase, such as:
python
PRICE_TIER_1 = 9.99
PRICE_TIER_2 = 19.99
MAX_USERS = 100
AI_MODEL = "gpt-4"
This method allows for quick searches across the entire codebase and keeps a clear record of any changes in version control. While building a dedicated configuration service may seem ideal, the reality is that I’ve only required changes in these values three times over three months
One Comment
This is a fantastic practical approach that champions the principle of “getting things done” over over-engineering from the start. The 3-month rule provides a disciplined framework for testing assumptions quickly and learning from real-world use, which is crucial in early-stage startups.
Your example of consolidating everything on a single VM resonates strongly—often, the cost and complexity of elaborate architectures obscure valuable insights that come from simplicity. Embracing “messy” and straightforward code early on allows teams to iterate rapidly and focus on validating core hypotheses.
I also appreciate your perspective on hardcoded values. While typically discouraged in production environments, they can be incredibly effective for rapid experimentation and learning, especially when change frequency is low. It’s a reminder that context matters—what’s “best practice” in mature systems isn’t always optimal for early-phase development.
Overall, your framework encourages developers and founders to prioritize learning and validation over premature scalability, which can lead to more resilient, user-driven products in the long run. Thanks for sharing this insightful take!