Lars Wikman changelog.com/posts

PETAL – the end-to-end web stack

what it is and why you might like it

There’s a new stack in town. PETAL. It destructures to

  • Phoenix
  • Elixir
  • Tailwind
  • Alpine
  • LiveView

(PETAL was coined by Patrick Thompson to describe a particular set of tools he was combining with good results. I’m just here to tell you about it.)

So what is it? Well, it helps you build web applications.

The “P”

So we take Phoenix, a web framework with heritage from Rails and the same kind of focus on developer experience and productivity without the kind of magic I’ve understood causes a lot of issues and confusion around Rails. I’ll have to take witness reports on that because I did Python and Django in the before-times. I find Phoenix more powerful and explicit than Django as well.

The “E”

Then we take Elixir. A developer-friendly high-level language in the Functional Programming school. Because of the people involved, Elixir has stylistic heritage from Ruby, but it is very much its own language.

(Changelog’s platform is built with Elixir and José Valim, the creator of Elixir, has been on the podcast 3 times.)

Elixir is built on an extremely well-respected runtime, the BEAM, which traditionally powers Erlang. The BEAM was built to do distributed systems at Ericsson, primarily for telecom use, which meant handling concurrency and maintaining good latency. It does concurrency very well for both multi-core machines as well as clustered distributed systems. It is an enormously capable virtual machine built for providing soft real-time performance. Whatsapp has built with Erlang to great success running an enormous system on a very small crew. With Elixir, we see companies like Discord that are repeating that success.

The “T”

Tailwind CSS is a well-liked CSS framework. I haven’t gone deep with Tailwind so I can’t speak to the power of it. But the JS Party podcast has covered it in the weirdest way possible and Thinking Elixir had a very good conversation around all of PETAL that I’d recommend.

The “A”

Alpine.js is a JavaScript framework by Caleb Porzio who built Livewire for PHP (inspired by Phoenix LiveView of Elixir fame). It is built to work well when you need strictly client-side interactivity and these live server-side rendering solutions just won’t do. It should give you something more convenient than vanilla JavaScript while mostly staying out of the way. Patrick Thompson covered a lot of LiveView + Alpine.js in his ElixirConf talk. Chris McCord (of Phoenix fame) also covers some of this at DockYard.

The “L”

LiveView. I dare say that this is the star of the show. It’s an increasingly important yet optional part of the Phoenix web framework.

It allows extremely efficient real-time interactivity and UI without writing frontend JS for the majority of your use-cases. This idea is not entirely new, but since Elixir/Erlang and the BEAM build on the actor model and have powerful facilities for managing in-memory state, events, and message passing… the actual implementation is absolutely outstanding. It is an immensely gratifying and productive way of building interactivity.

So, what it does is basically server-side rendering (SSR) and shipping updated parts over a WebSocket connection. Chris McCord explains it way better in his keynote at ElixirConf EU. Like most things built by the Elixir and Phoenix teams, it is much better in execution than it has any right to be.

Now, to give some external validation to the idea of LiveView I want to draw on a favored entity of The Changelog. I will invoke Basecamp. Because not only did Caleb Porzio feel inspired to create Livewire because of LiveView. I imagine the recently released Hotwire from Basecamp pulls some of its name from Livewire… suddenly we can trace the lineage. I think DHH has been working along this thinking for a while, so I’m not sure if LiveView had anything to do with its creation but they are similar solutions for the same problems: building an SPA is too much damn work for a lot of use-cases.

Whether you have a beef with modern JavaScript, just find the tooling frustrating, or simply don’t find the time investment makes sense for your project… there are many reasons why people reach for these solutions. With the release of Hotwire, DHH went on Full Stack Radio and spoke at length about it. I thought he did a good job of not saying “I hate JS and never want to write it”. Rather he emphasized that he really likes and enjoys Ruby and wants to focus on and use that language. I think he made a lot of good points in that conversation that applies quite closely to the PETAL stack. If you prefer Rails, that Basecamp stack is probably great.

Now I like and enjoy Elixir. I also happen to think it is technically superior. That isn’t the most important thing in the world, but it makes me happy. I find it gives me more tools than any other stack I’ve ever worked in. It is a fairly common story that Ruby shops rebuild a system that was performing poorly in Ruby with Elixir and suddenly forget it exists because it never caused trouble again and only required a slice of the previous power to perform at the same pace. In his talk on crawling, Adam Mokan covers some of that ground.

Why PETAL?

I think the PETAL stack is very compelling. Why? Because it has opinionated solutions to the common problems of selecting these layers, but doesn’t paint you into a corner.

Phoenix does your core web server work and basic rendering and forms. LiveView brings your system to the client and provides real-time interactivity for the 80-90% case. Alpine is there for the remaining 10-20% of high-touch interactivity. Tailwind CSS gives you the visual and styling baseline and tools you will need. This should give you all the power you need for a web application UI and all the way back to persisting data to a DB.

Personally I find what lies underneath this stack even more compelling.

Elixir is incredible

Hiding in the “E” for Elixir is an incredible set of capabilities that you won’t find in most languages. You get all of Erlang OTP which is a ridiculously powerful standard library of sorts. See, when your project grows the fun really begins. Because you can grow in this ecosystem like nowhere else. Adding your second host? You have the option of clustering them together allowing transparent message exchange between the nodes. One application spread across many hosts. Phoenix, Channels, LiveView and friends are already cool with that. It just works. You can, of course, run a more typical shared nothing if you like as well. Do you need to do background work? No need to offload that to another process. Your application is ready to manage countless parallell processes.

It’s nice to run on a runtime that can do more than one thing at a time.

There are things you can build without ever leaving your application or creating an artificial boundary because of runtime concerns. That would be really hard to argue for in a Python web application, or a Node.js backend. You can skip your Celery or Sidekiq workers for many use-cases. There’s also a very neat library for setting up LetsEncrypt automatically for you called site_encrypt. It works without certbot or a single line of cron. Because it can.

I think this stack has the potential to be quite approachable to new learners while not really setting any limits to future growth. You can go from simple forms and just work in this stack until you’re wielding CRDTs and applying hybrid logical clocks, or doing event-driven architecture and ingesting huge volumes of data. A traditional trade-off in high level dynamic languages such as Python, Node.js or Ruby is that you sacrifice performance for developer convenience and quick iteration. Elixir works at the same high level of abstraction but builds on very different fundamentals. The problem of distribution and concurrency is the primary bottleneck where these languages struggle. They generally attempt to tackle it with cooperative multitasking, which requires threading a needle of what kind of work can be done without delaying the time to yielding or you will impact other parts of the system. You can handle many requests in a concurrent non-parallel fashion. You run more instances for parallelism.

With Elixir and the BEAM you get another paradigm which uses preemptive scheduling (enabled by Functional Programming and the Actor model) to run things concurrently and in parallel. It has a scheduling system that prevents a heavy piece of work from holding up the line and as such protects system latency so you don’t have to be laser-focused on hitting that IO spot where you can yield. It scales across CPU cores by default.

Elixir won’t beat C++ for performance in number crunching, just like other high-level languages won’t. But it is very well suited to long-running applications, concurrency, state management and distributed computing. And that’s what we do as backend web developers.

Erlang has been doing this for quite some time already. Elixir makes it more approachable and brings better tooling. Phoenix gives all the web conveniences. And now, forming around LiveView, in line with the trend of server-side rendering returning, we can see the shape of a systematic approach to the final parts, all the way into the CSS and last mile of JS interactivity.

Yeah, I think PETAL might just be the stack to watch.


From the Editor

Lars Wikman is a big time contributor to Changelog’s codebase, news feed, and developer community. You can (and should) read more from Lars on underjord.io.


Discussion

Sign in or Join to comment or subscribe

0:00 / 0:00