Why I Chose Elixir Phoenix Over Rails, Laravel, and Next.js
Posted3 months agoActive2 months ago
akarshc.comTechstoryHigh profile
heatedmixed
Debate
85/100
ElixirPhoenixWeb DevelopmentFrameworksComparison
Key topics
Elixir
Phoenix
Web Development
Frameworks
Comparison
The author shares why they chose Elixir Phoenix over Rails, Laravel, and Next.js for their project, sparking a heated discussion about the pros and cons of each framework.
Snapshot generated from the HN discussion
Discussion Activity
Very active discussionFirst comment
50m
Peak period
151
Day 1
Avg / period
40
Comment distribution160 data points
Loading chart...
Based on 160 loaded comments
Key moments
- 01Story posted
Oct 16, 2025 at 9:48 AM EDT
3 months ago
Step 01 - 02First comment
Oct 16, 2025 at 10:38 AM EDT
50m after posting
Step 02 - 03Peak activity
151 comments in Day 1
Hottest window of the conversation
Step 03 - 04Latest activity
Oct 27, 2025 at 6:30 AM EDT
2 months ago
Step 04
Generating AI Summary...
Analyzing up to 500 comments to identify key contributors and discussion patterns
ID: 45605291Type: storyLast synced: 11/20/2025, 8:28:07 PM
Want the full context?
Jump to the original sources
Read the primary article or dive into the live Hacker News thread when you're ready.
I'm pretty sure this isn't true at all with Rails. Out of the box you get Solid Queue (jobs), and Solid Cable (real time messaging).
When paired with https://github.com/akodkod/solid-queue-dashboard you get a nice overview.
Thing is with Elixir though, yes the tools are right there, but you do have to take time to understand them. I've been on and off with Elixir since 2016 and I'm currently wrapping up on a fairly complex elixir project with zero UI. (connecting Shopify GraphQL to a series of 3rd party fulfilment providers who use SFTP (gross). So yes, GenServer, Supervisor etc are all right there as first class citizens, but whilst they are relatively simple to start using, you can end up with some horrifically structured code that would have been much better written without the distributed stuff.
Personally, I prefer Django. Been using it since 2006 and as a person who started off in design but ended up as an engineer, nothing beats Django's template engine (braces for incoming). Django isn't perfect but nothing is. When I have to get something done quick and there's UI work for me to do, I go to Django. When performance or no UI, I go elixir. If someone else is doing the UI, I go phoenix.
About OTP's primitives, they are great but a background job system has more features than those primitives offer. We wrote a fair amount of extra code to get what we needed for our production system. I'm using Sidekiq in Rails in my current Rails project and it's more feature complete than what we built for Phoenix. I'm using Celery with RabbitMQ in my current Django project and we would like to get rid of it. It's too fragile.
But I'm happy running worker type things in elixir & Phoenix if I can.
Solid Queue has a ton of database tables. Oban has `oban_jobs` and `oban_peers`. Oban just runs, simple on the same app. Solid Queue you can do that but it requires reading a lot of obscure blog posts and changing the settings. No sane defaults.
Just as a whole the Erlang and Elixir primitives allow oban to be built truly in the most retarded, obvious way and get away with it. It's wonderful to use as a dev.
Solid Queue I'm bearing because I get other stuff I need from Rails.
Maybe it is obvious in retrospect…
I mean sidekiq is tried and true
Where's the facepalm emoji?
Rails Hotwire uses websockets... The research done here seems to be so basic it literally missed something written on hotwired.dev's landing page, albeit it's mentioned far down enough you have to scroll a teeny tiny bit (half a page on my screen)...
Rails also has background jobs and all the other things considering Phoenix is modeled after Rails.
In short it means you don't have to do any manual diffing, just let the compression do it for you, and have something on the client like morph to merge it in to the dom. It's way more bandwidth efficient as compression is at the byte/char level not at the semantic html level (and not per message but over the whole stream).
This particular bit does seem interesting and would make sense to take advantage of the BEAM's cheap green threads. Couldn't find any info on LiveView's GitHub landing page nor the Phoenix website (haven't dug too much), do you happen to have a link?
https://hexdocs.pm/phoenix_live_view/
That said, the key difference is not whether both use WebSockets, but how deeply integrated and unified the real-time model is in Phoenix. LiveView is not a separate layer bolted onto traditional Rails views. It is part of the core rendering lifecycle. Every UI update, state diff, and event is handled natively within the same process, leveraging the BEAM’s concurrency and fault-tolerance.
In Rails, Hotwire sits on top of the request–response model, giving you partial reactivity without rearchitecting how views work. It is elegant, but still a composition of multiple layers (Turbo, Stimulus, ActionCable).
Phoenix LiveView, on the other hand, was designed from the ground up around real-time stateful components, which leads to fewer moving parts, no client-side JS framework to maintain, and native process isolation per connected user.
So while they share concepts, the philosophy and architecture diverge. LiveView feels closer to a full reactive runtime, not just HTML over the wire.
P.S: I do love rails
For example I have a small side project using LiveView where users would typically pull their phone out, quickly record data, then put it away again. But due LiveView only working with a connected websocket they often have to wait ~1s for the socket to reconnect, and get an annoying error message while it does.
I'm sure there's more I could do to configure this but the default at least is terrible. I believe with Hotwire I wouldn't have this problem, my view would just work and then restore the websocket when it can.
I use Phoenix and LiveView for a lot but I wish we could get more of these rough edges polished up.
You might find Hologram interesting for this use case - it transpiles Elixir to JavaScript so your UI runs client-side. No persistent connection needed, so no reconnection delays or error messages. Still write in Elixir, still communicate with the server when needed.
It's early stage with some rough edges, but there are already Hologram apps in production: https://hologram.page
This means in a vanilla PHP setup when i do something like this:
I need an additional runtime to support real concurrency. I also need a separate async IO library to handle blocking. This is usually a showstopper for most PHP still out there. And just annoying on so many levels.It (JVM) is getting better lately, for example with virtual threads, but still in same resources you can handle much more traffic via PHP and it can be hosted virtually on every hosting!
That said JVM is only a target, so if Java is not your cup of tea, you are free to pick and choose from any of the various JVM languages, like Clojure, Kotlin, Scala etc.
https://en.wikipedia.org/wiki/Actor_model
Smalltalk was a fun language to work with, albeit academically.
Goroutines probably come closest.
Thank you, this is the key factor -- a fundamental design decision that influences the foundation.
However as far back as I can recall it’s shift onto the dev stack was less about “is it a good framework” and more about “this framework can help Product org prototype faster”.
With the advent of Llms, will Product org even care about the dev speed for prototyping?
I hope you at least let devs deploy on whatever stack instantly with new projects and services with something selfserve-y like (Vercel/Heroku/etc).
Who know what they’re doing on your custom stack or who enjoy the 5 meetings it takes to get a basic yaml config setup for a db+mostly static site?
?? Phoenix Live View IS server side rendering...
Specifically I wanted to run both the API and website on the same server (since it was a small company), and with Rails the gem Devise didn't natively support both and while rodauth claimed to support both I couldn't get the build flag to work. With phoenix it just worked out of the box with the most popular libraries, allowing me to move on without becoming an expert in backend frameworks. I agree with most everything else the author said too, specifically about it being more performant and liveview allowing me to build more dynamic websites easily.
Sounds like a Devise problem.
It's worth noting that the creator of Elixir was also an author of Devise.
But you do need to solve a lot of stuff that Laravel already solves for you.
- no JS (well a tiny bit ships with Phoenix but I never have to look at it), no NPM, nothing that breaks every week
- the whole system lends itself to executing on multiple cores
- GenServers BEAM processes in general are amazing
> I still needed background jobs, real-time updates, and two-way communication that just works. Those things are possible in Rails and Laravel, but they take a bit more effort to set up.
These all have first class support in Laravel out the box.
Rails has everything he mentions as an advantage of Phoenix. He's also implying that Rails does not use web sockets to communicate with frontend which is not only wrong it should be evidently wrong to anyone who built a Rails app in the last 3 years.
That's not to say that Phoenix and LiveView aren't phenomenal tools, they are! However what's keeping me in the Rails world is Hotwire Native. I truly feel like a one man army building mobile and web apps in a quick turnaround time.
Redis, postgres. I think there's a couple of commercial offerings.
solid_cable is a database polling mechanism which can also be swapped in.
https://www.youtube.com/watch?v=mpWFrUwAN88&t=25m46s
That being said use what you like and hotwire native sounds cool will give it a try. I also think the author of the blog shouldve went a bit deeper with his points
What Ruby has though is ability to express what you are doing in a clear syntax. Elixir has a lot of ritual (albeit less than erlang) to set up your most used things like GenServer - you don't abstract away the concurrent flow (which is good, concurrency should be obvious), but you also wouldn't write elixir without it, so code inevitably becomes filled with technical concerns.
I'm biased, I write elixir for a living after a decade in Ruby, and I'm happy with that tradeoff. But there are times where you need to do an imperative thing and make it clear as day, and Ruby often does a better job here.
Rails is also somewhat more ergonomic for fast prototyping than phoenix. ActiveRecord is a blessing and curse, it's insanely productive for making things do things in minutes, but lacks composition later on.
I’m actually a rails dev but I’d reach for phoenix if my app required a large number of persistent sockets (e.g. high-volume MCP servers). I say this mostly because the hosting story is better for phoenix (gigalixir) than rails (heroku, or similar services that run behind a request router). Of course if you want your own infra this argument doesn’t apply. But a $100 gigalixir box can easily serve 100k persistent connections — even a few thousand persistent connections is a non-starter on Heroku.
As for raw performance I'm sure you'd get better deal with Elixir out of the box than Rails out of the box but if you wanted to keep all the benefits of Rails and scale websocket usage look into AnyCable.
Where is the article saying that? I only see " Those things are possible in Rails and Laravel, but they take a bit more effort to set up." which is a very different (and more nuanced/personal take) then what you're stating.
To be honest one of the reasons I don't like Phoenix is that even if I opt-out of LV in the generators, I still get a lot of LV code.
As for Livewire - it feels like a simplified copy of Phoenix. In my opinion, it’s less advanced and less intuitive. For example, Livewire components don’t support slots, while Phoenix components handle them without any issues. Slots are critical for clean component composition - without them, you end up with messy, repetitive templates and a lot of unnecessary logic in the components themselves.
When it comes to Next.js, constant router changes and questionable decisions have become a daily routine. There’s no point integrating with something that gets rewritten every week and can’t be trusted to stay stable.
Using Node.js would hurt productivity but it's more powerful if needed. It may be needed because it has async/await and it has socket.io. It's also possible to use Typescript.
Next.js can be useful if you need everything (good SEO + highly interactive) but let's be honest how many websites need good SEO and websockets? LinkedIn maybe.
Next.js server performance isn’t great either - honestly, it’s pretty bad. Pages don’t feel that fast for users despite all the tricks and optimizations. In my opinion, metrics like LCP and others are much easier to optimize in older, more traditional frameworks. Unless you’re building a full-blown web application, a classic web page will almost always be faster and simpler to deliver without all the Next.js complexity.
If you're using Nextjs to get a high level of rich interactivity then your SEO issues aren't about CSR vs SSR anyway though. As you point it it's just bundle size and site speed, and URL structure that end up causing a negative impact. Nextjs doesn't fix that.
That said, I'm not necessarily a big fan of mixed environments since IMO most web apps can be mostly client side and most websites can be mostly server driven. Either is simpler than the mingling tends to get. That's just my take though.
Nextjs with pages router was pretty good for me but app router is where it got complicated
In newer versions, import maps are recommended instead. The problem is that import maps enforce ESM, while Sprockets (as far as I know) doesn’t support ESM at all. On top of that, there are compatibility issues with Turbo links, various form libraries, and the limited extensibility of the import map library itself - adding extra dependencies is just painful.
Installing CKEditor wasn’t straightforward either, so I ended up creating a small DSL to simplify it. But then came another challenge: providing support for custom plugins in a way that would work with every Rails version, even without a bundler.
All of this is made even harder by the fact that CKEditor is distributed in both cloud and NPM versions, which complicates integration paths further.
In contrast, Phoenix makes things much simpler. From what I remember, the standard setup uses esbuild, which automatically pulls NPM dependencies from the deps directory - the same place where Elixir libraries are installed. This means you can distribute a package that includes both the Elixir and NPM parts of the editor, without having to manually modify package.json or worry about dependency conflicts.
Fair there will be some old never updated backend only services, but that seems like a stretch that those will need a FE library all of a sudden
React used to be the leader in how to make ui reasonable in the generic client sense. Having done java swing, android, swift ui, and custom game dev ui work with all the forms of state management, react was on to something… until the ssr fad attacked. Now it is all but nextjs in disguise.
In some cases it's just not what you need and SSR etc are more important - then just use appropriate tools instead of forcing React to do that too
I don't mind picking up a contract for maintaining React code, but never again am I touching anything built by Vercel; unless I specifically crave the “automagically different every release” quicksand masochism of their tools. I'm sorry to the people working on, say, Next; these are qualified and talented individuals. But the DX over time, gods…
React is still a reasonable view library, although not a top choice at all (for me). Insisting on using it for SSR via Next is self-inflicted pain down the road.
I think Livewire is still pretty great. Since PHP can't do websockets easily they focus on http and in most cases thats just fine. Liveview websockets can be an overkill.
IIRC, Livewire 4 will support slots, but... that's still a few weeks away from release. There seem to be a number of perf and qol improvements in LW4.
7 years in on an elixir startup that has well over a thousand active paid accounts using our system every day to run critical businesses. I have to politely disagree.
USE OBAN from day one for any kind of background jobs. do not trust genservers. they lose their state if a pod goes. There's no retry logic built in.
> Start there and only use Oban if there's some form of consistency/resumability guarantee that you need.
oban is easy enough to integrate. it takes like 10 min of your time and you get a LOT out of the box. use genservers if you're running ephemeral servers but if you are creating background tasks, absolutely use oban for anything you plan to put on production.
Oban is such an easy value proposition to justify. consider it as important to learn as core phoenix
sounds like you are using Elixir on Kubernetes. What is the experience and the reasoning with this? I was thinking about this and read on many blogs that it is somehow redundant because Kubernetes implements something like "let it crash" on its own when it's already an Erlang/OTP/Beam concept.
Kubernetes handles let it crash at the process level. so we have one erland vm running inside a docker container and it is the only tennant on its individual machine. this is managed by kubernetes. kubernetes also exposes a discovery endpoint so that all the erland vms we have can be aware of each other and form a cluster. IF something takes down the erlang vm (its exceedingly rare but it does happen), kubernetes will bring up a new one.
erlang's let it crash apply to its lightweight processes which are really just fancy threads with a vm specific scheduler and heap allocation. if somethign crashes a genserver, erlang handles it.
TLDR: they compliment each other
If Kubernetes is not involved, passing messages between Elixir nodes is easy. We just need the name of thr node (and a cookie, if needed).
Not sure if that is possible inside a Kube cluster.
Hope to be wrong though. Erlang based systems are really interesting and under appreciated.
But I could be completely wrong (or have the wrong perception).
Note: not at all suggesting hardwork/progress isn't being made.
Just look at projects like Nx, LiveBook, Explorer, Flame, and Nerves. All are making big steps forward and releasing new and interesting things.
As someone who uses the stack daily this is really wonderful. In the elixir world you just don't really have the problem where two tools don't work well together because they're built around very different versions of the language and runtime. I can pick up any elixir based tool and knowledge I can slot it into my tool chain or project and it'll just work.
To me this is even more exciting because it suggests a stable foundation, and makes it easy to adopt new developments. But I appreciate those projects aren't discussed as much on HN.
The one big thing they got cooking are types. Maybe that's enough to bring it to more people. Just make peace with the fact that it's around 25% the size of Rails market.
But the intent was to say that Elixir as it stands from a paradigm perspective is done, but the existing features and runtime will still be improved.
Which as someone with many years in .NET, I can appreciate. I showed a friend who used C# since the first beta, who’s been hands off for over half a decade now, some modern C# code, and he could not believe what he was seeing.
Much like I can’t believe what I’m seeing when I review a C# code base and have no idea what flavour du jour the developers decided to write it with and how I have to frame the program in my mind to understand it.
Compared to Elixir, which just looks like Elixir has always looked, and does what you expect.
Isn't that what's supposed to happen? It's not really fun to build on top of an exciting platform. Boring means if I build it today, it's likely to continue working for a long time. I've always got more to do than time to do it, so having to rebuild everything all the time because of underlying excitement is not by idea of a good time.
edit: eh, I just went to check and they just has a release today :D
https://elixir-lang.org/blog/2025/10/16/elixir-v1-19-0-relea...
2. Teach them Elixir
3. Profit
Are you giving this advice to every company in existent? Think about that for a second.
Possibly the one thing that Rails still does better is generating quick throw away CRUD apps with their generators. Rails is still pretty much flawless in that regard. That beings said, when things mature and complexity grows Phoenix/Elixir is definitely the better all around tool.
(Although I must say the advantages you listed — a strong compiler, concurrency, reliability — do sound universally good.)
It would have been interesting to see the specific problems you had when building specific features, and how the unique advantages of this stack helped you solve them.
100 more comments available on Hacker News