Discussion
Java Is Fast. Your Code Might Not Be.
koakuma-chan: As much as I love Java, everybody should just be using Rust. That way you are actually in control, know what's going on, etc. Another reason specifically against Java is that the tooling, both Maven and Gradle, still stucks.
krona: > That way you are actually in controlProgramming in Rust is a constant negotiation with the compiler. That isn't necessarily good or bad but I have far more control in Zig, and flexibility in Java.
bearjaws: JavaScript can be fast too, it's just the ecosystem and decisions devs make that slow it down.Same for Java, I have yet to in my entire career see enterprise Java be performant and not memory intensive.At the end of the day, if you care about performance you will use a language better suited to that.
maccard: My experience with the defaults in JavaScript is that they’re pretty slow. It’s really, really easy to hit the limits of an express app and for those limits to be in your app code. I’ve worked on JVM backed apps and they’re memory hungry (well, they require a reallocation for the JVM) and they’re slow to boot but once they’re going they are absolutely ripping fast and your far more likely to be bottlenecked by your DB long before you need to start doing any horizontal scaling.
kyrra: First request latency also can really suck in Java before hotpathed code gets through the C2 compiler. You can warm up hotpaths by running that code during startup, but it's really annoying having to do that. Using C++, Go, or Rust gets you around that problem without having to jump through the hoops of code path warmup.I wish Java had a proper compiler.
bombcar: Do none of the JVMs do that? GraalVM?
looperhacks: You can create a native executable with GraalVM. Alternatively, if you want to keep the JVM: With the ongoing project Leyden, you can already "pre-train" some parts of the JVM warm-up, with full AoT code compilation coming some time in the future.
jayd16: Not knowing what's going on in Java is a personal problem. The language and jvm have its own quirks but it's no less knowable than any other compiler optimized code. The debugging and introspection tooling in Java is also best in class so I would say it's one of the more understandable run times.Gradle does suck and maven is ok but a bit ugly.
jandrewrogers: You can write many of the bad examples in the article in any language. It is just far more common to see them in Java code than some other languages.Java is only fast-ish even on its best day. The more typical performance is much worse because the culture around the language usually doesn't consider performance or efficiency to be a priority. Historically it was even a bit hostile to it.
this_user: Performance is really not Java's issue. Even bad Java code is still substantially faster than the bulk of modern software that is based on technologies like Python or JavaScript/Node.js.
koakuma-chan: Yes, there is a learning curve to Rust, but once you get proficient, it no longer bothers you. I think this is more good than bad, because, for example, look at Bun, it is written in Zig, it has so many bugs. They had a bug in their filesystem API that freezed your process, and it stayed unfixed for at least half a year after I filed it. Zig is a nice C replacement, but it doesn't have the same correctness guardrails as Rust.
krona: Assuming we're talking about the same bug, The filesystem API freeze wasn't caused by Zig's lack of correctness guarantees, but a design flaw in Bun's implementation.
koakuma-chan: https://github.com/oven-sh/bun/issues/18192I am talking about this bug. It looks like it is still unfixed, in the sense, there is a PR fixing it, but it wasn't merged. LOL.Regardless of whether this specific bug would be caught by Rust compiler, Bun in general is notorious for crashing, just look at how many open issues there are, how many crashes.Not saying that you cannot make a correct program in Zig, but I prefer having checks that Rust compiler does, to not having them.
comrade1234: Also finding the right garbage collector and settings that works best for your project can help a lot.
steve1977: Which, to be fair, in many cases is ok. If you just need to churn out LOB apps for worker drones as cheap as possible, performance is probably not the most important factor.
dryarzeg: Maybe I'm stupid, but I never actually understood people who blame programming languages for bugs in software. Because sure, it's good to have guardrails, but in my opinion, if you're writing a program and there's a bug, unless this bug lies somewhere in implementation of compiler/interpreter/etc, you can't blame the tooling, It's you who introduced this bug. It was your mistake.It's cool when your tooling warns you about potential bugs or mistakes in implementation, but it's still your responsibility to write the correct code. If you pick up a hammer and hit your finger instead of the nail, then in most cases (though not always) it’s your own fault.
belfthrow: I really hate how completely clueless people on hn are about java. This is not, and has not been an issue for many many years in Java and even the most junior of developers know how to avoid it. But oh no, go and rust is alwaayssss the solution sure.
bombcar: Ah, but let's port rust to the JVM!
pjmlp: Rust has no place other than deployment scenarios where any kind of automatic resource management, be it tracing GC or reference counting, is not wanted for, either due to technical reasons, or being a waste of time trying to change people's mindset.
wood_spirit: A subject close to my heart, I write a lot of heavily optimised code including a lot of hot data pipelines in Java. And aside from algorithms, it usually comes down to avoiding memory allocations. I have my go-to zero-alloc grpc and parquet and time libs etc and they make everything fast. It’s mostly how idiomatic Java uses objects for everything that makes it slow overall. But eventually after making a JVM app that keeps data in something like data frames etc and feels a long way from J2EE beans you can finally bump up against the limits that only c/c++/rust/etc can get you past.
taspeotis: Knock KnockWho’s there?long pauseJava
dionian: This is why I use java for long running processes, if i care about a small binary that launches fast, i just use something slower at runtime but faster at startup like python.
packetlost: Python startup time can be pretty abysmal too if you have a lot of imports.
ptx: This is addressed by PEP 810 (explicit lazy imports) in Python 3.15 (currently in alpha): https://peps.python.org/pep-0810/
packetlost: Yeah, but it requires code changes to matter
FatherOfCurses: "Enterprise Java"Factories! Factories everywhere!
wood_spirit: Yes! Obligatory link to the seminal work on the subject:https://gwern.net/doc/cs/2005-09-30-smith-whyihateframeworks...
chuckadams: When millions of users constantly make the same mistake with the tool, there may be a problem with the tool, whether it's a defect in the tool or just that it's inappropriate for the job. Blaming the user might give one a righteous feeling, but decade after decade that approach has failed to actually fix any problems.
titzer: I worked on JVMs long ago (almost twenty years now). At that time most Java usage was for long-running servers. The runtime team staunchly refused to implement AOT caching for as long as possible. This was a huge missed opportunity for Java, as client startup time has always, always, always sucked. Only in the past 3-5 years does it seem like things have started to shift, in part due to the push for Graal native image.I long ago concluded that Java was not a client or systems programming language because of the implementation priorities of the JVM maintainers. Note that I say priorities--they are extremely bright and capable engineers that focus on different use cases, and there isn't much money to be made from a client ecosystem.
pythonaut_16: Can you provide any examples or evidence of Java apps that prove this?Because in my experience as of 2026, Java programs are consistently among the most painful or unpleasant to interact with.
liampulles: Understanding algorithmic complexity (in particular, avoiding rework in loops), is useful in any language, and is sage advice.In practice though, for most enterprise web services, a lot of real world performance comes down to how efficiently you are calling external services (including the database). Just converting a loop of queries into bulk ones can help loads (and then tweaking the query to make good use of indexes, doing upserts, removing unneeded data, etc.)I'm hopeful that improvements in LLMs mean we can ditch ORMs (under the guise that they are quicker to write queries and the inbetween mapping code with) and instead make good use of SQL to harness the powers that modern databases provide.
j-vogel: Author here. DB and external service calls are often the biggest wins, thanks for calling that out.In my demo app, the CPU hotspots were entirely in application code, not I/O wait. And across a fleet, even "smaller" gains in CPU and heap compound into real cost and throughput differences. They're different problems, but your point is valid. Goal here is to get more folks thinking about other aspects of performance especially when the software is running at scale.
cmovq: When you're using a programming language that naturally steers you to write slow code you can't only blame the programmer.I was listening to someone say they write fast code in Java by avoiding allocations with a PoolAllocator that would "cache" small objects with poolAllocator.alloc(), poolAllocator.release(). So just manual memory management with extra steps. At that point why not use a better language for the task?
cogman10: Easy to get wrong as well.There's a balance with a DB. Doing 1 or 2 row queries 1000 times is obviously inefficient, but making a 1M row query can have it's own set of problems all the same (even if you need that 1M).It'll depend on the hardware, but you really want to make sure that anything you do with a DB allows for other instances of your application a chance to also interact with the DB. Nothing worse than finding out the 2 row insert is being blocked by a million row read for 20 seconds.There's also a question of when you should and shouldn't join data. It's not always a black and white "just let the DB handle it". Sometimes the better route to go down is to make 2 queries rather than joining, particularly if it's something where the main table pulls in 1000 rows with only 10 unique rows pulled from the subtable. Of course, this all depends on how wide these things are as well.But 100% agree, ORMs are the worst way to handle all these things. They very rarely do the right thing out of the box and to make them fast you ultimately end up needing to comprehend the SQL they are emitting in the first place and potentially you end up writing custom SQL anyways.