Choosing Phoenix LiveView

The difficulties deciding between Phoenix LiveView and traditional web frameworks  

If I need to ship a new product in a week, Phoenix LiveView is my go-to framework.

Elixir LiveView is incredible, and an alluring choice for software leaders looking to develop applications super fast. However, in recent experience, I’ve seen teams hit some pitfalls.

The trick is to understand what Elixir LiveView excels at, and what it doesn’t.

TL;DR: LiveView is perfect for internal tools and simple apps. Skip it for complex UIs, offline-first apps, or if your team doesn’t know Elixir well.

Oban Pro
Oban Pro is a powerful job queue for Elixir built with LiveView.
# This is what a very simple LiveView component looks like.

defmodule DemoLive do
  use Phoenix.LiveView

  def render(assigns) do
    ~H"""
    <div>
      <div>
        Counter: {@counter}
        <button phx-click="inc">+</button>
      </div>

      <MySortComponent.display 
        lists={[first_list: @first_list, second_list: @second_list]} 
      />
    </div>
    """
  end

  def handle_event("inc", _, socket) do
    {:noreply, assign(socket, :counter, socket.assigns.counter + 1)}
  end
end

The Good

Avoid Javascript and Typescript

Skip the Typescript or Javascript. Avoid the monthly npm meltdowns and security nightmares. You can almost write your entire application in Elixir, and Phoenix LiveView will handle the rest.

Avoid “Hand Off” Between Frontend and Backend

The mental model of a LiveView component is incredibly simple.

How long does your engineering team spend writing OpenAPISpex, carefully crafting the API contract between your frontend and backend? With LiveView, you don’t have to; there is no “hand off” between frontend and backend. No argument or discussion about what the JSON payload should look like, no “glue code” to write. There’s no ALT-TAB to a different IDE when you push a new endpoint. It’s just there, in one .heex file.

UI Feels Super Responsive

It’s fast. It feels snappy and responsive, in a way heavy React or Vue applications often don’t. Most of the time, your browser is rendering static HTML, so it feels as snappy as a static HTML website (like this one). There’s no skeleton loading states, no flickering, no re-rendering of the entire page when you click a button.

Easy to Test

You can test your LiveView components in isolation, without having to spin up a full web server. You get what would normally be considered “E2E tests” without the hassle of orchestrating a full test environment. No juggling Selenium servers and no paying for Cypress licenses.

Elixir Livebook
Livebook is a multiplayer Jupyter-like notebook environment for Elixir built with LiveView.

It Handles “Multiplayer” Interfaces Really Well

LiveView is a great fit for building “multiplayer” interfaces. You can build a chat application, a real-time collaborative document, or a real-time multiplayer game with ease. Because it’s built on top of WebSockets, it’s incredibly easy to build these types of applications, and the Phoenix PubSub system is built to handle the complexity of scaling to thousands of concurrent users.

It Handles “Moment-to-Moment” Interfaces Really Well

If you are trying to build an application where the backend is going to be regularly pushing data to the frontend frequently, LiveView is a great fit. Anything like a realtime dashboard, live-updating graphs and charts, or any sort of moment-to-moment interface is a great fit for LiveView. This is why many Elixir developers use LiveView to build realtime dashboards and admin interfaces.


The Bad

Complex Custom UI Elements

If you need something more complex than a simple button and some HTML forms, I’ll be honest, now is when you’ll have to pick a side. Performing complex UI interactions like…

  • Data tables with sorting, filtering, and pagination
  • Chat windows
  • Drag and drop interfaces
  • Multiple nested modals
  • Interactive graphs
  • Interactive maps

…are all possible, but this is not what LiveView excels at.

You’ll find yourself wrestling with complex “bridging code” and you’ll probably lose out on the benefits of LiveView.

Disconnected LiveView

LiveView Struggles with Network Instability

If you expect your users to have patchy internet connections, you’ll find LiveView struggles to handle disconnects gracefully. If you expect your users to be out-and-about while using your product, it’s unlikely LiveView will be a good fit. Any sort of navigation or mapping application is likely to be a poor experience.

# You'll want to ensure you have sticky sessions enabled on your load balancer.

upstream phoenix_backend {
    ip_hash;  # Routes same IP to same server
    server 10.0.1.1:4000;
    server 10.0.1.2:4000;
    server 10.0.1.3:4000;
}

DevOps and Infrastructure Can Be More Complex

You’ll probably need to ensure you have sticky sessions enabled if you’re load balancing your application. This means reconnects are directed to the same server instance, rather than a new one. This is a simple configuration change, but it’s one that you’ll need to be aware of.

The way LiveView handles sessions and authenticating sockets is not immediately obvious, so you’ll need to be aware and ensure you have a good understanding of the underlying mechanisms.

In addition, many reverse proxies like Nginx will not support WebSockets without additional configuration, and long-lived connections may get terminated after a short timeout by default. Websockets are also a little more difficult to debug than traditional HTTP requests, so you’ll need to be aware and have good backend logging.

# You'll want to ensure you have sticky sessions enabled on your load balancer.

resource "aws_lb_target_group" "phoenix" {
  stickiness {
    type            = "lb_cookie"
    cookie_duration = 86400
    enabled         = true
  }
}

Third-party Component Support

Third-party support is still lacking, so if you need a really nice calendar UI for example, your choices are limited. You’ll probably find something but it’s unlikely to be a perfect fit. If you’re willing to make-do and sacrifice some features, you’ll probably be fine.

You’re Building a Complex Application Anyway

If you only need a few custom UI elements, you’ll probably be fine, as long as they’re not going to be deeply nested. If you carefully choose a small number of key UI components that are core to your product experience, it might still be worth it.

Complex custom UI elements will require you to pick one of the following trade-offs:

  • WebComponents without a framework

    You can develop web components without a framework, but you’ll need to write a lot of boilerplate to get what React or Vue gives you out of the box.

    class HelloCounter extends HTMLElement {
      constructor() {
        super();
        this._count = 0;
        this.attachShadow({ mode: "open" });
    
        this.shadowRoot.innerHTML = `
          <span>Hello world! Count: <span id="count">0</span></span>
          <button id="inc">Increment</button>
        `;
      }
    
      connectedCallback() {
        this._countEl = this.shadowRoot.querySelector("#count");
        this._buttonEl = this.shadowRoot.querySelector("#inc");
    
        this._onClick = this._onClick.bind(this);
        this._buttonEl.addEventListener("click", this._onClick);
      }
    
      disconnectedCallback() {
        this._buttonEl.removeEventListener("click", this._onClick);
      }
    
      _onClick() {
        this._count++;
        this._countEl.textContent = String(this._count);
      }
    }
    customElements.define('hello-counter', HelloCounter);
    
  • WebComponents with a framework

    I recommend the fantastic Lit framework from Google. It’s a great way to develop web components with a framework, and it’s easy to learn. The trade-off is that you’ll be writing Typescript, and nesting components is very complex.

    import {LitElement, html} from 'lit';
    import {customElement, property} from 'lit/decorators.js';
    
    @customElement('my-element')
    export class MyElement extends LitElement {
      @property()
      version = 'STARTING';
    
      render() {
        return html`
        <p>Welcome to the Lit tutorial!</p>
        <p>This is the ${this.version} code.</p>
        `;
      }
    }
    
  • React or Vue

    You can render React components directly in your LiveView using the phx-hook attribute. Again, you’ll be writing Typescript, and if you want to benefit from local state management, you might find yourself wrestling with the data model of LiveView, unsure where to store the state.

      <div id="react-root"
        phx-hook="MyCustomReactWidget"
        data-count={@count}
        phx-update="ignore">
      </div>
    

The Ugly

The Learning Curve; LiveView is Foreign to Most

LiveView is relatively new, and it operates in a way that will be unfamiliar to most frontend developers.

In fact, you’re likely to find backend specialists are more comfortable with the framework. LiveView uses Elixir and OTP’s GenServers as a primitive building block, and without strong understanding of how OTP processes, message passing, and concurrency works, you’ll find yourself struggling to grok the LiveView concepts built on top of them.

Even worse, Elixir itself is one of the most complex programming languages to master. While the syntax is simple and easy to initially pick up, the BEAM VM and the ecosystem are highly complex and quite different to anything else in the programming world. There are common programming patterns like the “early return”, “inheritance”, and “polymorphism” that are not strictly supported by Elixir, forcing developers to internalise completely different paradigms.

Hiring Can Be Tough

Elixir is still a niche tool. It’s not as popular as Python, JavaScript, or even Ruby so you’ll have to look harder to find experienced Elixir developers, especially in Australia! Adoption is rapidly growing, not least due to LiveView itself and Elixir’s unique strength for orchestrating AI agents and AI workflows.

However… Elixir Developers Are Highly Experienced

That said, one redeeming quality of Elixir, is that when you find someone experienced with the language, they tend to be more knowledgeable and senior than other languages. It is very rare for a junior developer to choose Elixir as their first language, and most of its denizens are highly experienced engineers who have learnt Elixir as an extension of strong pre-existing skills.

Google Trends
Google Trends shows LiveView has increased interest recently, but still trails majorly behind React, Vue and even Web Components.

In Conclusion

LiveView makes your developers many-times more productive than traditional web frameworks. However, this comes with a few caveats. You will not be able to use LiveView for every application you build. Be selective in your choices, and consider the following:

Where LiveView Shines: Internal Tooling

If you are already using Elixir and Phoenix, then using LiveView for internal tooling is a no-brainer. Using LiveView for simple admin interfaces and internal tools is a great way to get started with the framework.

Most of the downsides to adopting LiveView do not apply to internal tooling. You don’t need to worry about:

  • Product arguing that customers need that fancy UI element
  • Network instability
  • Complex custom UI
  • Performance or scalability issues

Many of Elixir and Phoenix’s community admin tools are built with LiveView, so you’ll be able to find a lot of inspiration and examples for your own projects.

  • LiveBook: A Jupyter-like notebook environment for Elixir built with LiveView
  • Ash Admin: A Powerful Admin Interface for Phoenix LiveView
  • Oban Pro: A Powerful Job Queue for Phoenix LiveView
  • Phoenix Live Dashboard: A Powerful Dashboard for Phoenix Applications
Ash Admin is a powerful admin interface for Phoenix LiveView.

Where LiveView Shines: Simple Customer-Facing Applications

If you’re building a simple customer-facing application, and want to optimise for time-to-market, you’ll probably love LiveView, assuming your team already knows Elixir!

I have frequently been able to deliver entire applications in just a few days.

Consider

If you’re not sure whether LiveView is a good fit for your application, here are a few things to consider:

  • Do you need to support older browsers?
  • Will your company’s existing infrastructure be able to support very long-lived WebSocket connections?
  • Is your application going to be a “multiplayer” interface?
  • Is your application going to be a “moment-to-moment” interface?
  • Do you need to support complex custom UI elements?
  • Is your team familiar with Elixir?
  • Do you need to handle network instability?
  • Do you need to maintain complex local state in the browser?

Get in Touch

If you have any questions or would like to discuss your project, please get in touch. I have extensive experience with both traditional web frameworks like React and Vue, and LiveView, and would be happy to discuss your project and whether LiveView is a good fit for you.

Book a Consultation

15 Minute Online Chat

Quick chat to discuss potential work.

Full Day Discovery Session

Day session to perform a technical discovery of your project and requirements gathering.

comments powered by Disqus