Hacker News new | past | comments | ask | show | jobs | submit login

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.




I'm fairly opinionated about this:

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.

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 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.


>> We use Python on the backend of our web app for realtime image recognition

I have no qualms with python. But Python is the high fructose corn syrup of programing languages... It's in everything.

It's dead easy to write out c bindings so from ML to Math to big data tasks it forms the glue to a lot of things.

My question is: is your real time image processing IN python or in C that python calls out to?


There’s numpy in the middle, so bits are outside python. The vast majority of the code is Python though and the performance gains come from being strategic about the architecture.

My point is that for most usecases you can go a lot further by looking at the code that’s running rather than the language that’s running it.


I think python have the best libraries you can buy, and that makes python a very strong choice if you do not suffer the NIH syndrom or do not need extremely fast code (python is fast enough now).

One big issue i have though: the lack of easy multithreading reduce your possibilities, or at least limit your creativity: you will often choose to use async/await (and sometimes use signals) rather than use producer-consumer designs, which are often the optimal solutions.


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.


> Once you start having to manipulate large arrays or do any large amount of math nodejs preformance goes into the dumpster.

We’re talking about web applications, no? You probably shouldn’t be manipulating large arrays or doing large amounts of math directly in your web application server. That should be isolated in some type of service or worker, which could be written in another language. Or maybe there’s a NumPy-like package for Node.js, I haven’t looked.

The question then is where do you draw that line of using another language? It probably depends on your application, but I think Node.js is perfectly suitable for typical web applications backends.


Any large query result in a large array, so I would disagree on that point. Web apps deal with fairly big data structures, if nothing due to orms.


Can you give an example? I just think that no matter what programming language or framework you're using, if you are querying for giant arrays through an ORM and passing them through an API result to a web app, it's going to be slow.

There are other kinds of solutions for this problem like breaking up the data into chunks and only returning the necessary data. Maybe it's a DB optimization where you can add indexes. Or caching the result of your ORM query.

I've never seen any web app written with any tech that was snappy while making requests for large amounts of data and waiting for it to come back in one big honkin array.

> Web apps deal with fairly big data structures, if nothing due to orms.

Perhaps due to using ORMs unnecessarily and/or inefficiently and failing to drop down to SQL when needed.


It's hard to think about an example, this is very application specific. But there are background jobs and that's where a big array could be manipulated


Probably still need to stream or chunk the data instead of dealing with giant arrays to get decent performance. That's not a language/platform issue.

I recently had to process and aggregate metrics for 5 million rows of user data (a few GBs) on my MacBook with Node.js. By streaming / iterating over the items without loading them all at once it chewed through them all in a few seconds. ¯\_(ツ)_/¯ And it's single-threaded (except for I/O offloaded to threads -- I'm talking about the calculations).


I have never seen a glorified CRUD backend suffering from array or math operations. What kind of backend are we talking about?


You're going to teach your developers? Because I just couldn't find enough Golang devs around. Node.js is well known.


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.


I do agree with this, but I'd argue the developer experience of nodejs with Typescript is far worse than that of rust/go


React Server Components is the best possible DX for a react backend


Agree. JS/TS is not a good environment for large software projects maintained over a long period of time. I'm not 100% convinced Rust is either, yet. cargo seems to be a dumpster fire. Build tools generate TB of mystery disk bloat. Obsession with async... hopefully these issues can be resolved.


> Build tools generate TB of mystery disk bloat.

No, it's not TB, it's a few GB for small projects, and tens of GB for large projects. Rarely does a project ever get over 30-40GB.

> Obsession with async...

If you're going to want any amount of decent performance, you're going to have to deal with async. That's just the nature of IO bound applications.


> JS/TS is not a good environment for large software projects maintained over a long period of time.

VSCode disagrees with you. Its codebase is fascinating btw.


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.


Making stuff faster is relatively straightforward engineering. Optimisation is a favored past time of many engineers.

Getting stuff that people value enough to pay for, to make money, is the hard part.

Any friction you put into the value creation process because "optimizing for future problems" is just doing it wrong.


What kind of application are you talking about? I agree to a degree but we haven't run into performance issues with say 100k users, what traffic did you handle, what was the business case?

Again sounds like you are running some complex math heavy operation like say a weather service, national taxi service with lots of pathfinding, a global gaming platform etc?

Curious to know what exactly you are talking about here? Because normally you just outsource the "heavy stuff" to some remote API, service, etc. you can write in a hyper efficient language anyway.


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.


> New team lead got hired, wasn't familiar with Rust, said we'd have trouble hiring Rust devs, and threw it all out.

Depending on the company you work for, this was probably a good call on their part.


Sounds like you're experiencing BAS, Bad Architecture Syndrome.

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"


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 is only sort of static typing

Can you elaborate on this?


It's progressively typed because it has to coexist with untyped Javascript code and libraries.


Sure, but you can enable TypeScript options and institute lint rules prohibiting use of untyped code.


i love typescript, but that's still not the same as static typing. imagine a full stack typescript app with a blog type

type Blog = { name: string }

everything works fine until you decide to refactor "name" to title. you update the backend and typescript code and deploy the change

type Blog = { title: string }

user john never closes his browser and leaves your website open. he clicks on a new blog post. his client typescript expects a name, the server gives a title, and crash, "Cannot read properties of undefined".

i still choose nodejs backends, but you obviously have to keep in mind it's not statically typed. same with "any", my coworker could take my blog and modify it. it's preventable, but with large teams and codebases still prone to error.

(blog as any).title = { summary: 'blah', full: 'blah blah blah' }


TypeScript is definitely statically typed. It is not a 100% “sound” type system, but very few languages actually are (Haskell, Reason, etc)

And in your example of loading data from a server, if you have appropriate lint rules set up your editor and linter will warn you when you pass “any” typed data (such as that returned by fetch’s response.json()) to something expecting another type. You can use something like zod or yup to validate the data is the type you expect before passing it the rest of your typed code, thereby containing possible type errors to a known location where you can gracefully handle it.

This is a problem with any language that accepts typed data from an external system, certainly not unique to TypeScript.


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.


The type any exists. The type unknown exists. The types actually have no meaning at runtime.


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.


‘nodejs is slow’ isn’t engineering.

‘nodejs is too slow’ is high school level backward rationalization.

‘nodejs is too slow for my use case’ is getting there.

Most stuff we engineer maxes out the database way way waaaay before it saturates its CPU capacity regardless of the language used. You’d better know very well that you’ll be vulnerable to this as a business, otherwise your inefficient competitors will take your money faster than you can build value.


Nodejs is slooooooooooooooooooooooooooooow. [0]

[0] - https://www.techempower.com/benchmarks/#hw=ph&test=composite...


What do you think about how well uWebSockets.js performed in the TechEmpower benchmark? Just js is admittedly experimental, but it has the fourth highest score, and the highest score of any non-Rust framework as well which I found interesting. Elysia (a Bun framework) did pretty well too.

Deno would have probably scored well too (it uses Rust's Hyper crate under the hood), but they're only running a single instance of the server despite Deno supporting the Linux SO_REUSEPORT socket option, which is important because the test is run on three servers with Intel Xeon Gold 5120 Processors that have 14 cores and 28 hyperthreads [0].

[0] https://github.com/TechEmpower/FrameworkBenchmarks/tree/9f0c...


Just go to its repo https://github.com/uNetworking/uWebSockets.js and see the uWebSockets submodule dependency that it's written in C++ (90.9%) and C (6.8%)...so sure, a "fair" comparison indeed with vanilla implementation!


Ok...Node is itself written in C++. The V8 and JavaScriptCore JS engines have no concept of a server (they were designed for web browsers), so under the hood JS runtimes implement servers in a lower level language capable of interfacing with Linux syscalls. Bun uses Zig, Deno uses Rust, Node uses C++, etc. I don't think that necessarily makes this an unfair comparison. The database drivers used in these benchmarks are also usually written in C++. Look at the repo for the native Postgres binding for Node: https://github.com/brianc/node-libpq


Generally anyone that references performance/bottlenecks without data, they’re just parroting their bias. This post is “nu uh!”, but with more words.


I repeat

> 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.


It's as fast or even faster than Java that you mentioned. In my experience, comparable to Golang.


I would not use prisma for anything until they fix https://github.com/prisma/prisma/discussions/12715


I wouldn't use find commands beyond the simplest Join. The beauty of Prisma is raw queries, because they're compiled and type-checked against your Entities. That's the whole appeal, IMHO.




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: