DEV Community

Alex Aslam
Alex Aslam

Posted on

Why We Replaced Rails with Elixir (And Regretted It)

"We rewrote our Rails app in Elixir—and it cost us 6 months of our lives."

Elixir promised us:
Blazing performance under load
🧩 Fault-tolerant systems that self-heal
💸 Lower server costs with lightweight processes

But after a year in production, we found the dark side of the BEAM. Here’s why we ultimately migrated back to Rails—and what we’d do differently today.


1. The Promises vs. The Reality

Promise: "Performance at Scale"

  • Expected: 10x faster response times under load.
  • Reality: Our CRUD endpoints were slower due to:
    • N+1 queries (Ecto doesn’t auto-include like ActiveRecord)
    • JSON parsing bottlenecks (no Oj equivalent)
# N+1 hell in Elixir
users = Repo.all(User)
Enum.map(users, fn user ->
  posts = Repo.all(from p in Post, where: p.user_id == ^user.id)
  %{user: user, posts: posts}
end)
Enter fullscreen mode Exit fullscreen mode

Promise: "Fault Tolerance"

  • Expected: Self-healing systems.
  • Reality: BEAM’s supervision trees don’t fix bad code.
    • A bug in our payment service still crashed—it just restarted mid-transaction.

Promise: "Lower Costs"

  • Expected: 50% fewer servers.
  • Reality: Our PostgreSQL bill doubled because:
    • Phoenix’s connection pooling was less efficient than Puma’s.
    • We needed more CPU to match Rails’ JSON rendering speed.

2. The 3 Biggest Pain Points

1. Ecosystem Gaps

What We Missed from Rails:

  • ActiveAdmin → Had to build admin panels from scratch.
  • Rails’ Migrations → Ecto migrations lacked change reversibility.
  • Gems (like Devise) → Elixir libs were less battle-tested.

2. Hiring Struggles

  • 10x fewer Elixir devs than Rubyists.
  • Onboarding took 3x longer—even for senior engineers.

3. Debugging Complexity

  • BEAM’s observability tools (:observer, recon) were powerful but opaque.
  • No equivalent to byebug—debugging meant tracing processes manually.

3. What Actually Worked Well

Real-time features (Phoenix Channels crushed ActionCable)
Background jobs (Oban was more reliable than Sidekiq)
High-throughput APIs (once we optimized JSON parsing)


4. When Elixir Is the Right Choice

🔹 Real-time apps (chat, gaming, live dashboards)
🔹 High-uptime requirements (99.999% SLA)
🔹 Teams with BEAM experience


5. What We’d Do Differently

  1. Hybrid approach: Keep Rails for CRUD, use Elixir for real-time components.
  2. Benchmark first: Prove Elixir’s ROI before full migration.
  3. Train the team: Invest in 3 months of Elixir mentorship.

"But Elixir Is the Future!"

Maybe—but future-proofing has costs. Our lesson?

  1. Don’t rewriteaugment instead.
  2. Measure bottlenecks before jumping stacks.
  3. Honor team DNA (ours was Ruby through and through).

Tried a stack switch? Share your story below—triumphs or regrets.

Top comments (0)