Typescript (nodejs) backends are not performant, and your ultra modern stack is going to just cause you issues going forward if you need to scale. Prisma is really bad too, slow queries and no flexibility. If you ever need to do any sort of complex query you will just have to write sql anyway. And typescript is only sort of static typing.
These technologies are great for prototyping and building a v1 release to see if what you're trying to achieve is actually possible, but you will regret it later on.
The reason I know this, I work at a startup where we literally had the same backend stack and its been nothing but preformance issue after preformance issue. And it all needs to be replaced. We would have been better off building everything with go/rust in the first place. Or even java.
1. I agree, Prisma is not a great ORM. Drizzle is a better choice. It's close to the metal and when the abstraction inevitably leaks, it leaks towards the user using raw SQL
2. Modern JS is extremely performant. Look at any of the benchmarks for the new JS runtimes that have come out in the past 6 months (e.g. Bun / WinterJS / etc...). It approaches Go / Java in terms of performance.
3. Even the traditional NodeJS runtime has been optimized out the ass by Google. For example: JSON parsing has highly performant SIMD instructions under the hood. When a trillion dollar company puts billions of dollars behind a technology it will get fast.
4. There is no possible way that building your CRUD backend in Golang / Rust is a "faster" solution than just using React Server Components.
5. The vast majority of startups are IO-bound, not CPU-bound - so "fast" languages like Go / Rust won't be as relevant.
The benefits of Go (for most companies) only apply once your company hits an inflection point and starts to scale and starts to see the throughput that can really take advantage of a lower-level language.
If you're building a high-throughput infra company or something, then the things I've mentioned are less relevant.
>> 2. Modern JS is extremely performant. Look at any of the benchmarks for the new JS runtimes that have come out in the past 6 months (e.g. Bun / WinterJS / etc...). It approaches Go / Java in terms of performance.
I like JS but lets not blow smoke up anyones ass here. Your not picking node or its faster safer cousin bun for server speed. You're picking it because you can keep your engineering overhead to a smaller number. Your picking it because you need to generate pages out of your SPA like app.
> 4. There is no possible way that building your CRUD backend in Golang / Rust is a "faster" solution than just using React Server Components.
Spend a month with SQLC and writing blood and guts API's in go. Your gonna realize that the slight slow down in finishing the feature code is more than made up for in finishing testing, ease of deployment and a million other things that you skip by NOT using a JS backend.
>> The benefits of Go (for most companies) only apply once your company hits an inflection point and starts to scale and starts to see the throughput that can really take advantage of a lower-level language.
This is some holdover thinking from PHP vs JAVA days that isnt true when comparing node/ruby to go/rust ... Im going to leave python out because you may have OTHER reasons (existing bindings to C ...) to head in that direction.
>> If you're building a high-throughput infra company or something, then the things I've mentioned are less relevant.
Maybe this is true. But I worry about the long term stability and paintability of anything written in JS. So much flavor of the month and then poof, off to the next thing, it IS a concern.
I only use TS on the frontend, so less opinionated about some of this.
I’d love to see some of the codebases where people complain about performance so I could profile them myself. Would put money on being able to improve the situation by orders of magnitude without switching stack.
We use Python on the backend of our web app for realtime image recognition and it’s fine because we’ve been thoughtful about data structures and algorithms.
Node.js backend performance is comparable to Java. Perhaps you had bad developers - trust me, if they screwed it up so bad they wouldn't be able to make your Java backend any faster, and probably couldn't get Go or Rust to work at all.
Go is perhaps the simplest language to learn there is. It's almost impossible to not get it to work because it has so few things you can actually do.
And nodejs only preforms well in hello world benchmarks, real world applications are nothing like that. Once you start having to manipulate large arrays or do any large amount of math nodejs preformance goes into the dumpster.
Many companies are not throttled by server language performance. Performance in many cases will depend on your database, geolocation, and caching techniques over nodejs vs go. Nothing wrong with prioritizing developer experience.
This sounds weird to me. What kind of scale / traffic did you have? Must be incredible read write heavy with millions of users?
I'm saying this because i myself have, and lots i know, have launched production sites with 100s of thousands of users on ready-made stacks like, Laravel, Rails, Flask (Php, Ruby, Python). But it's my impression that these fall short on millions of users and enormous concurrent traffic, but then you're already at huge evaluation, years into your project, or have 200+ positions, ie. you've already refactored your project multiple times.
That's why you shouldn't use slow backend technologies in the first place because you get to the point where you need preformance and it's impossible because your limited by extremely slow runtime you chose initially because it was flashy (not even easier to developer for) when you could have just chosen something better from the start.
Simple crud apps can get by fine with those technologies, but in the future I'd still never use it because you're leaving huge amounts of performance gains on the table for virtually no benefit. I don't buy the argument that javascript is just easier to develop for because it's simply not. The js ecosystem is a disaster.
I just built an app with Rust and Svelte with ~25k LoC, the app was solid, and working on it was a joy. New team lead got hired, wasn't familiar with Rust, said we'd have trouble hiring Rust devs, and threw it all out. We're now building a Python / ReactJS app from scratch.
Speak to your academic friends for advice on how to get him fired. Do this ASAP for the sake of the company and do not drop the ball once he’s gone. You may have to step into his role
For what it’s worth, I’d be much more interested in working for your company using Rust and Svelte compared to python and react.
If you need someone with experience working with Rust and Svelte, I’m looking for work and value making quality decisions like you did. Now you can point to at least one dev who has the skills your team lead was concerned about finding.
I’m not partial to Node.js backends for many reasons, primary being that I prefer batteries-included web frameworks and the choices are very limited in the JS backend world… But I have such a hard time believing that Node.js is inherently non-performant when there are so many counter-examples of large scale applications that do just fine on it. I understand that the single-threaded nature of JS can be a bottleneck for certain workloads, but without further explanation I’m going to concur with others and say that reading your comment, it’s hard to discard you guys made a mess on your own... Which at least in my experience often comes down to how difficult it is to build in Node.js precisely because of how “minimalistic” and “unopinionated” everything tends to be… You’d better know what you’re doing when there’s no prescription or standardized way for anything from queuing systems, to ORMs, file organization and architecture, concurrency outside of web requests and CRUD, etc.
> But I have such a hard time believing that Node.js is inherently non-performant when there are so many counter-examples of large scale applications that do just fine on it.
Like LinkedIn! Except that to make it performant they had to horizontally scale and then restart the server every N hours when they ran out of memory…
Sounds like the issue wasn't the performance of TS per se, but rather the use of some ORM led to inefficient database queries being executed. This sort of screwup is possible in all languages.
typescript compiles to javascript and you run javascript with deno, nodejs or whatever javascript server you choose. Typescript helps while you develop, but at the end is just javascript.
i don't agree at all. nodejs backends are as performant as you build them. the whole premise of node was async io, so if you're doing a bunch of blocking stuff then yeah, you're going to have issues. otherwise there's nothing innately non-performant about the platform.
it's impossible to debate more without going into details on your performance issues. typical backend architecture for any platform these days is the scalable container model, if you wanted scale-to-zero i wouldn't necessarily use node because of cold starts.
prisma can be great, can be slower than writing your own query, but that's the whole point of it. most of the time, it works and you can forget about queries and typings. when it doesn't, you can just eject to raw sql anytime you want.
i'm not a total nodejs fanboy, and have used more jvm (java/kotlin/scala) in my life, but if i was building a web-app today i'd absolutely consider node for all the reasons the author listed
Nodejs backends are not "as performant as you build them" nodejs is slow! This is an undeniable fact. If you ever have to do anything computationally intensive, which every backend at some point will nodejs will become the bottleneck.
"In many ways, I think I picked a great stack to move quickly and ship things. However, considering all the time spent debugging some of issues that stemmed from using more cutting edge infra providers, next time I'll more carefully consider setting up parts of my infra with a more traditional solution like AWS."
It really depends on which parts of AWS you're using. Spinning up a bunch of EC2 instances and treating them like colo'ed servers has pretty much always been boring (other than the excitement of not having drive to the DC when you need to reboot something).
Tend to agree, though I don't always practice it. Boring is also subjective, even if it's a metaphor for mature.
The same sort of arguments could be said for "choose what you know", "choose what you understand", "choose what you can hire for", "choose what you can afford".. the list goes on.
Like most things in life there are no cheat codes.
This article doesn't really help me choose and based on the title I expected it would. I don't think OP made a "hype" driven decision, but this is certainly one of the most popular modern stacks and what I would like to see instead is a comparison between the popular and less popular options and why OP chose exactly this stack.
My bias was always to err on the side of popularity. I thought that I would be less likely to encounter frustrating bugs and edge cases using choices that have been battle tested for a least a few years.
What I overlooked is that while the platform might be popular and mostly trustworthy (such as Vercel), there are specific solutions like the Vercel Cron Job are still relatively new (released Feb 2023) and still not ready for serious use.
Why does 'modern' nowadays mean 'host everything on managed services' like Vercel or Netlify? Why is running your own database so frowned upon? Is *SQL/SQLite so insecure that a default password-protected setup can be pwned within minutes?
Managed hosting can give you a head start, but also increased costs. There are quite a few horror stories when it comes to billing.
> Why is running your own database so frowned upon?
It's a meme that running your own DB means that you'll get owned within seconds of going live, or lose all your data in the first day because fires in your data center are a daily occurence :-/.
It's the modern equivalent of "MongoDB is Web Scale".
> Managed hosting can give you a head start, but also increased costs.
Yeah ... buuuuuuut ... it's a very tiny head start.
Sure, you may save a few hours by using a hosted postgres service, but you save that only once over the entire lifetime of the database server!
IOW, if you set up a PostgreSQL server on a couple of cheap VPS instances, you can continue using that server for each new product until you hit performance/security problems.
I've got exactly one PostgreSQL server set up, and all my little experiments happen on that one server, with me creating new databases as and when needed.
A true background job would be impossible with this stack. Because I was on the Pro plan, in theory I could set the serverless function timeout to 900s.
Definitely would reach for remix before next, and I would go with a big cloud provider container app solution such as Azure container apps (if azure was better) or Google Cloud Run (good, but do you trust google?) before Vercel.
Personally I think ORMs are mostly bad and Prisma is more of the same. Zapatos at least gives you typed SQL results without a lot of overhead.
Next is buggy, Remix mostly just works, and I have zero interest in Vercel which is the Next selling point IMO.
I haven't played with either Drizzle or Kysely, looking at the docs Drizzle in particular looks slimmer and more sql-like which is a plus, though in general I think having an environment like dbeaver or data grip that gives you completions for your queries and developing them there then copy/pasting the code and getting type safety on raw queries with zapatos is still superior for power users who know sql.
These technologies are great for prototyping and building a v1 release to see if what you're trying to achieve is actually possible, but you will regret it later on.
The reason I know this, I work at a startup where we literally had the same backend stack and its been nothing but preformance issue after preformance issue. And it all needs to be replaced. We would have been better off building everything with go/rust in the first place. Or even java.
1. I agree, Prisma is not a great ORM. Drizzle is a better choice. It's close to the metal and when the abstraction inevitably leaks, it leaks towards the user using raw SQL
2. Modern JS is extremely performant. Look at any of the benchmarks for the new JS runtimes that have come out in the past 6 months (e.g. Bun / WinterJS / etc...). It approaches Go / Java in terms of performance.
3. Even the traditional NodeJS runtime has been optimized out the ass by Google. For example: JSON parsing has highly performant SIMD instructions under the hood. When a trillion dollar company puts billions of dollars behind a technology it will get fast.
4. There is no possible way that building your CRUD backend in Golang / Rust is a "faster" solution than just using React Server Components.
5. The vast majority of startups are IO-bound, not CPU-bound - so "fast" languages like Go / Rust won't be as relevant.
The benefits of Go (for most companies) only apply once your company hits an inflection point and starts to scale and starts to see the throughput that can really take advantage of a lower-level language.
If you're building a high-throughput infra company or something, then the things I've mentioned are less relevant.
https://www.techempower.com/benchmarks/#hw=ph&test=composite...
I like JS but lets not blow smoke up anyones ass here. Your not picking node or its faster safer cousin bun for server speed. You're picking it because you can keep your engineering overhead to a smaller number. Your picking it because you need to generate pages out of your SPA like app.
> 4. There is no possible way that building your CRUD backend in Golang / Rust is a "faster" solution than just using React Server Components.
Spend a month with SQLC and writing blood and guts API's in go. Your gonna realize that the slight slow down in finishing the feature code is more than made up for in finishing testing, ease of deployment and a million other things that you skip by NOT using a JS backend.
>> The benefits of Go (for most companies) only apply once your company hits an inflection point and starts to scale and starts to see the throughput that can really take advantage of a lower-level language.
This is some holdover thinking from PHP vs JAVA days that isnt true when comparing node/ruby to go/rust ... Im going to leave python out because you may have OTHER reasons (existing bindings to C ...) to head in that direction.
>> If you're building a high-throughput infra company or something, then the things I've mentioned are less relevant.
Maybe this is true. But I worry about the long term stability and paintability of anything written in JS. So much flavor of the month and then poof, off to the next thing, it IS a concern.
I’d love to see some of the codebases where people complain about performance so I could profile them myself. Would put money on being able to improve the situation by orders of magnitude without switching stack.
We use Python on the backend of our web app for realtime image recognition and it’s fine because we’ve been thoughtful about data structures and algorithms.
And nodejs only preforms well in hello world benchmarks, real world applications are nothing like that. Once you start having to manipulate large arrays or do any large amount of math nodejs preformance goes into the dumpster.
I'm saying this because i myself have, and lots i know, have launched production sites with 100s of thousands of users on ready-made stacks like, Laravel, Rails, Flask (Php, Ruby, Python). But it's my impression that these fall short on millions of users and enormous concurrent traffic, but then you're already at huge evaluation, years into your project, or have 200+ positions, ie. you've already refactored your project multiple times.
Simple crud apps can get by fine with those technologies, but in the future I'd still never use it because you're leaving huge amounts of performance gains on the table for virtually no benefit. I don't buy the argument that javascript is just easier to develop for because it's simply not. The js ecosystem is a disaster.
If you need someone with experience working with Rust and Svelte, I’m looking for work and value making quality decisions like you did. Now you can point to at least one dev who has the skills your team lead was concerned about finding.
Depending on the company you work for, this was probably a good call on their part.
Application servers should scale out, sure you might need a few more for Node than Rust, but is that really where the issue lies?
You wouldn't implement Postgres, Ceph, QEMU or the kernel in Node... But the CRUD part of most applications will be fine in "any slow language"
Like LinkedIn! Except that to make it performant they had to horizontally scale and then restart the server every N hours when they ran out of memory…
Deleted Comment
Can you elaborate on this?
it's impossible to debate more without going into details on your performance issues. typical backend architecture for any platform these days is the scalable container model, if you wanted scale-to-zero i wouldn't necessarily use node because of cold starts.
prisma can be great, can be slower than writing your own query, but that's the whole point of it. most of the time, it works and you can forget about queries and typings. when it doesn't, you can just eject to raw sql anytime you want.
i'm not a total nodejs fanboy, and have used more jvm (java/kotlin/scala) in my life, but if i was building a web-app today i'd absolutely consider node for all the reasons the author listed
That right there is the rationale behind the "Choose Boring Technology" movement: https://boringtechnology.club/
I don't know whether to feel old or cry on my dedicated servers.
The same sort of arguments could be said for "choose what you know", "choose what you understand", "choose what you can hire for", "choose what you can afford".. the list goes on.
Like most things in life there are no cheat codes.
What I overlooked is that while the platform might be popular and mostly trustworthy (such as Vercel), there are specific solutions like the Vercel Cron Job are still relatively new (released Feb 2023) and still not ready for serious use.
Managed hosting can give you a head start, but also increased costs. There are quite a few horror stories when it comes to billing.
It's a meme that running your own DB means that you'll get owned within seconds of going live, or lose all your data in the first day because fires in your data center are a daily occurence :-/.
It's the modern equivalent of "MongoDB is Web Scale".
> Managed hosting can give you a head start, but also increased costs.
Yeah ... buuuuuuut ... it's a very tiny head start.
Sure, you may save a few hours by using a hosted postgres service, but you save that only once over the entire lifetime of the database server!
IOW, if you set up a PostgreSQL server on a couple of cheap VPS instances, you can continue using that server for each new product until you hit performance/security problems.
I've got exactly one PostgreSQL server set up, and all my little experiments happen on that one server, with me creating new databases as and when needed.
https://learn.shortruby.com/blog/tech-stack
It is nothing fancy and I say it is biased because I started with what I know. But I tried to get into details about each choice.
Personally I think ORMs are mostly bad and Prisma is more of the same. Zapatos at least gives you typed SQL results without a lot of overhead.
We migrated our main application to Remix and couldn't be happier. The app router stuff is such a mess.
As for the ORM / query building, did you also consider Drizzle and Kysely against Zapatos?
I haven't played with either Drizzle or Kysely, looking at the docs Drizzle in particular looks slimmer and more sql-like which is a plus, though in general I think having an environment like dbeaver or data grip that gives you completions for your queries and developing them there then copy/pasting the code and getting type safety on raw queries with zapatos is still superior for power users who know sql.