Ruby on Rails and Elixir Together

Ruby on Rails and Elixir Together article image cover

Your Rails app is doing its job. Customers use it, the business depends on it, and your team knows the code. But now you need live updates, more connections, or background workflows that stay responsive when traffic spikes. Does that mean starting over?

Often, you can keep Rails and bring in Elixir where it helps most. Rails continues to handle business logic, admin tools, payments, and everyday product features. Elixir takes on a specific workload, such as chat, live dashboards, or coordinating many tasks at once.

This is a hybrid architecture: two technologies working together, each with a clear role. It gives you room to improve the product without putting years of working code through a full rewrite.

The potential benefits are practical:

  • Keep existing Rails features, gems, and business rules.
  • Move a demanding workload without rebuilding the whole application.
  • Add real-time features with Phoenix Channels or LiveView.
  • Isolate failures and define how individual processes recover.
  • Scale the busy part of your system separately.

The key word is “potential.” A second runtime adds work, too. The goal is to solve a real problem well enough to justify that extra complexity.

How do Ruby on Rails and Elixir differ?

Rails is a web framework built on Ruby. Elixir is a programming language; Phoenix is its main web framework. Comparing Rails with Elixir usually means comparing Rails with an Elixir/Phoenix stack.

Rails makes common product work straightforward. Its conventions and libraries help teams build accounts, billing, forms, and APIs without assembling everything themselves. Elixir runs on the BEAM, the runtime behind Erlang, with a model built around lightweight processes that exchange messages.

AreaRuby on RailsElixir / Phoenix
Programming styleObject-oriented Ruby and Rails conventionsFunctional code, pattern matching, message passing
ConcurrencyThreads, operating-system processes, and job workersLightweight processes managed by the BEAM
Real-time featuresAction Cable and the wider Rails ecosystemPhoenix Channels and LiveView
Data accessActive RecordEcto, with explicit queries and changesets
Everyday strengthsBusiness apps, admin tools, commerce, APIsConnected clients, live interfaces, concurrent workflows
Team considerationsFamiliar tools for an existing Rails teamNew language, runtime, and operational skills

Concurrency is where the difference often matters. Think of thousands of users staying connected while the application receives events and sends updates. Elixir gives developers a natural way to organize these separate activities.

Phoenix famously demonstrated two million WebSocket connections on one server in 2015. That was a specific benchmark with limited message activity, not a promise that any production app can support two million active users.

Rails also supports WebSockets through Action Cable. For interactive pages, Phoenix LiveView keeps application state on the server and sends compact updates to the browser. It can reduce custom frontend code, though network latency and application design still affect responsiveness.

Practical ways to connect Rails and Elixir

Start with one feature that has a clear boundary. A notification service is easier to separate than a workflow that touches accounts, billing, inventory, and permissions at every step.

Ruby on Rails handing off selected workloads to an Elixir service

Before choosing the connection method, decide which application owns the data and business rules. Otherwise, a small service can turn into two applications that constantly depend on each other.

APIs for direct requests

HTTP APIs are a sensible starting point when Rails needs an immediate answer from Elixir, or the other way around. They are familiar, easy to inspect, and usually enough for an initial integration.

Consider gRPC if your team needs typed contracts or streaming and can support the tooling. Either way, define authentication, timeouts, error responses, and retry behavior. A fast service still needs a plan for slow or unavailable dependencies.

Events for background work

When Rails does not need an immediate response, it can publish an event for Elixir to process. For example, an order update might trigger notifications or refresh a live dashboard.

Use durable delivery where losing an event would matter. Make consumers safe to retry, so receiving the same event twice does not send two invoices or apply a change twice. An outbox pattern can help connect database changes with reliable event publication.

A shared PostgreSQL database

Both applications can access the same PostgreSQL database. This can make an early integration easier because the data is already available, but it also couples the services to the same schema.

Give one application ownership of migrations and define who can write to each table. Remember that Rails callbacks and validations do not run when Elixir writes directly to the database. Important rules need protection wherever writes happen.

Ecto’s create_if_not_exists only skips creating an existing object. It does not coordinate two migration systems or prevent incompatible schema changes. Keep changes backward-compatible while both applications are running.

Keeping a Ruby component callable

Sometimes a useful Ruby library or custom rules engine needs to stay. Calling it through a small service is one option; a process bridge may also be worth evaluating.

Keep the runtime boundary clear: an external Ruby interpreter remains an operating-system process, not a lightweight Elixir process inside the BEAM. Its memory use, crashes, and lifecycle still need deliberate handling.

What changes for developers and operations?

The biggest adjustment is learning a different way to structure code. Ruby developers will recognize many web concepts, but immutable data, pattern matching, Ecto changesets, and process supervision take practice.

Start with a small service and pair newcomers with someone experienced in Elixir. Clear examples and code reviews help the team build good habits before the new service becomes business-critical. Avoid setting a fixed “productive in two weeks” expectation; the learning curve depends on the people and the workload.

AI coding tools can help explain unfamiliar code, draft tests, or suggest translations between Active Record and Ecto. Treat their output as a starting point. Check library versions, queries, transaction boundaries, and process behavior, especially when generated code looks convincing but skips an important edge case.

Testing needs to cover the connection between applications. Check request formats, event payloads, permissions, and failure cases. What happens if Elixir restarts halfway through a task? Can Rails keep serving customers? What happens when the same message arrives twice?

Deployment also becomes a shared responsibility. Each service needs a repeatable build, monitoring, logs, and a rollback plan. Containers can help package the runtimes, but adding Elixir does not require Kubernetes. Use infrastructure your team can comfortably operate.

Elixir’s supervision trees let you configure how child processes restart after failures. They do not automatically restore lost in-memory state or finish interrupted business operations. Durable jobs, persisted data, and recovery logic still matter.

How do you know the hybrid approach is working?

Measure the current problem before moving anything. Useful baselines include response time under load, queue delay, memory use, connection count, infrastructure spend, and time spent handling incidents.

Then compare the new service against the same workload. A lower server bill is useful, but so is a feature that stays responsive during busy periods or takes less effort to maintain. Include the cost of running and supporting both stacks in the comparison.

For example, a SaaS product might keep subscriptions and account management in Rails while Elixir handles live notifications. A manufacturing tool might preserve its Ruby pricing rules while moving connection handling and update coordination into a separate service. These are possible designs, not guaranteed performance outcomes.

Roll out gradually. Send a small share of traffic to the new service, watch the results, and expand when behavior is predictable. Test rollback with real data changes in mind: sharing a database does not make every change reversible.

If slow SQL queries are the real bottleneck, moving the application code may achieve very little. Fix the constraint you can measure, then decide whether another runtime is the right next step.

Key takeaways

Rails and Elixir can work well together when they have clear responsibilities. Keep the parts that already serve your product well, and introduce Elixir where its concurrency model or real-time tooling solves a specific problem.

Start small, define data ownership, plan for failures, and measure the result. A successful hybrid system should make the product easier to grow and support, with benefits that outweigh the extra operational work.

Need help deciding where to start? Elixirator can help you assess your Rails app, identify a suitable first service, and plan an Elixir integration around your existing product. Feel free to contact us!

FAQ

Can I add Elixir without rewriting my Rails app?

Yes. Keep Rails running and introduce Elixir for one feature or service. Connect them through APIs, events, or carefully managed database access, then expand only if the results justify it.

Is Elixir always faster than Rails?

No. Elixir is particularly useful for many concurrent activities and long-lived connections. Actual performance depends on the workload, database, external services, and implementation. Benchmark the feature you plan to move.

Can Rails and Elixir share a database?

Yes. Active Record and Ecto can use the same PostgreSQL database. Agree on migration ownership, table access, and validation rules so changes in one application do not break the other.

Will Elixir replace Sidekiq?

It does not have to. Keep existing jobs in Sidekiq unless there is a reason to move them. A BEAM process alone does not provide durable job storage or guaranteed completion.

When should we stay with Rails alone?

When Rails meets your needs and the team can maintain it comfortably. Improve queries, caching, job design, and existing real-time features before adding another stack without a clear benefit.

elixir
elixir development
ruby on rails
phoenix
real-time systems

Ready to Build with Elixirator?

Prefer a quick call?
Photo of Alex Danyliak, Client Partner at Elixirator

Alex Danyliak

Client Partner at Elixirator

“Whether it’s a one-off consulting gig or a full dedicated team, let’s chat about how Elixirator can help you build something reliable, performant, and future-proof.”

Ready to Build with Elixirator?

Prefer a quick call?
Photo of Alex Danyliak, Client Partner at Elixirator

Alex Danyliak

Client Partner at Elixirator

“Whether it’s a one-off consulting gig or a full dedicated team, let’s chat about how Elixirator can help you build something reliable, performant, and future-proof.”