Yeah, tech stacks are important, but which one is right is so dependent on the specifics of a given project, which is what most of these tech-stack-hype conversations ignore. My small company pays out the ears in so many different ways to run our Python service, but we picked it because certain big companies can use Python at much larger scale than ours. Of course, those companies are mostly just doing CRUD operations to a database and often errors don't matter nearly as much because it's social media or whatever, and also they aren't as cost-sensitive as our business. Instead, we're fighting tooth and nail to keep our requests below a 60s HTTP timeout threshold when they could probably be on the order of a few seconds without optimization if we used a more performant application language like Java, C#, or Go (although the first two might involve some tradeoff on developer productivity; Go would probably improve developer productivity and it would certainly be a significant improvement to the tooling/deployment/etc story).
I'd argue that tech stacks are unimportant 99% of the time. It really doesn't matter if you use Java or PHP or Python or Node.
Failures that I have seen due to the choice of tech stack include:
- Technologies that your team doesn't know well
- Technologies where hiring is difficult (I've seen attempts to turn C# devs into F# devs and Java devs into Clojure devs and productivity suffered)
- Choosing the flavor of the week, whether that's the hottest Javascript framework or newest NoSQL database
- Over-architecting thinking you were Google-scale with the added complexity hurting velocity (it doesn't matter if you can scale to millions of users if you can't get there)
Generally boring tech stacks work. By the time your Ruby/MySQL monolith has performance issues, hopefully you're successful enough that you can scale out the worst performing parts in some other language/datastore combination. You'll be in a better position to fix performance problems are when you have them rather then when you are trying to predict them up front.
> I'd argue that tech stacks are unimportant 99% of the time.
I think this is true if your product is so wildly profitable that differences in tech stack are relatively unimportant--use whatever lets you move the fastest and just solve performance problems by scaling vertically or horizontally. If your business is cost-sensitive and your cloud-bill is a significant portion of your expense, then tech stack starts to matter a lot. Further, your tech stack doesn't matter very much when you're just writing a CRUD webapp--you can use whichever stack and you won't run into issues unless you're massively successful; however, if your app involves a lot of data crunching per request, the stack and architecture matter a lot more (you might have to do more than naive vertical scaling to meet performance requirements). Note that I'm a big proponent of "boring", but "boring stacks work" is orthogonal to "tech stacks don't matter [much]".
Maybe these cases are really only 1% of cases, I'm not sure--there are a lot of CRUD webapps out there, so maybe this is true. But it's not much of a consolation when your use case is one of those 1%.
If your app involves a lot of data crunching and that crunching is the bottleneck, then it makes sense to optimize that part.
It's better to have something slow and correct to optimize, so writing it first time round in a slower language isn't a bad thing.
Secondly, shunting work out of your app is easier now than it's ever been. Enqueue and process in a serverless way. Then you can write whatever code that makes most sense for that problem.
> It's better to have something slow and correct to optimize, so writing it first time round in a slower language isn't a bad thing.
It's better to have something that's fast and correct the first time. Rewrites are typically prohibitively expensive, and we're not getting anything from using a slow language (negligible productivity gains vs Go, for example). Moreover, there isn't much room to optimize with Python for many applications--you can't always subprocess or rewrite in C because the de/serialization costs will eat any savings from parallelism or C. Not to mention increased complexity.
Big bang rewrites are (and, moreover, tend to lose correctness from the source), Ship of Theseus ones are not and do not have that tendency. If you can do component-wise replacement, then fast-to-develop and correct but suboptimal performance is a better deal than anything which trades off either of the others for performance.
It's feasible, but it's still very costly. And again, there's no reason to pick a language that is going to force you to do a rewrite (incremental or not) when there are languages that offer good performance and good iteration velocity.
In practice 'good iteration velocity' is often dependent on using a language/stack that you and/or your team is comfortable with and proficient in.
When one can choose between multiple equally-mastered stacks, then choosing the most appropriate/performant one is perhaps a good choice. But even then there are other things to consider.
For example, I worked for a startup where my ideal choice would've been a performant stack that I'm pretty good with (Elixir/Phoenix), but we ended up going for Python/Django because the founders felt that 1) it would be easier to find more programmers locally, and 2) apparently some investors do care about this. Both seemed like valid reasons to me.
> In practice 'good iteration velocity' is often dependent on using a language/stack that you and/or your team is comfortable with and proficient in.
This is true, but some stacks impose such a high cost that the costs exceed gains from familiarity. Basically you need to evaluate the savings of switching to a better stack and how long it's going to take before that savings equals the cost of switching to the new, less-familiar stack. For greenfield projects, the cost of switching is just the opportunity cost of slower initial development velocity while the team learns the new stack; for existing projects, there may also be the cost of rewriting in the new stack, which quickly becomes prohibitive.
Every maintained project is a continuous Ship of Theseus rewrite, but yes, if there's a language your team is more productive at writing correct code in and that provides better performance, there's an easy choice to make. That's very often not the case, though, and as well as team it's often project scale dependent, and projects often start at a scale where the calculus is very different from where it might be years down the road.
Startups are most likely to fail for either never existing or crashing after take off. Founders mistake the first for an engineering problem and the second for a culture problem. Engineers are smart, if they can write a server in Python they can write a server in Go. Don't waste millions on maintaining an awkward stack for anything but first principles engineering decisions.
> like Java, C#, or Go (although the first two might involve some tradeoff on developer productivity
When I first learned Java I though like this. I liked Python, Perl and even PHP.
Then after reluctantly joining a Java team I learned to like it.
Next I realized how much I actually missed from Java every time I went back to work on a hobby project. Having a
Still for a couple of years other languages still seemed to have an advantage when it came to bootstrapping something, but today? With Quarkus reloads are as fast as in PHP. Things just work and are maintained by grown-ups. If you cannot pair program, the compiler will still have your back.
I'd recommend everyone to look outside the box once in a while: if you use Java, try Rails. If you use Python, try Asp.Net or Java (Quarkus or JavaEE or something). Etc.
At least I feel I have learned a lot from being forced through this process.
I'm sure a proficient Java dev can be very productive, but it would take quite a lot longer to turn a Python dev into a productive Java dev than into a productive Go dev. I don't think this is controversial, but it's not really relevant to my point either way.
> but it would take quite a lot longer to turn a Python dev into a productive Java dev than into a productive Go dev.
I'm really not sure about that. That said it seems you don't really want to discuss this further which is totally OK with me :-)
For others who wonder, my points are only that:
- I was a person who was strongly opinionated against Java and for Python and basically everything else (at that point I had been programming on and off for 10 years)
- Actually becoming productive with Java took a week and the big thing was culture.
If you’re interested in talking through this and are considering C#, you’re welcome to email me and bounce around some ideas. I have a lot of experience in both Python and C# and may be able to help!