The question comes up at every new project kickoff: "what are we building this in?" More often than not, the answer is driven by what the team already knows, or by whatever is trending on HackerNews this month. Neither is a particularly good method. I've seen a CRM written in Rust because the CTO watched a conference talk, a high-traffic API built in PHP because "that's what we've always done", and a data pipeline in Node.js because the front-end team refused to learn anything else. All three were the wrong call. Here's a more pragmatic framework — no evangelism included.
PHP: misunderstood and underrated
PHP carries a reputation built on the internet of 2005 to 2012. The problem is that its reputation froze in time while the language kept evolving. PHP 8.x ships with optional strong typing, native attributes, named arguments, enums, fibers, and JIT compilation. It's not the same language that made "PHP bad" jokes go viral.
For a classic web application, a REST API, an e-commerce platform, a business application built on Symfony or Laravel — PHP is often the most pragmatic choice available. Hosting is cheap (any shared server runs PHP out of the box), the developer pool is large, documentation is exhaustive, and the ecosystem is mature. A junior dev can be productive on a well-structured Symfony project in two weeks. Try making that claim for Go or Rust.
PHP's real weaknesses are structural: it's single-threaded by nature and not designed for real-time or CPU-intensive workloads. If you need persistent WebSockets, on-the-fly video processing, or an API that needs to handle 50,000 concurrent connections on a single server — PHP is the wrong tool. But for 80% of standard web projects, it's the rational choice that gets dismissed too quickly because it isn't exciting.
JavaScript: the Swiss army knife that doesn't always cut clean
JavaScript is non-negotiable on the front-end — that's not even a question. React, Vue, Svelte, the DOM, Web APIs: all of it runs in JS. The real debate is on the back-end, with Node.js.
The strongest argument for Node.js is code sharing between front-end and back-end. When you're building with Next.js or Nuxt, you write validation logic, types, and utilities once and use them on both sides. That's a real, tangible gain — not marketing. The second argument is serverless: Lambda functions, Vercel, Cloudflare Workers — the whole serverless ecosystem is designed with JavaScript as the first-class citizen.
The dark side: Node.js is still single-threaded from a CPU standpoint. The event loop handles concurrent I/O extremely well, but as soon as something blocks the thread — heavy computation, image processing, compression — everyone waits. And the npm ecosystem, despite years of improvement, remains a minefield: sketchy transitive dependencies, abandoned packages, version incompatibilities. TypeScript significantly improves long-term maintainability, but it's an added layer of complexity on top of an already complex stack.
If your project has no JavaScript front-end, choosing Node.js for the API because "the team knows JS" deserves serious pushback. Familiarity alone is not a good enough reason.
Go: boring, and that's a compliment
Go is probably the language I hear least about in hype-driven conversations, and yet it's the one I reach for most when building things that need to work reliably in production without waking me up at night. That contradiction says something.
Go is boring in the right way: no magic, no ten different ways to write the same thing, no obscure meta-programming. When you come back to Go code six months later, you read it the same way you wrote it. Concurrency is baked into the language through goroutines and channels — not a third-party library, not a pattern you need to remember, it's in the spec. For microservices, high-traffic APIs, CLI tools, and DevOps tooling, Go is hard to beat on the performance-to-code-simplicity ratio.
But honestly: Go is verbose. The repetitive if err != nil error handling is a well-known pain point. The library ecosystem is thinner than Python or JavaScript. And most importantly: for a simple CRUD app, a site with 100 visitors a day, or a two-week prototype, using Go is clear over-engineering. Go shines when long-term performance, maintainability, and load resilience genuinely matter — not when you're testing an idea before you know if anyone will use it.
Python: the undisputed choice for anything data-related
For data science, machine learning, and AI, the conversation is short: it's Python, and that's not changing anytime soon. NumPy, Pandas, scikit-learn, PyTorch, TensorFlow, Hugging Face — the Python data ecosystem has a decade-long head start on everything else. If someone suggests doing ML in Go "for the performance", that's almost always the wrong call.
Python is also excellent for scripting, automation, and rapid prototyping. The syntax is readable, the standard library is rich, and you can move fast. FastAPI, released in 2018, has become a reference point for lightweight APIs with automatic validation and generated documentation — it's excellent for exposing ML models or building internal services.
Where it gets complicated is in complex business web applications. Django is solid, but the PHP/Symfony ecosystem is more mature for e-commerce platforms, ERPs, and projects with deep business logic and large teams. Python also has a structural weakness: typing is loose by default. Mypy and type hints have dramatically improved the situation, but you have to actively choose to type your code well. Performance is also a limitation — CPython is slow for CPU-bound operations outside of libraries written in C.
Rust and the rest: for the extreme cases
Rust deserves a mention because it's the only language that delivers near-C performance with memory safety guaranteed at compile time. For compilers, rendering engines, WebAssembly, ultra-performant CLI tools (ripgrep, exa, Zed) — Rust is in a category of its own.
The reality for 95% of projects: the learning curve is real and expensive. The borrow checker is a genuine innovation, but it takes weeks before you stop fighting it. If your deadline is in three months and your team doesn't know Rust, now is not the time to learn. Rust is a long-term investment that pays off when performance or memory safety are hard constraints — not nice-to-haves.
A quick note on the others: Java and Kotlin remain solid choices for large enterprises with significant teams, complex projects, and an established JVM culture (Spring, Quarkus). Hiring is easier than people think. Ruby is less fashionable than it used to be, but Rails remains a strong foundation for startups that need to move fast — that's exactly what it was built for.
Quick reference
Language
Strengths
Weaknesses
Typical project
Avoid if...
PHP
Maturity, cheap hosting, large developer pool
Reputation (unfair), single-threaded
Website, e-commerce, classic REST API
Real-time, high performance
JavaScript / Node
Front/back code sharing, npm ecosystem, serverless
npm chaos, CPU single-thread
Full-stack JS, SPA, real-time
Pure API with no JS front-end
Go
Performance, native concurrency, long-term readability
Verbose, thinner library ecosystem
Microservices, CLI tools, high-traffic APIs
Prototyping, data science
Python
Unmatched for AI/data, fast prototyping
Performance, loose typing by default
ML, scripting, automation, lightweight APIs
Mobile, front-end
Rust
Maximum performance, memory safety
Steep learning curve
Systems, WASM, critical tooling
Projects with tight deadlines
Conclusion
The real problem isn't picking the "best" language — it's resisting two opposite temptations: the hype language you've been wanting to try, and the familiar language you apply everywhere by default because it's comfortable. The right question isn't "is Go better than PHP" — that question has no general answer. The right question is: "does the performance gain justify the recruiting cost and onboarding overhead on this specific project, with this specific team, in this specific timeframe?"
A team of three senior PHP developers who know Symfony inside-out will ship more in six months in PHP than in Go where they're starting from scratch. That's obvious when you say it out loud, but it gets lost surprisingly often in the heat of a technical decision. The best language is usually the one your team can still maintain in two years — not the one that tops the benchmarks.
Top comments (7)
Thank you for this great article 👍️. It seems that you compared all popular languages on the market. I'm a PHP dev and try to learn Golang. Your comparison of these 2 languages helped me to realize that PHP is still great 😃
What made you think PHP isn't great?
I think Go is a good choice as a second backend language, because it can be used to do the things PHP is weak at.
There are also Go solutions in the PHP ecosystem like FrankenPHP.
You wrote in the article:
I think that I'm a victim of this opinion. Java, Golang look more professional, because with these languages you can get a job in a some big company.
Anyway PHP is great! 💪
To be clear, I didn't write the article.
2005 to 2012 were the PHP 5 years, that was much better than PHP 4. It already improved a lot. The biggest problem I can remember is that a lot of websites and solutions used old PHP versions, instead of upgrading. With the changes PHP 7 and 8 brought that meant a lot of gains of the new versions were wasted.
I see this more as a developer problem than a language problem.
There are enough big companies that use PHP solutions. Of course if you want to get involved with the bigger projects you have to learn a more "enterprise" language like Java or C#.
While I think it is a fair post, there are a few points that I want to push back on.
The developer pool of PHP has been shrinking since the Node was released.
The main reason the developer pool is as big as it is, is because of Wordpress. And that is not an example of a modern PHP application.
That a junior dev can be productive on a Symfony project in weeks is because the dev has PHP knowledge and has good support. It has less to do with the language.
While serverless can be a good option, it comes with a lot of downsides. So picking your language based on serverless doesn't seems a good way to choose the application/service language.
The real pain with Go error handling is not that it is repetitive, but that it has no type system.
A while ago I created a data storage library based on the composability that the pipe operator brought to PHP and I used an
Errorobject to catch whatever error could occur in one of the piped functions. This way at the end of the pipe you have anErrorinstance or the actual result.I based that mechanism on Go's error handling and improved it by making it able to contain typed exceptions.
All the languages will keep surviving until nobody builds applications with them.
If there is one thing that can destroy languages it is AI. We are seeing it already by the way it made an em dash common in English text. And suggesting javascript or python code when a language is not specified.
I think it's better to write on what you know 😃
Just my two cents, but I think it's worth sharing: In the agentic era, unless a language truly outshines any other in its field (like Python does with Data Science), we should prioritize strongly and statically typed languages.
While C# is a solid choice due to its massive market share and smooth learning curve, Rust is the real champion for me. Its compiler is far less prone to runtime errors than C#, providing a level of reliability that is crucial when you are integrating AI into your workflow.
Furthermore, we need to adapt how we document our projects:
That said, never stop mastering the language itself. Don't over-rely on the agent—it’s meant to be your assistant, but you are the one in the driver's seat.