I implemented CKEditor integrations for Rails, Livewire, Phoenix, and React. I think the best developer experience was with Phoenix - at every step I was surprised by how well thought-out the framework is and how easy it is to build integrations for it. I definitely can’t say the same about Rails or, especially, React with the awful Next.js. For anyone curious: https://github.com/Mati365/ckeditor5-phoenix
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.
PHP (Laravel) + JQuery still works for me in 2025, but I would never use Livewire.
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.
I'm not so sure Next.js is as SEO-friendly as people claim. The JavaScript bundles are pretty heavy, and the page still needs to hydrate before it becomes fully interactive. There are attempts to speed this up with React Server Components, but the developer experience there is already worse than with Phoenix components.
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.
I think if you're going to push closer to the server in a client+server app, I'd probably look towards either HTMX integration options with a preferred backend (there's some cool C# integrations from Jetbrains as an example) or Astro over Next.js ...
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.
I don't understand the 'Nextjs is good for SEO' hype. I think it's better to frame it as Nextjs isn't bad for SEO. Whether a site loads without client side rendering is a pretty binary thing.
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.
Next is all about that server rendering for seo which i remember doing for a spa wedding website a decade ago. Eg, if a crawler, server render otherwise spa style.
Nextjs with pages router was pretty good for me but app router is where it got complicated
I am not sure you can say Livewire is a copy. The name suggests that is the case but both projects were started at similar time Livewire is afaik even older project than Liveview (Hotwire is youngest - in a way). They both take different approaches because PHP/Elixir have very different characteristics.
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.
As a fan of both, the LiveView DX is simpler than Hotwire's (though of course there are trade-offs both ways). With Hotwire you have the think about frames whereas LiveView is more like React where you just change the state and the appropriate diff is patched in without having to think about much else. This is not to say that Hotwire's frames are complex, LiveView is just that much simpler in that regard.
Yep, that's the whole thing, these technologies have strengths and weaknesses for different application. But of course most people just want to learn only one (and I don't blame them).
The main issues were related to how JavaScript is integrated and distributed within Rails. In older versions, you have to deal with Sprockets and dependency bundling, which is tricky if you want your integration to work across a wide range of Rails versions.
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.
It looks like a lot of these issues are due to the fact that Rails has been around for a long time, has lots of versions, and you wanted to support many versions (Which is commendable, by the way). If you only had to support the latest Rails version, how much harder would it have been than doing the same for Phoenix?
In the latest Rails versions, it’s probably just as easy as in Phoenix. The question is whether, after years of churn in the Rails frontend ecosystem, the core team hasn’t already driven away most developers who might have cared. At this point, few people would use a library that targets the newest Rails versions when most teams treat Rails purely as a backend and handle the frontend with something else.
While Rails indeed tries to support old versions for a while I found that many devs are eager to stay on top of upgrades (which also has been less painful the last few years and definitely when done incrementally)
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
Don't preemptively give up on React with Next.js because some posters turn their frustration with it into contempt. Many of us use React 19 and Next App Router to great effect, and enjoy it, although there was certainly a learning curve.
NextJS app router/server components is incredible. By focusing on server-component-compatible patterns for interactivity, my rather complex web app retains like 90% of its functionality even with client side js disabled. I think the hate it gets really might be a skill issue.
It’s not about frustration, unwillingness to learn, or dismissing the tool altogether. My point is about trust. I just can’t imagine a Next.js app being as easily maintainable 10 years down the road as a Rails one. Honestly, I can’t even picture upgrading to a new major version without breaking something, because the pace of changes is just too fast. Sure, it’s great for small, simple projects. But building a business on it and risking breakages or dropped support? Not for me.
This isn't accurate. Most Next shops continue to use Page Router with no problems. We have an internal tool that uses both Page Router with React 13 and App Router with React 19, all seamlessly supported OOB, including frontend composition. So, again, I have to assume most of the FUD is rooted in inexperience.
It makes me sad that today you cannot say react without nextjs in the same sentence.
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.
I love how this article reads more like the individual ignores features and capabilities of other frameworks to then state that the framework he chose is better.
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.
Ive only used ruby a handful of times, so my comment might be ignorant. But other than community , what does ruby and ror do better than say elixir & phx, i feel like the latter is leagues ahead simply because nothing can compare to the beam platform for soft real time systems, you have fault tolerance, nifs, actor model , you can have millions of processes running at the same time for cheap, easy to reason about concurrency , fp makes code concise imo, otp, the beam gc doesnt stop the world etc I just think on paper phx is superior thanks to the beam platform
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
> 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.
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.
In the local Rails community where I live we haven't used Heroku for a while now. Most of us have moved on to using Kamal with a VPS of our choice. The surprising benefit is that you can even host multiple rails app on a single VPS so it is ideal for playing around with multiple hosted apps.
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.
I didn’t say that rails doesn’t use websockets. What i meant is that liveview comes with websockets fully integrated into the framework. This doesn’t mean rails can’t use websockets, but liveview has implemented it more seamlessly at the core. I’ve also mentioned that rails and laravel are both great frameworks, but after using phoenix, i felt that liveview offered advantages in terms of performance and implementation. I’ve worked with all three frameworks and chose the one that worked best for my project. Have you had a chance to try phoenix? If not, do try it out then you’ll get what I meant.
That’s a fair take, rails with hotwire is genuinely powerful, especially with hotwire native. but the post wasn’t about claiming phoenix is better, it’s about how liveview’s model (server driven state, process isolation, lightweight channels) fit a specific use case. both ecosystems solve similar problems differently, rails leans on conventions and progressive enhancement, while phoenix leans on concurrency and fault tolerance from the beam. at the end of the day, it’s less about which is superior and more about which workflow clicks better for what you’re building.
Bit of an tangent, but I remember hearing about Hotwire Native a while back, and then relative silence. Can I ask how your experience has been with it, and the level of support/documentation/features for the kind of mobile apps you've been building with it?
The problem is the websocket implementation (last time I tested it) sucked. I'm assuming even now if you're doing non-trivial websockets you need to use the node or golang implementation.
> But 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.
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).
I think what the blog post is getting is OTP and the mystical/but not mystical GenServer / Supervisor/ distributed pattern. It's baked right in there as a core part of the Erlang VM. I think the post glances over the fact that in rails land solid queue may be right there to use (I've not really used rails in over 10 years).
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.
That's also where I'm at. For any project with UI (and auth/auth etc) I went back to Symfony (and Vue). I can't stand Phoenix templating especially layouts and I couldn't convince José of the greatness of template inheritance like with jinja2 in python ;)
But I'm happy running worker type things in elixir & Phoenix if I can.
IMHO Django's templating engine is its worst feature but that only proves how subjective all these matters can be. I'm currently making money both from Django and Rails. I made quite a bit of money from Phoenix years ago. Customers choose their platforms, I can choose customers.
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.
Take it from someone that uses both systems in production, they are not equivalent. Oban is leagues easier to use and obvious than Solid Queue. Solid Queue has no easy way to rerun a successful job, in Oban you can just update some dumb table columns and done, the Oban supervisor will sniff it out and workworkwork.
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.
I did not mean to diminish the implementation, of course it must be incredibly complex. I meant all that complexity is hidden from me, the developer. It's really easy to understand what to do. :D
As someone who did Rails professionally for a very long time, Phoenix/Elixir is now my default stack.
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.
I think LLM have really closed that gap. Quick throwaway stuff can be generated in a couple of minutes. But phoenix gives me back all the control in cases I care.
Yep I'm a moderate-to-strong LLM hater and this is one of like two things I use them for. Definitely a ground-leveler re: rails too it really had by far the best generators I had come across.
A lot of people tend to flag Elixir for its size and rightfully so, but the community is trying to punch above it’s weight with SOTA libraries. As an old developer once told me: less is more. https://github.com/elixir-dbvisor/sql
OTOH JS is too big for my taste. Everything has 10 implementations with no consensus about doing things. So everyone chooses their own horrible menu. Like an American super market. Or you go full chain restaurant with whatever Vercel pushes currently
Yup - an important distinction that wasn't obvious to me when I first jumped in. LiveViews are very opinionated and generate a ton of boilerplate. Not always a bad thing, but Elixir is elegant because of how spartan and expressive the code is - LiveView is kind of the opposite IMO.
I really want to choose Phoenix, but I can't get over the fact that LiveView is front-and-center. The whole web-socket model just seems so brittle to me.
Oh ok. Is it still worth learning without LiveView? E.g. in my case I’m much more proficient in Python. Is it worth the jump, over something like Django?
In every language there are sharp edges or dirty corners that are just annoying once you hit them. JavaScript and Php are full of inconsistencies, Ruby and Python are nice and the surface but once you dive into meta programming, OOP and mutability complex code bases are just impossible to trust/reason about their correctness. Rust, C++, C#, F#, Java... I could go on.
In my opinion Elixir just hits the sweet spot of good design. After multiple years using it there comes nothing to my mind that I find ugly or annoying.
Sure there are other languages that are quiet nice on paper but often they lack the ecosystem to let you just build production ready stuff.
The Elixir ecosystem is also not that large, but large enough for quickly building a web app or composing useful automation pipelines.
Definitely, Phoenix is way more streamlined than Django/Rails. Even if you jump to other language/framework, it'll teach a lot how to built stuff due to good defaults and project structure. Also simpler too. I remember spending hours trying to figure out how to use specific method and where is it coming from in Rails. In Elixir/Phoenix there's very few "import"s in use (single file you can inspect and modify), non hidden state. You see Foo.bar("some argument") and you know you don't need anything else to understand what it does. Rails is very magical in this sense, Django as well, a bit
The tragic part that all my 'corporate' customers don't even want to hear about Elixir. For them only JS, Python, C# and Java exist in this world. Any other stack is either "unacceptable", "unsustainable", "exceedingly expensive" or "unmanageable". In 7 years of using Elixir I couldn't impose it in any corporate project, used it only for hobby/personal/indie stuff.
Almost 20 years after I bought my first Erlang books, I would never recommend Erlang OR Elixir to anyone but a senior dev who likes coding on their own and want to try something different. This pool is almost 0 people, since I was someone who wanted to play with it. I found the juice not worth the squeeze, in time investment vs capability. The build system alone is enough to throw most people off.
> It's a piece of cake to create a deployment and everything is controlled through the one cli, mix.
* It is not, despite your own familiarity. Erlang is in worse shape, using rebar3 ofc
* There is no central package management. I want to know what library to include that will do X (or a selection of choices), if it's not in https://github.com/h4cc/awesome-elixir, I basically have to crawl github. (Lua has the same problem).
Past some toy projects, most people abandon these languages for more mature ecosystems.
In the corporate world ecosystem and fungibility of programmers are the top priority. The only way Elixir will get traction there is by Elixir companies literally growing to Fortune 500 size and showing the language/ecosystem is viable at that scale. Even then I doubt the advantages of Elixir will move the needle for that type of company because once you scale up the challenge is 99% people, teams, and communication; the elegance and efficiency of the code and ops don't matter much in those types of environments.
I'm always curious about C# because it seems to be fast, feature-full, not too much bloated, etc. I'm an elixir dev/fan, but what's wrong with C#? How would Elixir shine compared to it?
I absolutely adore .NET for backend development. It's fast, and while C# might be a little syntactically verbose but that doesn't bother me, the language has made great strides over the years to reduce verbosity.
While I haven't used other ORMs in many moons, Microsoft's Entity Framework coupled with LINQ is soooooo freaking nice to use.
For frontend work, I'm still manually writing boring, vanilla JS, and it's honestly not bad for average CRUD apps. Though, I have been exploring various frontend libraries, and I haven't found one I absolutely adore yet. Hated Angular, React is tolerable (never tried Next.js), HTMX provided little over vanilla JS, and so on.
I have not tried Elixir, but in your opinion, what do you think makes it so great?
The Elixir live view model to me look like one of the only sane programming models for modern web development right now... Otherwise your best choice still remains to be server side rendering.
Yes. I wasn't implying live views are not this, I was trying to say react, vue, angular, svelte, next.js, solid, preact, alpine.js, ember, backbone, lit, mithril, stimulus, knockout, aurelia, polymer, riot, inferno, marko, dojo have a terrible programming model and anything with server side templates is a vast improvement.
Don't know how much you have used ember, but I disagree, it's quite sane as a programming model and ember data is still ahead in terms of developper comfort for client apps.
Interesting article, but I had to scroll all the way to the bottom to find what you actually built. I consider this important information, because the right tool for the job will depend on what the job actually is!
(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.
Oban is great, but for most cases you don't need it. In languages with a less good concurrency model we are used to needing some form of library or system to manage "background jobs", but in Elixir you can just spin up some GenServers under a supervisor to do work. Start there and only use Oban if there's some form of consistency/resumability guarantee that you need.
> Oban is great, but for most cases you don't need it.
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.
we operated for 4 years before we switched to pro. you get quite a bit out of the free version. we only switched because we wanted the rate limiting features of pro. plus $100 month is cheap if you're dealing with the problems that pro solves for you
With GenServers, what happens if you pod/machine crashes? You lose all the unprocessed jobs. Oban gives you safe retries, and guarantees consistency. If you're using a relational DB, I would infact suggest to start with Oban, and then take a look at the jobs and see if you are okay with losing jobs and move to GenServers.
For a startlingly large number of use cases, you don't even need to go that far; the built-in task system can typically cover almost all the use cases you'd reach for simple background processing, and exposes an interface very similar to the promise interface in other languages
I haven't found Oban difficult to work with and it has the added benefit of ensuring your jobs are run only once. There is also the cron functionality that I find really useful for scheduling.
It's a pity the author didn't decide to offer a trial without attaching a credit card. I get it, we had these discussions here many times. But as a person that could potentially subscribe, I'm baffled at the choice.
You could argue that I'm not really willing to subscribe if I'm not willing to provide my CC details yet. But it doesn't work this way. Before I subscribe to a new service, I really like to know it well, to have a kind of emotional relationship to understand what it is giving/saving me. "Give me you CC or get off" makes me not even want to try.
This isn't a debate about whether to offer a trial period or how of one to offer. This is a debate about forcing people to give you payment info for a free trial.
Requiring a credit card for a free trial is a technique to trick people into paying for a subscription when they normally wouldn't have chosen do do so after the trial period.
Not taking VC funding doesn't make this kind of dark pattern any less scummy. Fundementally you are trading some voluntary customers (people who don't like these tactics) or involuntary customers (distracted, busy or lazy people who forget to cancel.) When I see a company that does this, it tells me that they care about extracting value from the market than providing value to customers.
I completely agree. Requiring credit card info for a free trial often feels like a dark pattern designed to trap users into paying. I’m taking a different approach with my product by offering a 3-day free trial that doesn’t require a card, and a 14-day free trial for serious users. I want users to try it without any pressure or tricks and make a decision based on the value they experience, not because they forgot to cancel.
After Elixir announcing being "feature complete" a few years ago, and then Phoenix going down the LiveView path for quite sometime ... I feel like the Phoenix/Elixir stack became less exciting to me.
Hope to be wrong though. Erlang based systems are really interesting and under appreciated.
> I feel like the Phoenix/Elixir stack became less exciting to me.
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.
The pace of new things coming to the ecosystem hasn't slowed at all, but it's happening beyond the language itself now.
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.
I've been developing full-time in Elixir / Phoenix for the last 6 years. I can assure you, momentum in the ecosystem has not slowed at all since the language was declared to be "feature complete".
In your defence, the choice of wording is confusing and that particular announcement did have a sense of “game over”ness to it.
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.
Elixir and Phoenix are as big as they ever will be. Around 25% of the size of the Rails "mindshare". But still I love the Elixir stack to death, it's so wonderful.
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.
Thanks for your feedback! Yes, Oban is a third-party package, but it’s built for Phoenix, which is what I meant in the article. Also, the article is not AI-generated. I’ve mentioned the app I built with Phoenix at the bottom to give context from real experience.
Working with Phoenix, and even more so Elixir and OTP, has been a great joy at a similar to almost the same level I had when transitioning from DotNet to Ruby in 2010 for my experience.
There are still some rough edges, and the job market might be more challenging, but overall I feel anything Elixir related at the moment provides for a high quality filter - both in terms of job opportunities and teams as well as the general product development experience.
I have been pretty happy with Elixir - the syntax takes getting used to, but I'm usually impressed by its elegance.
Phoenix I'm mixed on - it has a few things that "just work" and I'm happy about, but being an opinionated framework I find myself bumping into those opinions the more I want to do things my own way. Usually there's an escape hatch, but being new to both Elixir and Phoenix it's not always obvious to me how to do things when the happy path fails.
The best, most popular serverless platform? There are stacks much worse than PHP, like JVM for example ;)
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!
I'm taking one look at Elixir and I'm not sure how it's supposed to be an improvement from Ruby? The readability and syntax seems to be a step backwards, so I'll stick with Ruby/Rails, thanks!
that’s fair, though the intention wasn’t to dismiss rails or crown a winner. it was more about sharing a personal experience with elixir and phoenix for a specific use case, not a comparison to discredit other frameworks. i haven’t discredited rails, but features like fault tolerance and the beam make phoenix especially robust. i also mentioned that rails is a beautiful framework, i just chose what felt best for my project.
client disconnects, state desyncs, then reconnects, then liveview figures out via crdt and other things how to accurately diff the state
feels like i have to trust it too much - i'd have a lot more confidence if people were vocal about how they are running it at scale, battle-tested etc. etc.
shopify is straight up yolo running rails edge, which is a crazy endorsement
I watched a few demos and it is clearly magic and I was very impressed. Though I can't picture how a more standard run off the mill web app would be built with it.
My biggest problem with Elixir is the lack of support for 3rd-party libraries and the small community. I love the idea of it, but every time I try to ship a real project in LiveView, I'm left feeling like the community is not that mature. Maybe coming from a Go backend React frontend stack, that might be the case, but maybe for quick CRUD apps, it's great.
Elixir is pretty "nifty", and has Rails feels. I have worked on and seen its performance compared to scaled up Rails application. The BEAM / OTP is a very cool system to program on top of. I think it would be a great underlying system to develop a consciousness for AI systems with its concurrency paradigms and message passing, node connecting, other builtins. I'm not sure if the AI/ML focused Elixir projects like Nx have really taken off, but again, an Elixir based system that accepts numerous connections, passes messages around like exciting synaptic communications between functions... it just seems cool, maybe just on paper...
When you consider the message passing paradigm, I can envision how that simulates neuro-chemical communication between neurons (now here being functions that do things). So there is a design for communication between functions, then there are memory storage and information retrieval parts of the system, short-term RAM, long-term HD/SSD, databases, cache-systems, where relevant information can be and become manipulated. Long and short running processes, acceptance of fail-fast and that communications can fail and that's just part of software system life (I assume also a similar idea in the human brain, don't you find yourself forgetting something you were just thinking about?). There is then the external part of the system, accepting inputs from the outside.
The message passing paradigm is called the "Actor Model" and was invented in the 70s IIRC. It's available in most programming languages and it's not something exclusive to Elixir by any means.
Not exclusive to Elixir, but the BEAM was built from the ground-up around Actor for concurrency. Almost all other popular language ecosystems have it bolted on over time (with varying degrees of success) or relegated to a third party library. It's very natural and ergonomic in Elixir, because it's the paradigm of choice in the underlying vm.
Having built a mediumish soft realtime queue processing solution on rails I gotta say it was not great. If we didn’t kinda grow into it I would not have chosen ruby
Thanks for sharing. Yeah, I think that's a problem with bolted on functionality. Did you end up building a new version with a different language? What kind of problems did you encounter that made the solution "not great"?
True, the closest thing i like in the node.js backend world is nestjs. It’s a solid framework for building apis, but as an mvp framework, it’s not quite on the same level as laravel, rails, or phoenix.
I used to feel the same way, but at a certain level of Node.js experience I came to prefer the backend JavaScript idiom. It's much lighter and more pragmatic, and gives the knowledgeable engineer a lot of flexibility. So stick with it.
In the era of vibe coding just use the fastest servers. I wrote my last api in Rust and it wasn't any harder than anything else, it's wicked fast and stable.
After doing that, it seems a lot of the higher level languages will go away soonish
I'd rather fix AI slop in simpler languages, thank you very much.
And by the time performance is a startup's concern in majority of cases, they would have to rewrite most of the code anyway, including critical parts, so why not start with a language that's easier to find developers?
Doesn’t the LV approach suffer from latency issues?
If I understand correctly all state is managed by the server, which means even the most trivial UI interaction needs a roundtrip. Not to mention the cost of managing the state and connection of every client. So how does that work in practice?
latency is minimal because liveview sends only dom diffs, not full page updates. most interactions feel instant. each connection runs as a lightweight beam process, so managing per-user state scales efficiently. for very high-frequency ui updates, some client-side js may still be needed, but for forms, lists, modals, and live updates, liveview is smooth and responsive.
The size of the diff and the latency of the underlying transport layer are independent. If your user in NY clicks a button that has to go to your server in SF, you pay for that ping both NY->SF and SF—>NY for the reply.
Same goes for whether they’re on some flakey mobile connection in a car or on a train.
It’s also super easy to accidentally send a ton of data down the wire on component mount. I worked on a massive LiveView app at a company you’ve heard of and these kinds of issues were a problem the whole time.
You also give up the standard stateless HTTP request/response model when you go with LiveView. This is not necessarily bad, but people should be aware that they’re turning their stateless web tier into a stateful web tier. It’s an entirely different model (and in my opinion, more challenging).
LiveView is cool technology but I don’t want people to overlook the fact that it has some sharp edges you have to be aware of when building large products.
But yes, for interactive elements it's not optimal. They have some JS helpers for simple things but you may need to drop down to JavaScript hooks yourself if you want do better.
I've been playing around with Hologram, which transpiles Elixir to JavaScript. It's very early days but it has the potential to be a much better solution than LiveView.
I believe that's still true of Erlang, but Elixir has UTF-8 encoded strings. In practice the only time you need to use Erlang strings from Elixir is if you're using an Erlang API.
Both Erlang and Elixir support two types of text representations.
The first is a linked list of Unicode codepoints (also called a character list or a charlist for short). In Erlang, this is written using double quotes. For example, "abc" in Erlang is actually the list [97, 98, 99]. In Elixir, the same representation uses single quotes: 'abc' is a list of integers.
The second is a UTF-8 encoded binary. In Erlang, this is written using the <<"abc">> syntax. In Elixir, double quotes represent UTF-8 binaries, so "abc" is a binary.
So:
Erlang "abc" = list, <<"abc">> = binary
Elixir 'abc' = list, "abc" = binary
For efficiently handling textual data, Phoenix extensively utilizes iolists (https://hexdocs.pm/elixir/1.15.8/IO.html#module-io-data) to eliminate copying. It's used in performance critical areas such as generating http responses and template rendering. In general, on the Erlang VM, iolists are a first-class, widely used data structure for efficient I/O.
> 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.
All good, but did you know that Next.js is a full stack framework? You can have backend and frontend in the same code base. You don't need Laravel if you use Next.
that’s true, next.js does a great job offering a full stack experience. the difference with phoenix is that it’s built on the beam, which gives you concurrency, fault tolerance, and real-time capabilities out of the box. liveview also lets you build interactive frontends without managing separate api layers or client frameworks, keeping everything unified and fast.
Chris McCord directly addresses this in his recent ElixirConf talk. There's a threshold amount of training data needed for LLMs to work well, and Elixir more than clears it. Beyond that threshold, having more data doesn't make a tremendous difference. This means the "frustration gap" for newcomers essentially disappears - people who heard "Elixir is good" can now just ask an LLM to build something and start immediately, easing their way into understanding functional programming paradigms in order to be productive. I use Claude Code daily for Elixir development and it understands the language perfectly. The real strategic advantage is that while other ecosystems scramble to solve agent orchestration problems, Elixir/OTP already solved them decades ago. Lots more here: https://www.youtube.com/watch?v=6fj2u6Vm42E&t=1321s
The product that OP is building is a todo list. Rails or Laravel would have both worked just fine. Elixir/Phoenix are neat technologies, but I get the sense that this decision was primarily "because I want to" rather than any particular selection methodology (which is fine - you do you, OP).
It’s not just a simple todo list. The product includes advanced features like goal tracking, minimal project management, a streak system, daily task resets with a 3-task limit, and AI-powered task creation that can break tasks into subtasks. Users also get individual profiles to share streak progress and build habits. On top of that, we’re working on additional features like adding team members to projects and real-time collaboration. While it’s certainly possible to build these in Laravel, implementing them is not as seamless or straightforward as it is in Phoenix.
I worked with Elixir/Phoenix for over 3 years, and I recently started to learn Crystal, mostly to create CLI apps or other programs where I want to create a simple executable binary. I wanted a more expressive language than Go, and easier than Rust.
Out of curiosity, I took a quick look at some of the web frameworks available, they are interesting.
Lucky's Components looks pretty good, but I still prefer Phoenix's Components because the syntax make it very close to raw HTML.
Compilation is not incremental and is single threaded which means I have to wait at least 5 seconds every time I make a change (this was on a minimal project). It's not that bad, but compared to Elixir/Phoenix where it's almost instantaneous, it makes a difference.
Still, Crystal is an awesome language, and if for one reason Elixir was not a choice for a web project, I would definitely consider a Crystal framework.
Having done both for years, I can say confidently that you can use Phoenix without recreating Rails. The differences are important, and IMO Ecto is a much better approach to interacting with a database than ActiveRecord. I've also never seen a bug in my application due to upgrading Ecto, and I definitely can't say that about ActiveRecord.
I am curious how much longer NextJS will last considering it is a lock-in vehicle for Vercel.
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?
the sentiment around NextJS is terrible, I have rarely seen something go from "oh this might be cool" to "stop pushing this badly engineering crap on me" so quickly. Yes, it's widely used and that's to be expected given the amount of money spent in promoting it, but it's not loved by any mean and I see this as a fatal flaw that they'll have to reckon with sooner or later. It's so bad that it worsened React's reputation by association - React already had some issues to care about, but they went in Next's direction, and people have noticed
There's absolutely no reason to use Vercel. I've always run Next on our own servers, for multiple clients and some very complex projects. Page Router or App Router.
Ironically I choose to deploy our nextjs projects on Vercel because interacting with our inhouse stack means involving an infrastructure person who wants to critique and research how you’re developing your app. With Vercel I can just deploy a project and don’t have to ask Steve what the best set of server tools I need and then work with Steve on the monolith of Kubernetes configs to get it deployed. And while I like Steve, adding him to a project is a huge time sink and cost center all it’s own. Even if I get platform access to self serve, Steve will be there gating me for every little permission I need.
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).
One benefit i found over rails was just some of the libraries were more modern. I'm not a backend developer, so maybe I'm just not skilled enough to know how to do these things, but I found rails libraries tended to be dated and missing more modern features.
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.
I am not even sure that is true. Only if your main criteria is available resumes where the programming language is listed at all.
JS has probably upper 90% there
I don’t hire developers who are tied to just one framework. I prefer someone who has a solid understanding of a platform but also a mindset to learn new technologies. You don’t need a large team, just one or two talented developers on a good pay package can be more than enough, and in my opinion, it’s worth it.
> It’s way ahead of both Rails Hotwire and Laravel Livewire. LiveView communicates through WebSockets
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.
You’re right. Hotwire (specifically Turbo Streams) does use WebSockets under the hood when available. And yes, Rails has background jobs, ActiveJob, and other robust primitives that Phoenix was inspired by.
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.
This is actually one of the huge tradeoffs and pitfalls of LiveView. Its websocket model is all or nothing.
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
that’s a really valid point. liveview’s websocket-first model can feel heavy for quick, intermittent interactions like mobile data entry. it shines when the user is continuously connected, but those short bursts do expose rough edges. hotwire’s approach of progressive enhancement and optimistic rendering handles these scenarios more gracefully since the view works independently of the connection. phoenix and liveview are still amazing, but improving these “short session” experiences would make it even stronger.
Ya, this was not worded well at all (and more likely just not well researched (in the article, I mean). The difference between hotwire/livewire and LiveView is that with LiveView you get a "live" connection to persistence BEAM process which comes with benefits like not having to rebuild things (like the current user) on each request and storing ephemeral state on the server (if you need it). Of course there are trade off like PWAs are not fun in LiveView (you likely just wouldn't do it, I never have).
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?
The guides are the best place to learn about LiveView itself. Since guides are always included as part of the docs (reference docs) people always tend to shy away from them (not saying you are, it's just a thing with people it seems):
Oh also wanted to point out that while there has been an ongoing effort for LiveView Native, it is not there yet (I actually haven't heard anyone talking about it in quite a while). I'm not too in the Rails world so I don't know how good Hotwire Native is, but I assume it's much further along than LV Native, so that's a big thing if you need that. No idea about LiveWire as I've never even been in the Laravel world.
The author is a self-professed front-end developer according to LinkedIn, which may be influencing experience with backend systems and functionality. I was wondering really why this terse post is sky-rocketing to #1 today, hopefully we get some good discussion from the community.
It's standard http so you don't have to build your own bad version of http on top of it. It's handles disconnects for you. You can use the browsers built in compression over the life of the connection. You have access to brotli/zstd without having to ship it to the browser first (and it's the C++ version).
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).
I implemented CKEditor integrations for Rails, Livewire, Phoenix, and React. I think the best developer experience was with Phoenix - at every step I was surprised by how well thought-out the framework is and how easy it is to build integrations for it. I definitely can’t say the same about Rails or, especially, React with the awful Next.js. For anyone curious: https://github.com/Mati365/ckeditor5-phoenix
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.
PHP (Laravel) + JQuery still works for me in 2025, but I would never use Livewire.
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.
I'm not so sure Next.js is as SEO-friendly as people claim. The JavaScript bundles are pretty heavy, and the page still needs to hydrate before it becomes fully interactive. There are attempts to speed this up with React Server Components, but the developer experience there is already worse than with Phoenix components.
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.
I think if you're going to push closer to the server in a client+server app, I'd probably look towards either HTMX integration options with a preferred backend (there's some cool C# integrations from Jetbrains as an example) or Astro over Next.js ...
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.
I don't understand the 'Nextjs is good for SEO' hype. I think it's better to frame it as Nextjs isn't bad for SEO. Whether a site loads without client side rendering is a pretty binary thing.
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.
Next is all about that server rendering for seo which i remember doing for a spa wedding website a decade ago. Eg, if a crawler, server render otherwise spa style.
Nextjs with pages router was pretty good for me but app router is where it got complicated
I am not sure you can say Livewire is a copy. The name suggests that is the case but both projects were started at similar time Livewire is afaik even older project than Liveview (Hotwire is youngest - in a way). They both take different approaches because PHP/Elixir have very different characteristics.
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.
I wonder what made it hard for you in Rails.
As a fan of both, the LiveView DX is simpler than Hotwire's (though of course there are trade-offs both ways). With Hotwire you have the think about frames whereas LiveView is more like React where you just change the state and the appropriate diff is patched in without having to think about much else. This is not to say that Hotwire's frames are complex, LiveView is just that much simpler in that regard.
Liveview is also websockets. For many usecases going with simple http requests is a good limitation.
Yep, that's the whole thing, these technologies have strengths and weaknesses for different application. But of course most people just want to learn only one (and I don't blame them).
I'm curious about your experience with Rails. What specifically caused issues?
The main issues were related to how JavaScript is integrated and distributed within Rails. In older versions, you have to deal with Sprockets and dependency bundling, which is tricky if you want your integration to work across a wide range of Rails versions.
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.
It looks like a lot of these issues are due to the fact that Rails has been around for a long time, has lots of versions, and you wanted to support many versions (Which is commendable, by the way). If you only had to support the latest Rails version, how much harder would it have been than doing the same for Phoenix?
In the latest Rails versions, it’s probably just as easy as in Phoenix. The question is whether, after years of churn in the Rails frontend ecosystem, the core team hasn’t already driven away most developers who might have cared. At this point, few people would use a library that targets the newest Rails versions when most teams treat Rails purely as a backend and handle the frontend with something else.
While Rails indeed tries to support old versions for a while I found that many devs are eager to stay on top of upgrades (which also has been less painful the last few years and definitely when done incrementally)
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
> For example, Livewire components don’t support slots
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.
I want to give both of these a try, especially if you say react+next.js is awful. You'd think TS-TS would be well thought out
If you want to mix server with React and TS, then take a look at Astro or HTMX.
Don't preemptively give up on React with Next.js because some posters turn their frustration with it into contempt. Many of us use React 19 and Next App Router to great effect, and enjoy it, although there was certainly a learning curve.
NextJS app router/server components is incredible. By focusing on server-component-compatible patterns for interactivity, my rather complex web app retains like 90% of its functionality even with client side js disabled. I think the hate it gets really might be a skill issue.
It’s not about frustration, unwillingness to learn, or dismissing the tool altogether. My point is about trust. I just can’t imagine a Next.js app being as easily maintainable 10 years down the road as a Rails one. Honestly, I can’t even picture upgrading to a new major version without breaking something, because the pace of changes is just too fast. Sure, it’s great for small, simple projects. But building a business on it and risking breakages or dropped support? Not for me.
This isn't accurate. Most Next shops continue to use Page Router with no problems. We have an internal tool that uses both Page Router with React 13 and App Router with React 19, all seamlessly supported OOB, including frontend composition. So, again, I have to assume most of the FUD is rooted in inexperience.
It makes me sad that today you cannot say react without nextjs in the same sentence.
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.
If the industry wouldn't have pushed React as the magic bullet that is always to be used it could have stayed an awesome interactive frontend library.
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 love how this article reads more like the individual ignores features and capabilities of other frameworks to then state that the framework he chose is better.
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.
Ive only used ruby a handful of times, so my comment might be ignorant. But other than community , what does ruby and ror do better than say elixir & phx, i feel like the latter is leagues ahead simply because nothing can compare to the beam platform for soft real time systems, you have fault tolerance, nifs, actor model , you can have millions of processes running at the same time for cheap, easy to reason about concurrency , fp makes code concise imo, otp, the beam gc doesnt stop the world etc I just think on paper phx is superior thanks to the beam platform
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
The gem ecosystem and hiring pool is much better. Otherwise, as raw tech it's worse
> 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.
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.
In the local Rails community where I live we haven't used Heroku for a while now. Most of us have moved on to using Kamal with a VPS of our choice. The surprising benefit is that you can even host multiple rails app on a single VPS so it is ideal for playing around with multiple hosted apps.
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.
I didn’t say that rails doesn’t use websockets. What i meant is that liveview comes with websockets fully integrated into the framework. This doesn’t mean rails can’t use websockets, but liveview has implemented it more seamlessly at the core. I’ve also mentioned that rails and laravel are both great frameworks, but after using phoenix, i felt that liveview offered advantages in terms of performance and implementation. I’ve worked with all three frameworks and chose the one that worked best for my project. Have you had a chance to try phoenix? If not, do try it out then you’ll get what I meant.
That’s a fair take, rails with hotwire is genuinely powerful, especially with hotwire native. but the post wasn’t about claiming phoenix is better, it’s about how liveview’s model (server driven state, process isolation, lightweight channels) fit a specific use case. both ecosystems solve similar problems differently, rails leans on conventions and progressive enhancement, while phoenix leans on concurrency and fault tolerance from the beam. at the end of the day, it’s less about which is superior and more about which workflow clicks better for what you’re building.
Bit of an tangent, but I remember hearing about Hotwire Native a while back, and then relative silence. Can I ask how your experience has been with it, and the level of support/documentation/features for the kind of mobile apps you've been building with it?
Yup. the rails 7 demo showed websockets back in Dec 2021:
https://www.youtube.com/watch?v=mpWFrUwAN88&t=25m46s
I don't see anything in this post claiming that Rails doesn't support websockets, where are you getting that?
The problem is the websocket implementation (last time I tested it) sucked. I'm assuming even now if you're doing non-trivial websockets you need to use the node or golang implementation.
You can swap out the ActionCable backend with different providers.
Redis, postgres. I think there's a couple of commercial offerings.
solid_cable is a database polling mechanism which can also be swapped in.
> But 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.
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).
Yeah def odd, I'm a recent rails convert and SolidQueue is dead simple and is setup out of the box.
When paired with https://github.com/akodkod/solid-queue-dashboard you get a nice overview.
I think what the blog post is getting is OTP and the mystical/but not mystical GenServer / Supervisor/ distributed pattern. It's baked right in there as a core part of the Erlang VM. I think the post glances over the fact that in rails land solid queue may be right there to use (I've not really used rails in over 10 years).
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.
That's also where I'm at. For any project with UI (and auth/auth etc) I went back to Symfony (and Vue). I can't stand Phoenix templating especially layouts and I couldn't convince José of the greatness of template inheritance like with jinja2 in python ;)
But I'm happy running worker type things in elixir & Phoenix if I can.
IMHO Django's templating engine is its worst feature but that only proves how subjective all these matters can be. I'm currently making money both from Django and Rails. I made quite a bit of money from Phoenix years ago. Customers choose their platforms, I can choose customers.
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.
All the things are possible in rails as well. it is a beautiful framework, but it is so much easier to use with phoenix. Do try it out
Take it from someone that uses both systems in production, they are not equivalent. Oban is leagues easier to use and obvious than Solid Queue. Solid Queue has no easy way to rerun a successful job, in Oban you can just update some dumb table columns and done, the Oban supervisor will sniff it out and workworkwork.
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.
> 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.
Maybe it is obvious in retrospect…
I did not mean to diminish the implementation, of course it must be incredibly complex. I meant all that complexity is hidden from me, the developer. It's really easy to understand what to do. :D
> Solid Queue I'm bearing because I get other stuff I need from Rails.
I mean sidekiq is tried and true
I don't want to pay for a redis instance. On principal! coming from elixir thats an ick haha
As someone who did Rails professionally for a very long time, Phoenix/Elixir is now my default stack.
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.
I think LLM have really closed that gap. Quick throwaway stuff can be generated in a couple of minutes. But phoenix gives me back all the control in cases I care.
Yep I'm a moderate-to-strong LLM hater and this is one of like two things I use them for. Definitely a ground-leveler re: rails too it really had by far the best generators I had come across.
why / what do you find works better?
A lot of people tend to flag Elixir for its size and rightfully so, but the community is trying to punch above it’s weight with SOTA libraries. As an old developer once told me: less is more. https://github.com/elixir-dbvisor/sql
OTOH JS is too big for my taste. Everything has 10 implementations with no consensus about doing things. So everyone chooses their own horrible menu. Like an American super market. Or you go full chain restaurant with whatever Vercel pushes currently
Couldn’t agree more, I was taking a diplomatic approach as I was linking to my own work!
> First things first, why do we code? To solve problems in the most optimal way possible.
I admire the enthusiasm. As a person who codes just to solve problems in a good enough way - I assume I should stick to Rails.
I had to laugh out loud when I read that sentence.
Really? I write code to pay my bills and sometimes just for fun.
Trying to do everything "the most optimal way possible" is going to get in the way of actually getting stuff done.
"Why do we code? To prematurely optimize all the things".
Rails is awesome!
Author should read the rails docs again, seems like they missed a lot.
For those who want to experience the strength of Elixir, they should watch all videos of Saša Jurić on Elixir.
iirc he wrote elixir in action. also. really good.
Indeed, it's a masterclass in technical writing. It's the best programming book I have read.
+1 to Elixir. The entire erlang ecosystem is great and Elixir allows devs who don't have time to learn Erlang to leverage it.
One of the best languages for startups who want to design scalable software from the start
The post is mostly about Phoenix LiveView, while the title makes it about the framework.
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.
Yup - an important distinction that wasn't obvious to me when I first jumped in. LiveViews are very opinionated and generate a ton of boilerplate. Not always a bad thing, but Elixir is elegant because of how spartan and expressive the code is - LiveView is kind of the opposite IMO.
I really want to choose Phoenix, but I can't get over the fact that LiveView is front-and-center. The whole web-socket model just seems so brittle to me.
Although I agree that LiveView sucks up too much air in the ecosystem, you can just ignore that and develop web apps the standard ways of you want.
Oh ok. Is it still worth learning without LiveView? E.g. in my case I’m much more proficient in Python. Is it worth the jump, over something like Django?
Yes because Elixir is such a nice language.
In every language there are sharp edges or dirty corners that are just annoying once you hit them. JavaScript and Php are full of inconsistencies, Ruby and Python are nice and the surface but once you dive into meta programming, OOP and mutability complex code bases are just impossible to trust/reason about their correctness. Rust, C++, C#, F#, Java... I could go on.
In my opinion Elixir just hits the sweet spot of good design. After multiple years using it there comes nothing to my mind that I find ugly or annoying.
Sure there are other languages that are quiet nice on paper but often they lack the ecosystem to let you just build production ready stuff. The Elixir ecosystem is also not that large, but large enough for quickly building a web app or composing useful automation pipelines.
Definitely, Phoenix is way more streamlined than Django/Rails. Even if you jump to other language/framework, it'll teach a lot how to built stuff due to good defaults and project structure. Also simpler too. I remember spending hours trying to figure out how to use specific method and where is it coming from in Rails. In Elixir/Phoenix there's very few "import"s in use (single file you can inspect and modify), non hidden state. You see Foo.bar("some argument") and you know you don't need anything else to understand what it does. Rails is very magical in this sense, Django as well, a bit
Depends on how much you value the language you are using. Elixir can be quite a bit more elegant than Python.
The tragic part that all my 'corporate' customers don't even want to hear about Elixir. For them only JS, Python, C# and Java exist in this world. Any other stack is either "unacceptable", "unsustainable", "exceedingly expensive" or "unmanageable". In 7 years of using Elixir I couldn't impose it in any corporate project, used it only for hobby/personal/indie stuff.
Almost 20 years after I bought my first Erlang books, I would never recommend Erlang OR Elixir to anyone but a senior dev who likes coding on their own and want to try something different. This pool is almost 0 people, since I was someone who wanted to play with it. I found the juice not worth the squeeze, in time investment vs capability. The build system alone is enough to throw most people off.
How is the build system a problem? It's a piece of cake to create a deployment and everything is controlled through the one cli, mix.
> It's a piece of cake to create a deployment and everything is controlled through the one cli, mix.
* It is not, despite your own familiarity. Erlang is in worse shape, using rebar3 ofc
* There is no central package management. I want to know what library to include that will do X (or a selection of choices), if it's not in https://github.com/h4cc/awesome-elixir, I basically have to crawl github. (Lua has the same problem).
Past some toy projects, most people abandon these languages for more mature ecosystems.
In the corporate world ecosystem and fungibility of programmers are the top priority. The only way Elixir will get traction there is by Elixir companies literally growing to Fortune 500 size and showing the language/ecosystem is viable at that scale. Even then I doubt the advantages of Elixir will move the needle for that type of company because once you scale up the challenge is 99% people, teams, and communication; the elegance and efficiency of the code and ops don't matter much in those types of environments.
I'm always curious about C# because it seems to be fast, feature-full, not too much bloated, etc. I'm an elixir dev/fan, but what's wrong with C#? How would Elixir shine compared to it?
C# is great. You might like Blazor if you enjoy LiveView. I prefer .NET / C# static type system
Blazor is not surviving backend scaling, so currently it’s not really usable for bigger, real apps. Hopefully this will get fixed eventually.
I absolutely adore .NET for backend development. It's fast, and while C# might be a little syntactically verbose but that doesn't bother me, the language has made great strides over the years to reduce verbosity.
While I haven't used other ORMs in many moons, Microsoft's Entity Framework coupled with LINQ is soooooo freaking nice to use.
For frontend work, I'm still manually writing boring, vanilla JS, and it's honestly not bad for average CRUD apps. Though, I have been exploring various frontend libraries, and I haven't found one I absolutely adore yet. Hated Angular, React is tolerable (never tried Next.js), HTMX provided little over vanilla JS, and so on.
I have not tried Elixir, but in your opinion, what do you think makes it so great?
Sounds like you need to sell it better ;p
The Elixir live view model to me look like one of the only sane programming models for modern web development right now... Otherwise your best choice still remains to be server side rendering.
> Otherwise your best choice still remains to be server side rendering.
?? Phoenix Live View IS server side rendering...
Yes. I wasn't implying live views are not this, I was trying to say react, vue, angular, svelte, next.js, solid, preact, alpine.js, ember, backbone, lit, mithril, stimulus, knockout, aurelia, polymer, riot, inferno, marko, dojo have a terrible programming model and anything with server side templates is a vast improvement.
Don't know how much you have used ember, but I disagree, it's quite sane as a programming model and ember data is still ahead in terms of developper comfort for client apps.
I think they more specifically mean server side rendering of react components vs an SPA.
Interesting article, but I had to scroll all the way to the bottom to find what you actually built. I consider this important information, because the right tool for the job will depend on what the job actually is!
(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.
Oban is great, but for most cases you don't need it. In languages with a less good concurrency model we are used to needing some form of library or system to manage "background jobs", but in Elixir you can just spin up some GenServers under a supervisor to do work. Start there and only use Oban if there's some form of consistency/resumability guarantee that you need.
> Oban is great, but for most cases you don't need it.
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
> lose their state if a pod goes.
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.
saem idea, different levels of the abstraction
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
Oban is good but they should have a more reasonable tiers for their paid offering, the Pro plan is quite steep and is a bit all or nothing.
we operated for 4 years before we switched to pro. you get quite a bit out of the free version. we only switched because we wanted the rate limiting features of pro. plus $100 month is cheap if you're dealing with the problems that pro solves for you
With GenServers, what happens if you pod/machine crashes? You lose all the unprocessed jobs. Oban gives you safe retries, and guarantees consistency. If you're using a relational DB, I would infact suggest to start with Oban, and then take a look at the jobs and see if you are okay with losing jobs and move to GenServers.
For a startlingly large number of use cases, you don't even need to go that far; the built-in task system can typically cover almost all the use cases you'd reach for simple background processing, and exposes an interface very similar to the promise interface in other languages
I haven't found Oban difficult to work with and it has the added benefit of ensuring your jobs are run only once. There is also the cron functionality that I find really useful for scheduling.
It's a pity the author didn't decide to offer a trial without attaching a credit card. I get it, we had these discussions here many times. But as a person that could potentially subscribe, I'm baffled at the choice.
You could argue that I'm not really willing to subscribe if I'm not willing to provide my CC details yet. But it doesn't work this way. Before I subscribe to a new service, I really like to know it well, to have a kind of emotional relationship to understand what it is giving/saving me. "Give me you CC or get off" makes me not even want to try.
Subscribe to what, it's a blogpost
At the end of the article, I’ve highlighted the app I built with Phoenix, which is what he is referring to.
you can opt in for a 3-day free trial without needing to add a credit card after signing up.
Not everyone has VC funding where profit does not matter.
This isn't a debate about whether to offer a trial period or how of one to offer. This is a debate about forcing people to give you payment info for a free trial.
Requiring a credit card for a free trial is a technique to trick people into paying for a subscription when they normally wouldn't have chosen do do so after the trial period.
Not taking VC funding doesn't make this kind of dark pattern any less scummy. Fundementally you are trading some voluntary customers (people who don't like these tactics) or involuntary customers (distracted, busy or lazy people who forget to cancel.) When I see a company that does this, it tells me that they care about extracting value from the market than providing value to customers.
I completely agree. Requiring credit card info for a free trial often feels like a dark pattern designed to trap users into paying. I’m taking a different approach with my product by offering a 3-day free trial that doesn’t require a card, and a 14-day free trial for serious users. I want users to try it without any pressure or tricks and make a decision based on the value they experience, not because they forgot to cancel.
After Elixir announcing being "feature complete" a few years ago, and then Phoenix going down the LiveView path for quite sometime ... I feel like the Phoenix/Elixir stack became less exciting to me.
Hope to be wrong though. Erlang based systems are really interesting and under appreciated.
> I feel like the Phoenix/Elixir stack became less exciting to me.
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.
hasn't elixir kept innovating? The whole static typing/inference system seems pretty cool and keeps improving.
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...
Can you explain more? What became less exciting and why exactly?
It just felt like momentum slowed and/or there was less PR about Elixir/Phoenix.
But I could be completely wrong (or have the wrong perception).
Note: not at all suggesting hardwork/progress isn't being made.
The pace of new things coming to the ecosystem hasn't slowed at all, but it's happening beyond the language itself now.
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.
I've been developing full-time in Elixir / Phoenix for the last 6 years. I can assure you, momentum in the ecosystem has not slowed at all since the language was declared to be "feature complete".
In your defence, the choice of wording is confusing and that particular announcement did have a sense of “game over”ness to it.
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.
Elixir and Phoenix are as big as they ever will be. Around 25% of the size of the Rails "mindshare". But still I love the Elixir stack to death, it's so wonderful.
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.
This artile seems like AI generated, with vague content and , at least `Oban` is not phoenix build in: its a 3rd package.
Thanks for your feedback! Yes, Oban is a third-party package, but it’s built for Phoenix, which is what I meant in the article. Also, the article is not AI-generated. I’ve mentioned the app I built with Phoenix at the bottom to give context from real experience.
Working with Phoenix, and even more so Elixir and OTP, has been a great joy at a similar to almost the same level I had when transitioning from DotNet to Ruby in 2010 for my experience.
There are still some rough edges, and the job market might be more challenging, but overall I feel anything Elixir related at the moment provides for a high quality filter - both in terms of job opportunities and teams as well as the general product development experience.
I have been pretty happy with Elixir - the syntax takes getting used to, but I'm usually impressed by its elegance.
Phoenix I'm mixed on - it has a few things that "just work" and I'm happy about, but being an opinionated framework I find myself bumping into those opinions the more I want to do things my own way. Usually there's an escape hatch, but being new to both Elixir and Phoenix it's not always obvious to me how to do things when the happy path fails.
Anything PHP and you going to have bad time once you need concurrency. This time will come sooner or later.
The best, most popular serverless platform? There are stacks much worse than PHP, like JVM for example ;)
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!
Request-level concurrency has always scaled well. As for lightweight concurrency, have you worked with PHP Fibers? https://medium.com/@binumathew1988/leveraging-php-fibers-for...
I'm taking one look at Elixir and I'm not sure how it's supposed to be an improvement from Ruby? The readability and syntax seems to be a step backwards, so I'll stick with Ruby/Rails, thanks!
These "why I chose articles" can be summed up adding: because I like it more and I cherry picked some facts for justification.
Exactly, this is all blogspam at this point. Ignores all the features available in Rails so he can pick Elixir/Phoenix the “winner”.
that’s fair, though the intention wasn’t to dismiss rails or crown a winner. it was more about sharing a personal experience with elixir and phoenix for a specific use case, not a comparison to discredit other frameworks. i haven’t discredited rails, but features like fault tolerance and the beam make phoenix especially robust. i also mentioned that rails is a beautiful framework, i just chose what felt best for my project.
liveview feels a bit too magical
client disconnects, state desyncs, then reconnects, then liveview figures out via crdt and other things how to accurately diff the state
feels like i have to trust it too much - i'd have a lot more confidence if people were vocal about how they are running it at scale, battle-tested etc. etc.
shopify is straight up yolo running rails edge, which is a crazy endorsement
I watched a few demos and it is clearly magic and I was very impressed. Though I can't picture how a more standard run off the mill web app would be built with it.
My biggest problem with Elixir is the lack of support for 3rd-party libraries and the small community. I love the idea of it, but every time I try to ship a real project in LiveView, I'm left feeling like the community is not that mature. Maybe coming from a Go backend React frontend stack, that might be the case, but maybe for quick CRUD apps, it's great.
Elixir is pretty "nifty", and has Rails feels. I have worked on and seen its performance compared to scaled up Rails application. The BEAM / OTP is a very cool system to program on top of. I think it would be a great underlying system to develop a consciousness for AI systems with its concurrency paradigms and message passing, node connecting, other builtins. I'm not sure if the AI/ML focused Elixir projects like Nx have really taken off, but again, an Elixir based system that accepts numerous connections, passes messages around like exciting synaptic communications between functions... it just seems cool, maybe just on paper...
What do you mean "consciousness for AI systems"?
When you consider the message passing paradigm, I can envision how that simulates neuro-chemical communication between neurons (now here being functions that do things). So there is a design for communication between functions, then there are memory storage and information retrieval parts of the system, short-term RAM, long-term HD/SSD, databases, cache-systems, where relevant information can be and become manipulated. Long and short running processes, acceptance of fail-fast and that communications can fail and that's just part of software system life (I assume also a similar idea in the human brain, don't you find yourself forgetting something you were just thinking about?). There is then the external part of the system, accepting inputs from the outside.
The message passing paradigm is called the "Actor Model" and was invented in the 70s IIRC. It's available in most programming languages and it's not something exclusive to Elixir by any means.
https://en.wikipedia.org/wiki/Actor_model
Not exclusive to Elixir, but the BEAM was built from the ground-up around Actor for concurrency. Almost all other popular language ecosystems have it bolted on over time (with varying degrees of success) or relegated to a third party library. It's very natural and ergonomic in Elixir, because it's the paradigm of choice in the underlying vm.
Goroutines probably come closest.
> It's very natural and ergonomic in Elixir, because it's the paradigm of choice in the underlying vm.
Thank you, this is the key factor -- a fundamental design decision that influences the foundation.
Correct, it's not strictly unique to this. Even Ruby has it, but Ruby does not have BEAM/OTP.
Smalltalk was a fun language to work with, albeit academically.
Having built a mediumish soft realtime queue processing solution on rails I gotta say it was not great. If we didn’t kinda grow into it I would not have chosen ruby
Thanks for sharing. Yeah, I think that's a problem with bolted on functionality. Did you end up building a new version with a different language? What kind of problems did you encounter that made the solution "not great"?
Just curious, what libraries did you miss in particular compared to Go?
As much as I love node and typescript i am forever bummed it never achieved a railsy or Laravellian framework
True, the closest thing i like in the node.js backend world is nestjs. It’s a solid framework for building apis, but as an mvp framework, it’s not quite on the same level as laravel, rails, or phoenix.
I used to feel the same way, but at a certain level of Node.js experience I came to prefer the backend JavaScript idiom. It's much lighter and more pragmatic, and gives the knowledgeable engineer a lot of flexibility. So stick with it.
Have you checked out t3 stack? Curious which pieces are missing from that that you'd deem critical
In the era of vibe coding just use the fastest servers. I wrote my last api in Rust and it wasn't any harder than anything else, it's wicked fast and stable.
After doing that, it seems a lot of the higher level languages will go away soonish
curious what your process was for hardening your API for security? or is that still a pending step?
TBH probably easier to vibe-code securely in statically typed languages like Rust vs. something like Elixir. Probably my biggest Elixir complaint tbh.
I'd rather fix AI slop in simpler languages, thank you very much.
And by the time performance is a startup's concern in majority of cases, they would have to rewrite most of the code anyway, including critical parts, so why not start with a language that's easier to find developers?
Doesn’t the LV approach suffer from latency issues?
If I understand correctly all state is managed by the server, which means even the most trivial UI interaction needs a roundtrip. Not to mention the cost of managing the state and connection of every client. So how does that work in practice?
latency is minimal because liveview sends only dom diffs, not full page updates. most interactions feel instant. each connection runs as a lightweight beam process, so managing per-user state scales efficiently. for very high-frequency ui updates, some client-side js may still be needed, but for forms, lists, modals, and live updates, liveview is smooth and responsive.
The size of the diff and the latency of the underlying transport layer are independent. If your user in NY clicks a button that has to go to your server in SF, you pay for that ping both NY->SF and SF—>NY for the reply.
Same goes for whether they’re on some flakey mobile connection in a car or on a train.
It’s also super easy to accidentally send a ton of data down the wire on component mount. I worked on a massive LiveView app at a company you’ve heard of and these kinds of issues were a problem the whole time.
You also give up the standard stateless HTTP request/response model when you go with LiveView. This is not necessarily bad, but people should be aware that they’re turning their stateless web tier into a stateful web tier. It’s an entirely different model (and in my opinion, more challenging).
LiveView is cool technology but I don’t want people to overlook the fact that it has some sharp edges you have to be aware of when building large products.
In practice it's mostly fine actually.
But yes, for interactive elements it's not optimal. They have some JS helpers for simple things but you may need to drop down to JavaScript hooks yourself if you want do better.
I've been playing around with Hologram, which transpiles Elixir to JavaScript. It's very early days but it has the potential to be a much better solution than LiveView.
https://hologram.page/
Last I checked, Erlang strings were represented internally as a linked list of integers, one int for every character.
That worked, but I felt like not every efficient, as web is very text heavy.
Has that changed in the later versions?
I believe that's still true of Erlang, but Elixir has UTF-8 encoded strings. In practice the only time you need to use Erlang strings from Elixir is if you're using an Erlang API.
In Elixir it's bytestring.
Both Erlang and Elixir support two types of text representations.
The first is a linked list of Unicode codepoints (also called a character list or a charlist for short). In Erlang, this is written using double quotes. For example, "abc" in Erlang is actually the list [97, 98, 99]. In Elixir, the same representation uses single quotes: 'abc' is a list of integers.
The second is a UTF-8 encoded binary. In Erlang, this is written using the <<"abc">> syntax. In Elixir, double quotes represent UTF-8 binaries, so "abc" is a binary.
So:
Erlang "abc" = list, <<"abc">> = binary
Elixir 'abc' = list, "abc" = binary
For efficiently handling textual data, Phoenix extensively utilizes iolists (https://hexdocs.pm/elixir/1.15.8/IO.html#module-io-data) to eliminate copying. It's used in performance critical areas such as generating http responses and template rendering. In general, on the Erlang VM, iolists are a first-class, widely used data structure for efficient I/O.
Not knocking the choice but:
> 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.
do real time updates and two way communication work out of the box with a cluster as well?
Laravel - https://laravel.com/docs/12.x/queues
All good, but did you know that Next.js is a full stack framework? You can have backend and frontend in the same code base. You don't need Laravel if you use Next.
Next.js is still missing lots of backend stuff. Background jobs, cron jobs, queues, etc.
that’s true, next.js does a great job offering a full stack experience. the difference with phoenix is that it’s built on the beam, which gives you concurrency, fault tolerance, and real-time capabilities out of the box. liveview also lets you build interactive frontends without managing separate api layers or client frameworks, keeping everything unified and fast.
BEAM / Erlang / OTP / Elixir feels different:
- 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
> You don't need Laravel if you use Next
But you do need to solve a lot of stuff that Laravel already solves for you.
What matter most is having enough code out there for ai model to learn and study it so people can build with it.
Chris McCord directly addresses this in his recent ElixirConf talk. There's a threshold amount of training data needed for LLMs to work well, and Elixir more than clears it. Beyond that threshold, having more data doesn't make a tremendous difference. This means the "frustration gap" for newcomers essentially disappears - people who heard "Elixir is good" can now just ask an LLM to build something and start immediately, easing their way into understanding functional programming paradigms in order to be productive. I use Claude Code daily for Elixir development and it understands the language perfectly. The real strategic advantage is that while other ecosystems scramble to solve agent orchestration problems, Elixir/OTP already solved them decades ago. Lots more here: https://www.youtube.com/watch?v=6fj2u6Vm42E&t=1321s
The product that OP is building is a todo list. Rails or Laravel would have both worked just fine. Elixir/Phoenix are neat technologies, but I get the sense that this decision was primarily "because I want to" rather than any particular selection methodology (which is fine - you do you, OP).
It’s not just a simple todo list. The product includes advanced features like goal tracking, minimal project management, a streak system, daily task resets with a 3-task limit, and AI-powered task creation that can break tasks into subtasks. Users also get individual profiles to share streak progress and build habits. On top of that, we’re working on additional features like adding team members to projects and real-time collaboration. While it’s certainly possible to build these in Laravel, implementing them is not as seamless or straightforward as it is in Phoenix.
Why not Crystal and one of its web frameworks?
I worked with Elixir/Phoenix for over 3 years, and I recently started to learn Crystal, mostly to create CLI apps or other programs where I want to create a simple executable binary. I wanted a more expressive language than Go, and easier than Rust.
Out of curiosity, I took a quick look at some of the web frameworks available, they are interesting. Lucky's Components looks pretty good, but I still prefer Phoenix's Components because the syntax make it very close to raw HTML. Compilation is not incremental and is single threaded which means I have to wait at least 5 seconds every time I make a change (this was on a minimal project). It's not that bad, but compared to Elixir/Phoenix where it's almost instantaneous, it makes a difference.
Still, Crystal is an awesome language, and if for one reason Elixir was not a choice for a web project, I would definitely consider a Crystal framework.
Until you realize you're reimplementing Rails :)
Having done both for years, I can say confidently that you can use Phoenix without recreating Rails. The differences are important, and IMO Ecto is a much better approach to interacting with a database than ActiveRecord. I've also never seen a bug in my application due to upgrading Ecto, and I definitely can't say that about ActiveRecord.
I am curious how much longer NextJS will last considering it is a lock-in vehicle for Vercel.
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?
the sentiment around NextJS is terrible, I have rarely seen something go from "oh this might be cool" to "stop pushing this badly engineering crap on me" so quickly. Yes, it's widely used and that's to be expected given the amount of money spent in promoting it, but it's not loved by any mean and I see this as a fatal flaw that they'll have to reckon with sooner or later. It's so bad that it worsened React's reputation by association - React already had some issues to care about, but they went in Next's direction, and people have noticed
There's absolutely no reason to use Vercel. I've always run Next on our own servers, for multiple clients and some very complex projects. Page Router or App Router.
Ironically I choose to deploy our nextjs projects on Vercel because interacting with our inhouse stack means involving an infrastructure person who wants to critique and research how you’re developing your app. With Vercel I can just deploy a project and don’t have to ask Steve what the best set of server tools I need and then work with Steve on the monolith of Kubernetes configs to get it deployed. And while I like Steve, adding him to a project is a huge time sink and cost center all it’s own. Even if I get platform access to self serve, Steve will be there gating me for every little permission I need.
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).
I can see why elixir over rails but do you guys know about type checking?
One benefit i found over rails was just some of the libraries were more modern. I'm not a backend developer, so maybe I'm just not skilled enough to know how to do these things, but I found rails libraries tended to be dated and missing more modern features.
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.
A lot of ruby gems have definitely seemed to suffer from brain drain the last few years.
It's worth noting that the creator of Elixir was also an author of Devise.
> the gem Devise didn't natively support both
Sounds like a Devise problem.
Sounds like you're saying it sounds like a Devise problem.
Great. Now tell me how you plan to scale a dev team who all know Elixir?
Give your new hires my free course: https://liveviewcrashcourse.com
If the only metric you care about is "scaling a dev team", use JavaScript. You're welcome.
I am not even sure that is true. Only if your main criteria is available resumes where the programming language is listed at all. JS has probably upper 90% there
Did I say it was?
I guess hiring a developer who knows rails or even laravel can easily pick up with phoenix.
by hiring people without the expectation to be already proficient in it, as long as they are willing and capable of learning it in a reasonable time
I don’t hire developers who are tied to just one framework. I prefer someone who has a solid understanding of a platform but also a mindset to learn new technologies. You don’t need a large team, just one or two talented developers on a good pay package can be more than enough, and in my opinion, it’s worth it.
Hiring is hard enough and you want to add this additional complexity? Okay.
1. Hire good developers
2. Teach them Elixir
3. Profit
> 1. Hire good developers
Are you giving this advice to every company in existent? Think about that for a second.
> It’s way ahead of both Rails Hotwire and Laravel Livewire. LiveView communicates through WebSockets
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.
You’re right. Hotwire (specifically Turbo Streams) does use WebSockets under the hood when available. And yes, Rails has background jobs, ActiveJob, and other robust primitives that Phoenix was inspired by.
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
This is actually one of the huge tradeoffs and pitfalls of LiveView. Its websocket model is all or nothing.
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.
(Disclosure: I'm building Hologram)
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
that’s a really valid point. liveview’s websocket-first model can feel heavy for quick, intermittent interactions like mobile data entry. it shines when the user is continuously connected, but those short bursts do expose rough edges. hotwire’s approach of progressive enhancement and optimistic rendering handles these scenarios more gracefully since the view works independently of the connection. phoenix and liveview are still amazing, but improving these “short session” experiences would make it even stronger.
Ya, this was not worded well at all (and more likely just not well researched (in the article, I mean). The difference between hotwire/livewire and LiveView is that with LiveView you get a "live" connection to persistence BEAM process which comes with benefits like not having to rebuild things (like the current user) on each request and storing ephemeral state on the server (if you need it). Of course there are trade off like PWAs are not fun in LiveView (you likely just wouldn't do it, I never have).
> "live" connection to persistence BEAM process
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?
The guides are the best place to learn about LiveView itself. Since guides are always included as part of the docs (reference docs) people always tend to shy away from them (not saying you are, it's just a thing with people it seems):
https://hexdocs.pm/phoenix_live_view/
Oh also wanted to point out that while there has been an ongoing effort for LiveView Native, it is not there yet (I actually haven't heard anyone talking about it in quite a while). I'm not too in the Rails world so I don't know how good Hotwire Native is, but I assume it's much further along than LV Native, so that's a big thing if you need that. No idea about LiveWire as I've never even been in the Laravel world.
The author is a self-professed front-end developer according to LinkedIn, which may be influencing experience with backend systems and functionality. I was wondering really why this terse post is sky-rocketing to #1 today, hopefully we get some good discussion from the community.
Any kind of comparison of popular frameworks activates all the dev nourons in my monkey brain.
Yeah I feel like most devs still think of rails as it was about... 8 years ago.
Yeah it has become much more solid recently
18
Websockets are the wrong choice. SSE is the way to go. That or your own UDP protocol.
What's the advantage of using SSE versus WebSockets in this instance?
It's standard http so you don't have to build your own bad version of http on top of it. It's handles disconnects for you. You can use the browsers built in compression over the life of the connection. You have access to brotli/zstd without having to ship it to the browser first (and it's the C++ version).
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).
Hotwire lets you use either. https://turbo.hotwired.dev/handbook/streams