Decision framework for making technical decisions at a growing startup. Here are some situations that I’ve encountered and put some thought into.
Different growth stages.
Startup Engineering Growth Stages
On Demand.
You don’t have to come up with the final system design on the first try. In this case, it’s preferred if you build out the simple version of the system first, you can always extend on the system on demand (when you actually receive the business request, or when your systems aren’t holding up). However, there is a core difference between this and the MVP stage. There’s a tradeoff to be made with building things incrementally and finding yourself in a situation where you’re in a deep hole. The rule of thumb is just to come up with a good extensible design that allows you to iterate and change / scale individual components. Build for now, but plan for later.
Making a decision on tech that you don’t have experience in.
For me, this area is currently and mobile development and building out data infrastructure. You can’t make decisions without talking to people. Videos and articles are not enough. You have to talk to different people a lot for you to get a better understanding. For me, that was talking to team members, external industry experts, and even interview candidates.
How important is stack language / framework homogeneity?
The more homogenous it already, the more important it is. If you already have a next.js app and a node.js backend, you should choose react native for your mobile app.
Focus on the certain, not the uncertain.
Thing change rapidly, especially at a startup. There’s little utility in trying to predict future business requirements and traffic patterns. Instead you should focus on things that are certain and will never change:
- Software design principles like modularity, extensibility, Domain Driven Designs, data layer separation etc. will not change regardless of your product. You can never go wrong with building a modular backend service with domain driven design principles, e.g. https://github.com/rarescrisan/typescript-api-service.
- Current industry best practices. E.g. designing your backend services to be stateless to allow easy horizontal scaling. Referencing existing system designs for your own software, hard to go wrong if you just follow what the other companies are doing that has proven to work.
- There was something else on my mind, I forgot when I was writing another section.
Vendor lock in.
You should consider vendor lock-in to a certain extent. E.g. I prefer Kubernetes over ECS (though I am also a fan of the technology myself). I prefer to go heavier with client side rendering over SSR / ISR / SSG etc. to prevent lock-in to the triangle company.
Favor newer technology.
This somewhat goes against Choose Boring Technology and reflects only my personal opinions. I chose to favor new technology and not use older technologies like Java or AWS Redshift. Instead I consider using newer things like node typescript as the backend or clickhouse cloud. I don’t see enough node backends out there.
Promote good design principles via the setup.
Good boilerplate / guardrail / framework setup can promote good design principles. This is part of the reason for choosing a frontend backend separation. If you are working with a full stack framework with TRPC on top that abstracts away the rpc, it’s harder to strengthen concepts like modularity, reusability, and even safety. One can argue that good designs can still be done in a full stack framework with enough setup & developer education, but I prefer to go with a frontend backend separation in growth stage 2 to promote good design principles that can go a long way.
Serverless Companies.
Many serverless companies scale terribly, On Serverless Providers (WIP) discusses more about this. E.g. the triangle company charges loads of money for bandwidth and execution hours. The exception I’ve noticed recently are serverless database companies, pricing wise they compete well against cloud providers.
You’re likely overestimating your scale. :)
When you’re building for scale for the first time, it’s easy to overestimate the scale in which you’re operating at. As an example, a Next.js service gets millions of requests per day, and all the individual request logs with all the relevant fields are sent to a log store. My first response to that is: that’s big data :D, but our log volume is just around ~10GB, scale our platform by 10 times and that’s still 100GB, tiny in the eyes of big data. Because of this, there’s no point of building out a complicated ETL pipeline with data transformations until you reach the scale of growth stage 3.
You will rewrite things 6-12 months down the line.
This is why the time horizon for growth stage 2 is 6-12 months. Your product is not stable yet and things will 100% change.
Two way doors.
Don’t put too much thought into decisions that are two way doors. E.g. if you choose bun as your runtime, it’s going to take you max a few days to convert it back to node.js. Put more thought into one way doors, like database designs or choosing frameworks.