Hacker News new | past | comments | ask | show | jobs | submit login
Build a real-time Twitter clone with LiveView and Phoenix 1.5 (phoenixframework.org)
548 points by chrismccord on April 22, 2020 | hide | past | favorite | 243 comments



I was a Rails user for almost a decade. I switched to Phoenix/Elixir 3 years ago. Elixir is a super simple language. It has no OO concepts and everything is functions first. In fact, it's so good that I started teaching it for universities. All my production web applications are now fully on Elixir.

Elixir is one of those languages where everything has been done perfectly as of the time of this comment. When I say perfect, I mean, there has been never once in my career where I hit a roadblock due to the language's limitation or complexity or flawed assumption. I faced this with other languages, but not Elixir.

I'm currently a full time consultant writing, teaching and deploying production apps for clients in Elixir. Most of my apps have served my clients well beyond my contractual agreement. It's almost deploy and forget because of Phoenix. It also scales amazingly well. It's extremely performant.

I just re-wrote the entire crappy mess Wordpress core in Elixir and enjoyed the process. In any other language, I wouldn't be saying the same. It's really an enjoyable language that forces you to rethink the way you write code. Don't be put off by this statement, I mean that in a really good way. And once you start thinking interms of functions, you just won't touch any of those terrible OO programming paradigms (Eg. writing for loops, nesting conditionals, etc.). You will start writing maintainable, beautiful code.

You will appreciate Elixir a lot especially if you have a background in horrible programming languages like Javascript. You will literally start finding ways to use Elixir in your entire stack like I am. It's that good.

Enough said. Give it a shot.


> When I say perfect, I mean, there has been never once in my career where I hit a roadblock due to the language's limitation or complexity or flawed assumption. I faced this with other languages, but not Elixir.

This is pretty amazing praise! Are many of the other languages you've used strongly typed? That's the thing that gives me pause - I feel like I rely on the compiler a lot in languages where it can do a lot for me, and that I'd be really frustrated managing a large project without it.

I'm not sure what other languages you have a lot of experience with, but does anything in Elixir stand out to you as the reason dynamic typing works well there? I think dynamic typing is the main reason I nod along with "horrible programming languages like Javascript", for instance.


Before Elixir, I considered Scala because static typing was a strict requirement for me. After I tried Elixir, I found out that good, reliable and maintainable code doesn't have to be necessarily static typed.


For me static typing is essential not when I am writing a new application from scratch, but when I am coming into huge old legacy code projects. For example, I am currently working on a messy and old Swift / Objective C application and having first class IDE support for things like calling hierarchies is pretty amazing to unwind spaghetti code. Also, it's a good feeling to be able to delete a big chunk of code and be 100% confident that its not being used anywhere if your project compiles. Does Dialyzer seem like it would allow you to do things like this safely as well?

My other huge gripe about Elixir when I worked on it last year was lack of IDE autocompletion. This to me is a the #1 dealbreaker in working with dynamically typed languages. Im a horrible speller and having to run my program every time just to find out that I missed a capital letter somewhere in my code is infuriating.

Has Dialyzer and IDEs (VSCode I assume) gotten good enough yet to have decent autocomplete support? When I was using Elixir with WebStorm the experience was less than optimal.


I definitely get the point about static typing. I've seen the same need in legacy codebases myself. :-)

That said, I'm head-over-heels for Elixir. As for autocomplete and such, there's a pretty good project for vscode called something like "Elixir LSP (fork)". Be sure to use the fork version, it's a continuation of the old stale original extension.

In more general terms, the `elixir-lsp` project is pretty solid (and lies underneath the VSCode extension, FWIW), and I've had good luck with it so far in neovim with CoC + coc-elixir.


https://elixirforum.com/t/introducing-elixirls-the-elixir-la... The original author of the plugin passed the controls back to the current fork developers, so you can return to the original one as it is the same as the fork.

https://elixirforum.com/t/introducing-elixirls-the-elixir-la... The fork will probably be deprecated soon


That's an encouraging answer because I currently use Scala :) Thanks!


Static typing is far from a panacea. Don't forget that the rise of Perl and PHP, and then later Ruby and Python was in response to statically typed languages like Java.

There are trade-offs.


What I want hear on static types vs dynamic is how it plays out on a team of say 30 to 100 people. I love JavaScript when it's just me but I much prefer types when using someone else's code because they provide guidance that otherwise isn't there.


One of the things I like about Guards is that you can enforce/match against types as needed.


Guards are nice, but compared to static typing, they a run time check whereas static typing alerts you to errors at compile time.


I’m a fan of static types don’t get me wrong, I’m just saying with guards and dialyser it’s 60% of the way there compared to nothing. Also I don’t seem to make to class of errors I do in other languages because 90% of this time passing the wrong thing breaks immediately due to pattern matching.


Guards are mostly used to do pattern matching, not to specify which types a function accepts, though you can use them as such.


I agree, I wasn't trying to imply otherwise. It's just that static typing is the first thing that looks like a theoretical trade-off of Elixir based on my experience, and I was curious why it doesn't feel that way in practice.


Structs and pattern matching help quite a bit.


Dialyzer via Dialyxir also helps as well


Don't Perl and PHP both predate Java? By quite a bit in Perl's case.


The rise in popularity can happen later than the creation of a language, see Python (1991).

In my case I left Java for Ruby for web programming in 2006 because working with Rails was infinitely easier than working with Structs. I didn't even know that Ruby was a programming language before Rails.


FWIW: Perl, 1987. PHP & Java, 1995.


To be fair PHP, while still dynamic, has eventually evolved to be (optionally) a strict and strongly typed language.


I was excited to the other day to see https://gleam.run/ on HN, which is statically typed and will interop with elixir... but still early days for the language.


I've been programming Elixir professionally for three years. I wish Elixir was statically typed, but there isn't a statically typed language that I really like better all around. I've done a lot of Haskell development but it seems like I always spent too much time playing type tetris and polishing abstractions instead of getting work done. Elixir feels more static than most dynamic languages; you'll get compile errors or warnings if function arity doesn't match or if you use names that are undefined. There is a static analyzer called Dialyzer that can detect a lot of errors you'd catch with static language compiler such as passing the wrong type to a function (often, even if there are no type specs defined). Yet at the same time you get the benefits of a dynamic language with excellent meta-programming capabilities.


Over time I find my Elixir is more and more "statically typed". Since you get access to basically the full language at compile time, with a bit of hand-coding you can opt-in to features that statically type critical sections of your code at compile time. Critically important things can be guarded by relatively advanced checking, if you want to get really clever you can yank those checks for performance in prod deployments. I have been doing this with configurations, so that configs are checked at compile time instead of at deploy time, and I'm pretty happy with it.


> Are many of the other languages you've used strongly typed? That's the thing that gives me pause - I feel like I rely on the compiler a lot in languages where it can do a lot for me, and that I'd be really frustrated managing a large project without it.

As someone who has been writing Elixir professionally for 4-ish years, and who is otherwise about as big of a proponent of static types as is possible, this is simultaneously my biggest critique of Elixir, and also a critique that has ended up being more theoretical than not. I wish that it were statically typed, but in practice that hasn't been slowing me down.

Part of the reason for that is that while Elixir is dynamically typed, I've found that it's possible to pretend it is a statically typed language if you squint just right. By that, I mean making judicious use of typespecs [0], dialyzer [1], Norm [2], and just generally constraining the way you write code to mirror the sorts of code that you'd write in a language that offers algebraic data-types, like Haskell. I've been meaning to put together a blog post on what I mean by this, because I often hear people talking about how unusable Dialyzer is, so I feel like my team is a rare example of a large production app that requires that Dialyzer typechecks on every build. This makes large-scale refactoring of our app almost (but not quite) as easy as it would be in Haskell.

The macro system in Elixir also means that it's possible to write libraries like typeclass [3], that offer compile-time guarantees (using compile-time property tests!) that your implementations correctly implement a given interface. I think that as the language evolves, we'll be seeing a lot more examples of macros that move runtime logic into the compilation step, to offer compile-time guarantees and safety. For example, a few weeks ago, I prototyped an experimental library in a few hours that added support for compile-time OCaml style parameterized-modules. [4]

Obviously, all of these techniques don't get you quite as far as proper static typing would (though the Whatsapp team is working on static types for Erlang! [5]), but the rest of the language and the ecosystem is just so well thought out, that I've been okay with that!

[0] https://hexdocs.pm/elixir/typespecs.html

[1] https://github.com/jeremyjh/dialyxir

[2] https://github.com/keathley/norm/

[3] https://github.com/witchcrafters/type_class

[4] https://github.com/QuinnWilton/daat/

[5] https://www.facebook.com/careers/jobs/229713254864749/


To add to this, it's worth noting that Elixir would have difficulty _ever_ becoming statically typed because of how message-passing works. For example, if you look at Gleam [0] -- the recent project that's trying to create a statically typed language for the BEAM -- it can't handle message-passing [1].

And I totally agree with you here:

> I've found that it's possible to pretend it is a statically typed language if you squint just right.

My Elixir code tends to use a lot of pattern matching on structs. It's not real static typing, but it gets me a lot of mileage!

[0] https://gleam.run/index.html

[1] https://gleam.run/faqs.html#how-is-message-passing-typed


Hi, I'm the author of Gleam.

We have fully type safe message passing, we just don't have any special syntax for it. I'll update the documentation to make this clearer.


Hi! Super cool project you've embarked on. I know everyone I work with (those who write Elixir, anyway) is very interested in its progress.

> I'll update the documentation to make this clearer.

Thanks! Much appreciated.


Typing messages is considered a PhD (?) level problem. Could you talk more about how you went about solving it? Thanks!


It would be difficult (or perhaps impossible) to type all of Erlang's message passing features, so we reduced scope to not include distributed message passing or hot upgrades- so the types of all actors in the system can be known up front in order to be checked.

In practice this is enough for the vast majority of applicatinos, and messages with runtime checks (like in regular Erlang) can be used for the other situations if required.


Thanks for commenting. Do you have any code somewhere that demonstrates type-safe messages?


Certainly, there are some links to relevent libraries here -> https://gleam.run/faqs.html#how-is-message-passing-typed


I've heard a number of times that static typing would be near impossible for Erlang because of how message-passing works, but just the other day I read a quote where one of the creators (I think it was Joe Armstrong, but not completely certain) indicated that the primary reason they decided against static typing was the hot code reloading, not the feasibility. or not primarily anyways.

Not disagreeing with you, I guess. It was just surprising/interesting to read.

Sadly I can't find the quote...


I'm the author of Gleam, a statically typed language on the BEAM.

What you've said matches my findings. Messages can be typed, however hot code upgrades cannot be. For Gleam we've sacrified hot code loading in exchange for types, which I think is a good trade for most use cases.


Hi, thank you for contributing! I have gotten into the functional programming paradigm conceptually from working with react/redux. We do all of our development work using TypeScript, rather than JavaScript. Typescript isn’t really static typing, but more like type assertions on top of a dynamic language, but hot reloading works fine and is a core component of the workflow, especially with the ability to maintain state in between loads. I’m new to this world and haven’t yet tried Elixir, but what is it about the type system that prevents hot reloading? Is it because the underlying execution system is using types for something? Could a typescript-style language be built on top of Elixir and BEAM that would allow hot reloading and type assertions together?


Not touching on the reasons why the type system and hot code reloading are complex in the BEAM, but the hot code reloading dev workflows in other languages and the BEAM one are two completely different beasts.

Erlang/OTP was designed for systems where the amount of acceptable downtime is 0, you don't want phone calls failing because you have to fix a bug, the solution is a system where you can replace parts of it running live, if you replace a module all processes currently running it will still work normally but any new call to the module will use the updated version of it.

https://blog.appsignal.com/2018/10/16/elixir-alchemy-hot-cod...


The hot loading of code we're talking about is mutating of running code in production, and it involves running multiple different versions of the same code at the same time in order to do a clean and incremental migration to the new version while continuing to serve traffic. It's a different set of constraints to hot loading JavaScript style and very difficult to get right. The nation problem is that you don't have any way of knowing what the the state of the running system is (it is mutable) so you cannot unify your new types with the existing system.

We could probably do hot loading in development using type assertions fairly happily.


I see, thank you for the response. I haven’t ever heard of something like this being possible in production. We typically have to do phased rollouts at a different level of the stack, it’s not something supported by the runtime!


It came from Ericsson needing to upgrade telephone switch firmware without taking the system down. These telephone switches were often expensive and in physically difficult to reach places so having a standby for a switch-over wasn't viable.

Quite an interesting set of constraints!


I'd really like to read about your finding wrt hot code loading. Is there anything you can point me to?


I'm afraid not, it's not been a fruitful area of research so we've not written anything down about the limitations.


Ok. Thank you and good luck with Gleam!


It’s a combination of message passing to distributed nodes AND hot reloading. The compiler guarantees would only work on your current node, but if you were sending something to another node in the cluster you have zero knowledge of the types without forcing a full contract exchange on connection.

There’s a lot of problems introduced by that.


Joe Armstrong, RIP, also stated they tried to add type to Erlang later on but gave up.


I don't know if I'd say "ever", but it definitely won't be easy! Take a look at session types [0] if you haven't seen them!

Type checking unrestricted message passing would be difficult, but I can imagine a subset that's typeable.

[0] http://groups.inf.ed.ac.uk/abcd/index.html#about


I haven't seen them, thanks!

> Type checking unrestricted message passing would be difficult, but I can imagine a subset that's typeable.

I'd love to see a discussion on this somewhere. I can totally imagine a world where it's true that "yes, you can't send messages of type X because the receiver can't pattern match on them in the way you expect, but what you're really trying to do is Y, and you _can_ send messages of type Z that accomplish Y."


"hasn't been slowing me down" --> would it slow a new developer who approaches the code base? or 30-100 people who work on the codebase?


That's hard to say. I've never worked on an engineering team of more than 10 people.

That being said, with the tools I described, you still have type annotations and automated type checking, so the documentation benefits of static types are still present.


Thanks for sharing all this! It's great to hear that it's not an issue in practice and they're some useful looking tools to check out when I get a chance to play with it. It definitely sounds great to work with :)


I 100% agree about Elixir and its surrounding ecosystem being almost perfect. It's insane how simple the building blocks are and how easy the code is to read and write.

Here are a few pain points I've ran into: 1. Typespecs leave something to be desired compared to other type systems 2. Maps vs structs and easily using one in place of the other

Things that my team would like to see: 1. Components in addition to templates as a first-class citizen in Phoenix. My team loves React because of the component model even though we hardly use an insane amount of interactivity.


If you are interested in a React like component library built on top of LiveView you should check out Surface http://surface-demo.msaraiva.io/


Seconding the recommendation to check out Surface! From the docs:

Surface is a server-side rendering component library that allows developers to build rich interactive user-interfaces, writing minimal custom Javascript.

Features: * An HTML-centric templating language with built-in directives (:for, :if, ...) and syntactic sugar for attributes (inspired by Vue.js). * Components as modules - they can be stateless, stateful, renderless or compile-time. * Declarative properties - explicitly declare the inputs (properties and events) of each component. * Slots - placeholders declared by a component that you can fill up with custom content. * Contexts - allows a parent component to share data with its children without passing them as properties.. * Compile-time checking of components and their properties. * Integration with editor/tools for warnings/errors, syntax highlighting, jump-to-definition, auto-completion (soon!) and more.


Hey, just a friendly Elixir user here! Could you explain why you think that maps vs. structs is a pain point? I found this interesting because I personally really like how they are so similar, because you can almost always manipulate a struct like a map, just like you'd expect. It lets you use standard operations for working with structs.


Not GP, but: You can't use trivially use [] dereferencing notation with structs, or, for that matter get_in or put_in, without first making it access protocol compliant (which maybe you shouldn't do? I haven't figured that out for myself yet). A common use case for me is initializing a GenServer with a kwl, which is nice for your code prettiness, but you'd like to also support maps, because that fits with how the internal state of the GenServer looks. Then when you go to refactor your GenServer to use a struct because you prefer a more solid typesystem, you can run into a minor stumbling block and slightly uglier code. Not insurmountable though, and you're writing tests right? Once those tests pass you've got nothing to worry about.


Making the conversion from/to Map and (keyword) list explicit makes sense, as they have very different access patterns: keyword lists really are not suited for random access unless very small.

And in general Erlang and Elixir have very little automatic type conversions, if any.

But maps and structs are interchangeable, I don't get why using one or the other would make your GenServer code any different. A struct is just a map with an additional field called "__struct__".


> And once you start thinking interms of functions, you just won't touch any of those terrible OO programming paradigms

Also worth noting (because Elixir was strange and new for everyone at some point) that a lot of what used to be mind-boggling to me in earlier versions of Elixir/Phoenix have become relatively commonplace when dealing with things like React or modern Javascript.

If you've ever handled a JS promise for something as simple as a `fetch()` query and processed results, you _already understand_ how to build code in functional components.

There's much less difference between

    fetch(url)
      .then(results => doSomething())
      .then(results => doSomethingElse())
and

    doSomething()
    |> doSomethingElse() 
than it looks like at first blush.


Unlike a Promise, I hope you can cancel processes in Elixir


You can cancel a Promise by using AbortController and its AbortSignal, still experimental but supported in most browsers already.


I'll stick to Futures for; Futures work everywhere now and aren't immediately invoked when called with new.


Not sure exactly what futures you're referring to as there are no "native" futures in any browser (that I know of) so they are either implemented on top of Promises or by using callbacks, and still doesn't solve the problem of cancellation...


You're right. There's not a native solution. I've used Fluture (https://github.com/fluture-js/Fluture) for while now as it follows the Fantasy Land spec. The canceler is returned in the Future's constructor. The biggest feature difference in comparison to Promises is that you can pass around a Future adding to the data transformation without it being invoked until fork is called.

It's good to know that there exists a way to do this natively now though.


You can kill them. Just like processes on your computer!


> When I say perfect, I mean, there has been never once in my career where I hit a roadblock due to the language's limitation or complexity or flawed assumption. I faced this with other languages, but not Elixir.

That is interesting.

I've gone from Geocities pages to ASP Classic, PHP, WP, Rails, Flask and have been dabbling with Elixir and Phoenix for a bit.

So far LiveView (and some bits of Elixir in general) has been the only time in my career where I felt like I'm seriously struggling hard to understand how things come together and how to solve real but fairly common web dev problems without asking for help (mainly with LV). I've had to ask for help on IRC / the forums an embarrassing amount of times. Where as with Rails and Flask almost everything except the most crazy problems were solvable with a little bit of Googling and self exploration.

Now, I'm not saying Elixir and Phoenix is bad at all. I'm still happily using it to build my next big project (for all of the reasons that everyone else uses it for), and the Programming Phoenix book is a great learning resource for building regular web apps with Phoenix, but there's nothing like that for LiveView.

But on the bright side, Chris (the author of Phoenix) and Jose (the author of Elixir) are remarkably responsive to help the community. Lots of other folks are super helpful too. That and once things start to click, you can write some really pleasant looking code and actually understand what it does a few months later.


LiveView is much much easier to understand if you have a solid understanding of how Elixir works in a non-webdev setting, because Phoenix hides a lot of the process architecture that it's leveraging to serve pages, and it's front-and center in LiveView.

And also, it's easy to find help for Flask and Rails by googling because... It's been around longer. LiveView has been GA for less than a year, and even some major shifts have come around (like mount/2 suddenly becoming mount/3 in one of the last releases).


Yeah, that's one of the main problems, almost every blog post is out of date because live components are new and there's introductions to many other new things as well.

But then I look at the Live View equiv. in other frameworks. All of which came well after Live View since they are modeled after it.

For example: https://laravel-livewire.com/docs/quickstart in Laravel. I'm not a Laravel developer but their documentation is next level amazing and the author of the library even has a screencast series going that is fully up to date where he builds a real app using Live Wire to demo how it works in practice.

I don't even know Laravel at all, but I can skim their docs and get a feel for how to solve real problems like validation, authorization, pagination, and everything else is focused on practical examples and explaining things very well in the process.

But with Live View, the docs are not anything like this. It reads more like a low level guide on the API itself, not how things work in practice and when you should use certain things or how to write common web dev features. After reading the docs, you're left wondering "ok, but how do I get started using Live View in practice?", IMO at least.

There's also the Rails equiv. which is https://expo.stimulusreflex.com/. Besides the docs there's a bunch of real practical examples, with a live demo of how they all work without having to install anything. With Live View, we have an example repo but it's very out dated at the moment to the point where you can't even follow it with the docs and it seems to not be based on best practices anymore since new things were released with LV.


I agree. I’ve tried learning a ton of times but I always hit something I don’t understand and struggle to find help except asking. I think because it’s such a niche language still. With Rails there aren’t a lot of questions left to ask. They’ve already been asked and answered. That’s not the case with Elixir and especially Phoenix.


It sounds like you're mostly backend and struggle with the blending of backend/frontend with liveview?


I haven't had extensive front-end experience writing React code but I've been around the block with JS. I'm pretty familiar with the event model of "hey guys, I want to do something on click, so let me wire up this handler which executes X when Y happens".

The struggle is mainly around the nuisances of how certain things work with LV and what the implications are of using X vs Y with practical examples. I wrote a forum post asking for help about this the other day at https://elixirforum.com/t/concrete-examples-of-when-to-use-l....

Then there's other things like wanting to do authentication. I know in theory you'll need to create a controller action to create / delete the session and there's phx-trigger-action to submit a LV form to a controller but there's no code examples anywhere on how to pull this off and get a "current_user" like you normally would with a non-LV set up. But authentication is one of the most important things in any app.


I actually agree with every pain point that Dave Thomas described in his talk[1] and is outlined in the Component github repo[2]. Sadly, it's unclear to me if anyone else is as passionate and willing to continue the effort. Nonetheless, it put to words exactly what I hated about genservers and such.

[1]: https://www.youtube.com/watch?v=6U7cLUygMeI

[2]: https://github.com/pragdave/component


I loved his complaints about genservers (and his complaints about nomenclature), and it made me settle on my own genserver structure. I think the hard thing about dave thomas' component is that it just doesn't have enough buyin in the community to make it "its own thing". I wish it did though. But on the other hand, if elixir had diverged too much from erlang it would have made people angry...


It's unfortunate. Because when fresh eyes take a look at Elixir, it's hard to miss that the whole genserver pattern feels like a workaround / anti-pattern.

I remember thinking, "This feels messy..." but not really knowing why. And I was brand new and barely a developer!

But I think you nailed it. It's because of the Erlang continuity.


I'll say Elixir isn't perfect. There are a few annoying bits that won't be changed due to backwards compatibility, that 98% of people won't run into. For example:

    a = [foo: "bar", foo: "baz"]
    Keyword.get(a, :foo)   #==> gives you "bar"
    a[:foo]                #==> gives you "bar"
    my_struct = struct(SomeStructWithFoo, a)
    my_struct.foo          #==> gives you "baz"
But really, this minor, minor inconsistency is near the top of my list of complaints, so... Take that into consideration.

Also, if you start coding in Elixir a lot, you will write better Javascript by importing good practices in from Elixir.


What's the problem there? A map has unique keys, a keyword list is just a list of {atom, term}, so there might be duplication.

They are similar but they are not the same thing and are not to be used in the same places.


The problem is that it violates the principle of least surprise. Thankfully this sort of thing is not rampant in Elixir, and I discovered the example only after something like 50k lines of very joyful code.


> I just re-wrote the entire crappy mess Wordpress core in Elixir and enjoyed the process.

That sounds useful. Do you plan to make a product out of that?


Yup, launching soon. Probably will open source it too.


Any way to get updates when this happens?

Edit: Saw the link to your blog below https://medium.com/build-ideas/


If you want to compete with WordPress, you should open source it.


Do you have somewhere we can register/watch to be notified ? Also interested here.


You can follow my updates here as the other commenter has mentioned. Thanks!

https://medium.com/build-ideas/


Thank you HN. If you're interested, I'm actually documenting my journey as a consultant building ideas on Elixir at https://medium.com/build-ideas/

Thank you.


I love Elixir, but tha language is not super simple. The learning curve is actually rather steep. Writing Elixir like it's easy is probably creating technical debt hell that's going to fall over the moment a system is under non-trivial load. It's all fun and games until someone who didn't know who write a GenServer doesn't understand why everything starts timing out after 5 seconds.


Can you explain in your own words for elixir where the balance between "joy" (productivity, flow, whatever you want to call it) and what you call "rethinking the way you write code". As another example of a functional oriented language that prides itself in the same thing look at Haskell. I wouldn't say most people think that Haskell is an easy or productive language (that is until after you have years of experience under your belt), but it definitely forces you to rethink how you code. Scala is another example, but draws the line at a different place. How is where elixir draws the line preferable in your opinion?


So as someone who worked in Erlang (and is familiar with Elixir), I can answer that a little bit.

They hit a sweet spot. Enough rigor, enough limitation, at the language level, to force you to do things "the right way" for a broad swath of problems (there are certain problems they're poorly suited for), but enough simplicity and freedom to keep a minimal learning curve, and minimal runtime complexity to figure out issues.

The focus on fault tolerance also means once you learn to use the app structure, with supervisors, you mostly have just one concern for reliability ("how do I start this into a known, good, consistent state?"), rather than hundreds ("what happens if -this- fails? Or that? Or that other thing?").

Haskell and Scala both have a huge surface area to learn before you're productive, let alone anything approaching fault tolerant, and even after years of use, there's still a lot of hidden gotchas with them. I've seen teams take Erlang, and their very first project just...worked. None of their lessons learned caused production issues, and no weirdness; the three issues that made it to prod I can even think of were, variously, one that wasn't user facing (just a log entry indicating something wasn't handled right; supervisor took care of it), one where performance started to slow (and it was due to having written an O(N^2) algorithm accidentally, and not testing at higher loads than production), and one where a low level C driver made an unnecessary reverse DNS lookup that, when the caches flushed, caused things to hang, which became an issue when load increased, and which should have been circuit broken (but which instead caused a failover to another node).

I've never had that experience with another language. The ramp up time to productivity was longer, the production issues caused by us missing something about the language were more frequent, the production issues caused by us failing to expect or handle a failure condition were more frequent, etc.

That said, Elixir and Phoenix do raise the bar a little. Elixir has a larger surface than Erlang (only a few concepts, but a lot of ramifications when it comes to macros if you haven't used them in other languages), and Phoenix is reliant on a fair bit of magic so you need to read the docs and it may take a little bit of work to feel happy with things. But even when I knew nothing about it, picking it was easy because of the experience I had with Erlang.


> with supervisors, you mostly have just one concern for reliability ("how do I start this into a known, good, consistent state?"), rather than hundreds ("what happens if -this- fails? Or that? Or that other thing?")

Thank you for this comment. I have used Elixir for a couple of years and is a concept I have always understood but have never been able to explain coherently and succinctly.


Ok, I've heard of Haskell and I've been to many Haskell meetups too. This was before I found Elixir. For me, the biggest problem with Haskell is that it will turn cryptic if you don't touch the codebase for say, 6 months. Because, you need to essentially re-learn the special syntax of the language if you're touching Haskell code after 6 months.

In contrast, Elixir is super simple. I can describe the language in a single HN comment. Everything is just a function and they're inside modules. That's pretty much it. When I was picking up Elixir, I started off writing an E-Commerce platform from scratch with Elixir. When I was about to finish it, I was thrown into a 8 month long PHP project. When I was finally done with it and returned back to work on my E-Commerce project, I was able to just open up the code in a text editor and immediately understand what was happening - without having to re-learn the language. That is a the "Joy" part for me.

One more "Joy" of writing in Elixir is you don't need to worry about memory usage or performance that much. It's pretty efficient unlike Ruby or PHP even. So, I can just throw this entire application in a $5 Digital Ocean droplet and watch it handle insane amounts of traffic. And this is without optimizing anything. You will probably able to squeeze more with caching, optimizations, etc.

As for re-thinking the way you write code, it's mostly to do with pipe operations. Piping was a new concept for me jumping from Ruby. It's absolutely powerful, concise and productive. In Elixir, if you don't write good code, the compiler will warn you AND show you examples of how (and sometimes why) it should be re-written. Eg. If you write a nested case statement which many people subconsciously may do coming from OOP backgrounds, the compiler will ask you to re-think your code. And stuff like this really challenges you, but actually doesn't do anything destructive to your code - your code will still compile and function, but you will feel that tingling inside - "Hmm, maybe I should consider re-writing that?"

THAT is the balance. Before Elixir, I also used Scala. Took me 3 months to fully learn the language from the 700+ pages book on Scala. I absolutely love Scala and the JVM. It's powerful, but there's just too many ways to do the same thing in Scala to keep track of. So, it goes back to my first point on looking at the language after 6 months without the need to re-learn it. I would still try Scala at some point because JVM is very powerful. But, will it replace Elixir? Absolutely not.


> And once you start thinking in terms of functions, you just won't touch any of those terrible OO programming paradigms

This sort of absolutism does nobody any favours. Functional zealotry is every bit as bad as OO zealotry.


How is the IDE support and in particular the refactoring assistance? If I rename something do I have to find and replace or will language service tools handle that for me? Speaking as someone who just did a very large refactoring of a large (100k+) codebase. Statically typed languages and tools around them help a ton there but not sure how it would work with Elixir.


I'm a full-stack Typescript dev (React, Node.js, etc.). Lately I've been more intrigued by functional programming. I feel like I've gone pretty deep into OO and classes, inheritance, etc. Looking back, I feel like there is a better way to structure that, and the glimpse of functional programming that I've seen seems to help with this boilerplate.

I've heard only good things about Elixir/Phoenix, so I'm thinking about picking it up for my next project. One thing about JS/TS is that the ecosystem is well developed, especially on the deployment side. For side projects especially, I like to minimize my dev ops configs and utilize "serverless" type stuff (i.e. Zeit/Vercel, FaaS, etc). I haven't seen much of this in Elixir-land, but hey, maybe that's an area I can help innovate in.


Are there any good tutorials to get started? What major sites are currently using Elixir?


Discord and Pinterest use Elixir at a massive scale. Discord in particular has been writing a great technical blog about the process.

On a smaller scale Feedback Panda very successfully bootstrapped to a 55k MRR SaaS and was aquired in under 2 years: https://youtu.be/vaXp81OxxK0

Edit: Not to be too self-promotional, but AFIK I've created more free Elixir-learning screencasts than anyone on YouTube. I cover a pretty broad range of topics from total beginner to some fairly niche things: https://youtu.be/z1nKbzZiRtY


The Elixir video courses at https://pragmaticstudio.com/ are the best available, in my opinion. There are some free tutorials available and some other good paid courses, to be sure, but I think Mike and Nicole over at Pragmatic Studio offer the most complete and easy-to-follow courses available. The cost-to-value ratio of their courses is really good, I think.

I'm not affiliated with them in any way. I'm just a happy customer.


I don't know why you're downvoted, I did the Elixir course and it was useful and well done.


Haven't done their Elixir course but can vouch for their Ruby/Rails stuff. They just really value simplicity and sweat the details more than most instructors. Great stuff


Thanks for the recs. If you're willing to share what other paid courses you consider good, I'd appreciate it!


> What major sites are currently using Elixir?

Besides what was listed already, if you're looking for info on people running Elixir / Phoenix in production there's this podcast: https://runninginproduction.com/tags/phoenix

One guy was pumping over 7 billion log events a month through it.

Another one (remote.com episode) serves 100k+ daily requests.

Each podcast episode goes through how the app was built and how it's deployed at a high level, but still has enough details to apply those things back to your own projects.

With that said, if anyone is running Elixir or Phoenix in production and sees this and wants to be on the show, just head over to the above link and click "become a guest" on the top right. I'd love to have you on, both big and small sites are welcome.


> any good tutorials?

https://elixir-lang.org/learning.html - Start here. It starts off kind of abstract, and then works its way into the concrete (from my experience) -- but is very easy to pick up.

> What major sites?

Last I heard, Discord was serving ~5 million concurrent users, and that was well before compelled isolation.

Bleacher Report is also using Elixir, and serving something like 100k requests per minute just to mobile clients.

Bet365 handles as much as 100k monetary transactions during a big sporting event like a Champions League final.


I heard Divvy, Brex, Slab, and PagerDuty use elixir, so if you're a bay area startup, there's a good chance you're already using elixir as part of your business stack.


>Elixir is one of those languages where everything has been done perfectly as of the time of this comment.

Including GenServers? I find writing GenServers to be needlessly painful. Their syntax is one of my least favorite things about Elixir.


Why is that? The GenServer API very similar to Erlang version.

You can add your own abstractions with macros on top of that if you like.


Wait, for loops and nested conditions is an OO concept? What does Elixir do instead?


It seems since Elixir is purely functional you don't mutate things. So basically you use tail call optimised recursion for everything. Neat.


Recursion lol.

Erlang does it too.

If you want to have state you do recursion and call itself with the updated value.

fn me(iter) -> me(iter+1) end


It's not OO per say, but it is an imperative concept, OO is almost always imperative.


How’s the speed?

Is it as performant as technologies like Django / Ruby?


As with anything benchmarking is hard and "performance" is not a 1 dimensional thing.

That said, there are some ways in which Phoenix/LiveView is extremely "scalable".

For example, pushing messages to 2 million simultaneous websocket connections: https://www.phoenixframework.org/blog/the-road-to-2-million-...

... and running on the BEAM gives all sorts of exciting horizontal scaling possibilities on top of that.


I think calculations are it's weak point, but for the typical message passing application like Twitter it's fast and incredibly scalable.


Congratulations Chris, Jose and the Phoenix core team on Phoenix 1.5 and the livedashboard.

I used liveview in https://readastorytome.com. I posted it here last week and it stayed on the front page for a good few hours. I was concerned about load, so before I posted it I upgraded my $5 DO box to a 4 core box which turned out to be completely unnecessary. The CPU load stayed in the 2-3% range the entire time it was on the front page, which is pretty amazing considering how much traffic was coming in. Funnily enough I came across the livedashboard repo just before I posted it, so I set it up and I was using it to monitor my app live while it was on the frontpage of HN.

The dev experience is pretty amazing - I don't think I would have been able to write this app as quickly and to add new features at the pace I have been in any other language.

So thank you Chris, Jose and the Phoenix/Elixir team.

If anyone has questions about my experience with liveview free free to ask - either here or by email - ben@readastorytome.com


Are the people videos streamed via LiveView as well? Super impressive. Congrats!


No - video stream is webrtc, pdf viewer is pdf.js

We use liveview + hooks(where necessary) for all of the interactive parts on the site, switching pages, changing books etc...


We are really excited about this release! I also wanted the screencast to be a single take, so I'm happy to answer questions if there are gaps to fill in for things I could have explained more clearly.


Any hope of getting this as a text article, or even a git repo? Blind user here who can't see code embedded in a video, but can read ascii-text with a screen-reader perfectly fine.

People who don't enjoy videos for various reasons would probably like a text version too.


Hi miki123211, I wrote up a transcription for you. It details the code he's talking about, along with the context of what's going on, and why.

https://pastebin.com/raw/WxH0uAsf

If Pastebin doesn't work for you, let me know and I can get it hosted at a different location.

My apologies if there are any mistakes in this. I'm not familiar with Phoenix, but found this video very interesting, so wanted to make sure it could be shared.


Thanks, that works. The raw link is perfect for accessibility, as there's no garbage on the page.


Thank you for doing that, good job!


> People who don't enjoy videos for various reasons would probably like a text version too.

Yes this. I went to the video eagerly looking for a repo link and was disappointed not to find one.


Great work! I think the phoenix framework project really recognizes the power of "Defaults". Defaults for dev, user interaction, server, and client. Make useful things quick but also learn how and why they are chosen.


First of all, great demo, and great showcase for this technology. I think it did a great job of showing its strengths to traditionally backend developers like me.

I also appreciated the twitter analogy. I just couldn't help but think "Wait, Twitter doesn't have 'Update/Edit Post'!" :)

I've heard that Blazor in the .net world has similar goals to LiveView, but I haven't gotten into it much. Can anyone confirm?


Yes, there are two Blazor variants. Serverside Blazor is basically the same thing as Phoenix Live View, client side Blazor is providing some optimized Mono runtime as webassembly.


From an empty repo, how many minutes do you think it would take one to do what Chris McCord did in Phoenix Live View in Blazor?


I have no idea. Probably longer. But it is the same idea. The big gains come from going back to the simpler server side programming model. I'm working on a big Angular application right now for which something like Live View would be the ideal fit. That said, a switch to Elixir would be a very hard sell in my company. Blazor would be easier because it's .NET.


I also don't know enough about c#, to comment on this being a risk for blazor but having the BEAM's process isolation is absolutely critical to minimizing programmer error from turning into a let's say a DOS attack risk, or possibly worse.

I worry that all these other platforms rushing to emulate liveview are missing that extremely critical component of this model. If you aren't certain about what I mean, I suggest watching Sasa juric's "the soul of erlang and Elixir" video where forward progress of the system is unimpeded by a panic or a process that attempts to hog processing via an infinite loop, both are detectable in the running system, and able to be easily identified (down to the malfunctioning function name) in the in-prod system.


I'm really amazed this sort of functionality can be implemented in such a nice and clean manner. Your presentation is mind blowing!

Just out of curiosity (please don't consider this as a feature request, more like a thought exercise), in case you wanted the application to have offline editing functionality, could the framework provide it in a similar manner? having a generic JS handler that manages pushing state when an internet connection is available again and exposing hooks that you can implement to handle data consistency? Of course in this case the data payload passed through sockets would be bigger as you would need some identifiers to make sure for example increments don't get duplicated, and there could potentially be different strategies for solving data conflicts (CRDTs for example). But would it need extra back-end support for this or would it be enough to have engineers manage state through the current handlers?


"offline support" is strictly on the side of needing to run a lot of code on the client, so this is where we draw a line and say you need a js framework, of which there are number of great options. We have javascript interop via phx-hook, so it could be made to work, but you'd necessarily have to have a lot of js running on the client, and any feature you wanted to work online & offline would not share a code path or need js, thus client side rendering and templating gets involved and suddenly we're writing a SPA. If we're strictly talking allowing the edit of a textual input and syncing on reconnect, it would be straight forward to do with LV and some small js hooks, but the moment you start adding offline UI features you'll need a js library.

The funny thing is last I tried to use Google Docs offline, it locked the page in read-only mode, so offline mode even in the SPA space isn't just a given – you're definitely opting in to some necessary complexity.


Sounds fair, thank you for your reply!


Hi Chris. I built a demo with LiveView a year ago and am very happy to see all the improvements.

One thing I didn't understand from the video is how the :post_updated callback worked. It prepends the updated post to the list of posts. How come that doesn't lead to the same post being double in the list?


Components IDs are unique. So once you try to render the same component, we know you simply want to update the current one.

The same happens on the client. If the server emits the same DOM ID, the client just updates it in place too.


Congrats on the launch! I've been following this for a while and played around with it a bit, I'm excited to get my hands dirty with this.

How does reconnection work? lets say someone is using the site, and you do a deployment, rolling the nodes over. Does live view simply reconnect to another node without any interruption from the user's perspective?


Confirm. LiveView will apply css loading state classes, which are user defined, but we generated css by default in new apps to lock the UI with loading cursor, and show a top loading bar. On reconnect, which happens automatically, we rematch the DOM with any changes, and we also send up any user form input beforehand so client state is lost that was in progress. We already have reports of users pushing bugs to their systems and the UI seemingly being unaffected because the LiveViews automatically recover, wether from a disconnect or a crash on the server.


Thanks for putting this together, Chris :)


You are running this on localhost but won't interactions be slow if a user is 200ms from the server?

Re-rendering templates every time on things that require high interaction also seems very expensive and an easy way to slow down your server when you have multiple users correct? or what I'm missing?


LiveView does not re-render the template on every interaction. LiveView actually sends patches over the wire, which is typically smaller than a hand-written JSON response. The screencast linked above has a good example of this, where clicking the "retweet" button sends a minimal payload, since we know the exact position on the page.

LiveView also uses a long-running WebSocket connection and that reduces the amount of data sent over the wire compared to regular requests/responses, as you don't need to encode headers, cookies, etc.

Finally, if you are worried about latency, you can call "liveView.enableLatencySim(200)" in your browser console, and you will be able to emulate how your application behaves over high latencies.


This is the future of frontend development. Happy to see it making progress.

DHH was right about this stuff long ago in 2012 (mixing server side rendering with interactive JS frontends) even as the software wasn't quite there yet: https://signalvnoise.com/posts/3112-how-basecamp-next-got-to...

The other approach is SSR with React/Vue that hydrates on pageload with something like Next.js/Nuxt.js. https://nextjs.org/

But the Phoenix approach seems better for a more Railsy single framework approach (assuming you don't like writing the entire server side code in JS, which I do not). It's more cohesive and quicker to roll something out.

I currently do mostly Vue with Rails backends professionally but if it was from scratch or rearchitected with Elixir I'd seriously reconsider using full blown Liveview.

My only concern would be missing out on some UI libraries and pure size of community support. But I wouldn't miss getting rid of the super complicated JS tooling set ups I currently use (in addition to rails or trying to jam it through the asset pipeline via webpacker), in exchange for a more centralized approach. I've gotten a bit too used to maintaining the frontend almost separately from the server app and sometimes miss the simple days of being pure Rails.

One additional concern may be portability for mobile with React native. But that only applies to a subset of apps where reuse/cross platform makes sense. Still it was a big reason why these SPA style frameworks flourished like they did.


The patches don't need to be processed by the template engine to render them?


It turns out that Elixir/Phoenix templating is, in general, astoundingly fast, and that diffing operations are highly optimized at the language level due to the data structure (IO list) used.

Here's some information: https://www.evanmiller.org/elixir-ram-and-the-template-of-do...


Due to the efficient diff'ing and data format, in practical terms I’d estimate a normal web app doesn’t require much more server resources with LV than a rest api backend. Maybe double? Of course that’ll depend drastically on the web page and template size used. Loading the text of full novels might not fair well!

On the extreme end I have a few pages that plot IoT data where it can take ~3 seconds to do a drop down in LV... Granted the server is serving a dozen SVG plots with a total of ~80,000 data points and performs the server template diff in that time. That’s on a RPi3 "server", which are also processing data, running similar pages on 4-10 browser tabs and running its own web browser. Haven't gotten close to using up the ram. Much of the slowness in that case is due to Chrome choking on that much SVG. I haven’t bothered optimizing the server side by dropping already rendered graphs.

Hope that helps give some insights. It'd be interesting to hear from people running high traffic sites.


The patches are sent as pure data and a small client-side Javascript library (morph-dom) patches the DOM accordingly, so the template itself doesn't get sent.


you are correct, you can't escape the laws of physics latency wise, but most web things we are all building, including 100% JavaScript apps require a round trip to the server. For example I can't post tweet without a round trip to twitter. On the LiveView side UX wise, we apply css loading states to the interacted elements, so the user is provided feedback while awaiting an acknowledgement. On the server, our templates are precompiled and do change tracking. So we only execute the elixir code that is necessary to render the parts of the template that changed. The rest of the calls are noops. From the top down, it appears like an extremely heavy approach, but with our change tracking and diffing, it's actually incredibly optimized. Also note the Erlang VM was made to handle multiple users, as we showed in our "The road to 2M connections with Phoenix" blog post a couple years ago. More connected users will mean more memory, but Memory is cheap, and the platform scales well enough that opening a websocket on all pages as a matter of course is completely viable. Hope that helps!


I also forgot to mention we provide optimistic UI features with our loading states and annotations. For example, in the screencast, the "Save" button has phx-disable-with="Saving...", which applies on client instantly and stays until an ack is received. You can leverage the loading states as well to toggle entire containers for a happy medium between traditional optimistic and instant user feedback.


How stable do you expect LiveView's API will be going forward?

I'm especially invested in this since I've just rolled out an alpha of a project that may incorporate it in the future: https://phoenixigniter.com


As always, I can make no guarantees before 1.0, but we have really focused on refining the programming model and APIs for the last several months, so we're in a good state currently.


Hey Chris, do you have any plans in the very near future to update the example LV repo to use all of the goodies in LV 0.12+ and Phoenix 1.5+ and perhaps even add more examples?


Oh, holy crap, I'm stoked, as someone who has just started using LiveView after like too many years of single page apps... all I can say, is "oh fuck, did we get it wrong." The experience is truly great. Also, LiveComponents are pretty awesome since they don't have their own process, just mount in existing LiveView, it makes 'em really easy to reuse and performant (at least from my experience so far).

Writing UI code, in a language/environment that has first class support of pattern matching is like a dream for me. Seriously, pattern matching is sooo good when you don't have fucking classes and objects and bullshit "abstractions" in the way of your data.

Also, if you took a stab at it before 1.5, try it again. This release has all the goodies to make it nice and documentation to go with it... I'm stoked to delete the phx.live generators I copy-pasta'd into my repo from phx master a couple weeks ago trying to get my bearings.

Truly awesome work on this! Thank you so much.

Also, pro-tip, use the generators at least once, even if you have already used live view without 'em, because now there's more or less an official pattern for how to organize yer live code and it really helps.


I feel your pain on SPA's.... I feel like code velocity drops on small teams.

What about LiveView/Phoenix made the process more enjoyable - let's call it 'less painful'?


Oh, yeah, here we go:

1. Tooling, yeah, you gotta have node installed, but that's pretty much the last time you have to touch it. I'm not anti-node or anti-js by any means, but the tooling around them often turns me off. Getting to do front-end work without _having_ to think about 'em is a breath of fresh air.

2. Less duplication of effort. I don't need to define schemas twice... once in the "backend" and once in the "frontend" application. You don't think this is bad until you spend two hours adding a adding, removing, or changing a simple property to your application because you have to update the backend, the backend's api docs, its tests. Then on the frontend, adjust the schema, adjust the frontend tests, and finally see if it's working.

3. Faster iteration. I prepare a new context, and can immediately consume it in a view. Views are reloaded instantly when changes are made during development reducing the time it takes to get feedback and increasing how fast I get shit done. Also less duplication of effort REALLY helps here...

4. We (at least me) got S(F)PA idea totally fucking backwards. The idea isn't to make you're entire web site a Single Fucking Page Application, but to make individual (single) pages which NEED TO function like applications do so... Quintessential examples that do _NOT_ need an SPA: a fucking FAQ, about, or contact pages. In fact, having an "application" on top of them is more burden than not.

5. CSS is really powerful these days and provides a lot of what the 2008-2012 JS movement was trying to do. If I combine that, with being able to re-render only part of the page, I've got almost the entire flexibility of what SPAs offer with almost none of the complexity.

6. Going to a new page, and causing a page refresh, but totally knowing the next page isn't going to be broken because of the previous page's state. Page refreshes are awesome. Growing up on 28.8k that wasn't the case, but ever since I got above 10Mbps its really not something I ever even notice (though I do notice when pages are broken that shouldn't be because they're SPAs and not just fucking content).

I could probably keep rambling but I'll stop here...


For point #2, it gets even worse if you're doing GraphQL. Another layer of data abstraction on the backend to update and worry about and another layer on the frontend as well (using Apollo, etc)


I've been following this project for 5 years now, and I've really hoped it would take off. However, part of what made (and to some extent, still makes) the Rails framework so great is the surrounding ecosystem of well supported gems that makes building tedious things a breeze.

I built a few things in Phoenix in the past, and while the core framework is very simple and elegant to use, I recall having to write my own file uploading library because the one that existed had almost no documentation. This made me really hesitant to adopt Elixir / Phoenix stack for any projects I'm serious about.

I was hoping there was a world where most of the old rails community moved onto phoenix, but in the time this project has been around, it seems the backend web stack has really fragmented into a multitude of Node, Go, python, etc, while Phoenix hasn't really grown its mindshare.

For former Rails / Django devs who has made the switch: what are your thoughts on this?


In my experience, Elixir and Phoenix are both so straight forward you don't really need to rely on third-party libraries as much as you do in Rails. Some of the things you'd normally reach for a gem to accomplish is just built into Elixir itself (e.g., you don't need anything like Resque or Sidekiq because Elixir processes can do all of that and more for you).

The lack of magic is nice too. For example, it's easy to add a new custom Plug (that you wrote yourself) to your pipeline without resorting to third-party libraries to help you navigate all the magic and boilerplate you'd otherwise have to deal in other frameworks.


This happened to me with Clojure. You really get to appreciate languages with big ecosystems when working on niche languages. It's sad because these languages are more enjoyable to work with IMO. Thy are better cause they had the advantage of being created much later than the mainstream ones but that also means they had hard competition.


Seriously. I would love to work at this level of abstraction in Clojure, but to do something that is trivial in Rails with something like Devise is a chore in Clojure, and you have to put it all together yourself. Of course this makes it excellent for learning, but not so great for deadlines. More and more I think I might've made a mistake trying to do basic CRUD web stuff in Clojure for my current project.


Interestingly one of the creators of Devise is the creator of Elixr


And is currently working on an authentication "framework" (more like generators IIRC)


The other side of that coin is the huge amount of unmaintained risk in the Ruby community. When you delegate business logic to someone else's efforts you taking on the risk that the library will be maintained and patched for the lifespan of your application.

As someone else already pointed out, many of the solutions in Elixir are significantly more simple to just "roll your own" rather than have to worry about pulling 50 gems.


That's the same risk you have with any open source project. Elixir and Phoenix have similar risks. I think there's a lot to be said for getting default/easy functionality for free so you can focus on building your unique amazing things vs working on plumbing.


> That's the same risk you have with any open source project.

Yes and no. The larger the number of dependencies you have, and the larger number of maintainers that are behind them, the more chances you have of one of them containing malicious code.

I think you're pretty safe from Phoenix or Rails or NodeJS getting owned because so many people work on them. But one of the thousand small packages you use may belong to someone careless or malicious.


I totally agree. I love phoenix and elixir but it's been hard to roll out a really significant site to production because many of the things you take for granted in the rails world don't exist in the elixir world. Friendly id, acts as follower, public activity, file uploading and more are not as easy in the elixir world as rails. I think rails is still king when it comes to developer productivity but elixir's performance is amazing. And for those of you that are "roll your own", when it comes to business decisions you always have to make a trade off. Heck authentication in the elixir world is just now finally getting official support via a generator (thank Jose!) but it's not even close to devise levels of easy.


You are correct. Phoenix is better, but the community code is not there yet. Having said that... instead of using a big upload library we just do upload + signing for Azure in two very small modules. Sometimes you realize that you might need to write something yourself, true, but also that you don't need to make a full-featured Active/Action library out of it.


Coming from laravel, I've not used phoenix much, but often I find i'll need what a package 'brings' but different, or perhaps I need a package that's not updated for the latest laravel. Often if it's MIT I'll take the code and just put it in a service, modify it so it works w/ latest version, etc...

you could do the same potentially for any rails or laravel package you wanted for phoenix, obviously language constraints would be different and programming paradigm. It'd take a little bit but you could port things over, if you package it up - even contribute to the community growth.

I think choosing a framework solely because of available packages isn't a good thing. I mean nodejs probably has the most packages in it's ecosystem but a lot of them are pure shit.


I wrote a little app recently to test out live-view. It was my first time really working with it, though I've been writing elixir for years. https://gif.energy

Didn't really have any issues. There were maybe one or two gotchas but they were explained clearly by the docs (appending vs updating elements) and I was able to get it sorted easily. That whole app took a couple days, but more than half the time was wasted on iOS not supporting mp4 and webm formats for the animated shots in the chat messages. Unfortunately, liveview does not fix Apple's stupid walled garden.

Overall it was a great way to minimize the javascript involved. It doesn't make sense for certain types of apps, but it really adds a ton of value and saves a lot of time when the use case is right. And it performs really well. Loading and rendering a chatroom full of messages (with animated gifs in each message) makes a couple requests and happens in less than a second.

And combined with phoenix presence it was like...5 lines of code to add realtime online/offline statuses for users. Super cool.


> It doesn't make sense for certain types of apps, but it really adds a ton of value and saves a lot of time when the use case is right

What are some of these use cases?


The common retort from SPA devs is "what about offline?" Since LiveView keeps state on the server, it doesn't really work offline.

However, 1) you can add custom JS using LiveView's hooks, which might be enough for very simple offline behavior and 2) many SPAs don't work offline either.

If offline support is a major part of your app's design, LiveView isn't a good fit. But you could still use Phoenix Channels (the building block underneath LiveView) to provide fast push updates to your client. See the channels docs for an idea of how they work - https://hexdocs.pm/phoenix/channels.html


I'm not the person you asked this, but the BEAM (and phoenix by extension) excels in highly parallel contexts.

basically if you got an application which wants to connect everyone to each other in real time, thats a perfect usecase for the BEAM. so chat rooms, live-feeds, comments, video/audio conferencing, etc.

and thats also exactly where phoenix excels in my opinion as a occasional user. (never professionally though) quick and seamless communication between silly amounts of people with almost negligible amount of resources while being error tolerant to an extreme (functional, so almost no state)

just try it out on a weekend. its definitely worth it just to see how web-development couldve been. you'll probably go back to the old way, because thats just how you earn your money and where you already have your expertise... but its definitely amazing to see how easy it can be


This just keeps getting better and better. Thank you for your effort.

I'm a big fan, Elixir + Phoenix is excellent enough, and LiveView is what really sealed the deal for me as the perfect web development stack. It's simple, it's fast, it works. Sure, it has a few rough spots that have to be worked around when you start to push its limits, but as this blog post showed it's perfect to quickly have a working web application by completely skipping having to write client-side code. I developed a couple of prototypes and single-use applications in hours that with any other stack would have taken me days. Hell, I'd argue that in some cases it took me less time to complete my app with LiveView than it would have taken me to setup Webpack with Frontend Framework.

I don't believe it to be a silver bullet for sure, and it has to prove its worth at scale, but it gives excellent results with little effort, and honestly the reduced tedium is worth it on its own.

Also, protip: try LiveView with Tailwind CSS.


I recommend this free Phoenix course:

https://shankardevy.com/phoenix-inside-out-mpf/#mastering-ph...

I found it more approachable than the PragProg book. Helps if you've dabbled in Rails a little bit.


For those wondering how this works under the hood, there is a great presentation: https://www.youtube.com/watch?v=9eOo8hSbMAc

I wrote out a quick analysis of the details there along with some looking into the backing code in text format here: https://github.com/SaturnFramework/Saturn/issues/228#issueco...


Question to the former Rails devs out there:

We mostly see threads fawn over Elixir and Phoenix, have you experienced any downsides to switching? Anything you miss from Rails?

I'm convinced to give it a try after that demo!


I have ~6 years experience working in rails and ~3 years working with Phoenix. The only downsides I can think of are lack of official clients for APIs, and some missing packages. For example, if I wanted to do some PDF work I would really miss the prawn library. I don't miss anything from rails, Phoenix IMO is a superior web framework.


I agree. Luckily, sometimes the fix is easy. For example, I packaged my invoice PDF library[0] as a Docker container and simply created a small Elixir module that calls it.

[0] https://github.com/strzibny/invoice_printer


There's so much to like about Elixir/Phoenix. The only real downside I've experienced is that there isn't the range of libraries available compared to Ruby/Rails. That said, many of the libraries that do exist are of a decent quality with good documentation, and easy to contribute to where you need to.


It seems like a lot of companies are moving to Go for fast services. As a rails dev for 10+ years, I am looking at Go instead of Elixir and Phoenix, b/c Go is a much more popular language than Elixir.


I’ve invested a lot of time into both Go and Elixir. I like both languages a lot.

My anecdotal view of the marketplace is that Elixir recruitment emails tend to come from startups looking for their 2nd or 3rd dev, usually full stack, and the salaries are nothing special. Go recruitment emails tend to come from bigger companies looking for backend devs, often hoping for kubernetes experience too, and the pay is higher.

I built an internal service with LiveView at work and I loved it. I gave a presentation about how it all works and was hoping it would catch on. It didn’t. The front end team would probably mutiny if we told them to give up React and level up their LiveView skills.

If I were running a web business as a solo founder I would 100% want to use LiveView. As a dev on a larger team that already has specialization it’s a tougher sell.


what would you say are the benefits of using LiveView over react?


With LiveView, you've got one code base. There's no frontend/backend split, so you don't think about the API, you don't worry about going back and forth between JSON and all the associated error handling, you don't worry about versioning and keeping deployments in sync when/if you break APIs.

You shouldn't really compare it to React, you should compare it to your whole stack, and see how a lot of the code and the worries just kind of go away.

This is much like how it used to be with classic server-side rendered Rails/PHP/Phoenix... except with LiveView you can update part of the page running on the client, in response to events coming from the client without a page refresh.


Eliminating a bunch of API code.


Go may be popular, but is also a lot less complete.

Some other things to consider are that Go's concurrency model is quite bloated when compared to Elixir's, Go uses public memory for its goroutines vs. Elixir's private memory that protects processes, Go uses cooperative multitasking vs. Elixir's preemptive model, and Go's dependency handling is absolute rubbish. Elixir's process supervision is amazing and Elixir's pattern-matching allows you to write easier-to-read and more maintainable code, in my opinion.

While both are good languages, I've personally found Elixir > Go.


Which would you say is easiest to learn, for someone with a little programming experience?

I'm currently planning a SaaS project and had settled on go, but this discussion is making me wonder if perhaps Elixir is the better choice.


I think the basics of Elixir are easier to learn. The syntax is pretty straight forward and you don't have to worry about much more than functions and modules.

OPT, which is how you build supervision trees and other more complex Elixery things, is tricky at first but reading through Designing Elixir Systems with OTP, by James Edward Gray & Bruce A. Tate, and The Little Elixir & OTP Guidebook, by Benjamin Tan Wei Hao should clear it up fairly well.

This is highly subjective, of course, but I've written code in C, C++, Pascal, Basic, Python, Perl, Ruby, JavaScript, Go, PHP, Java, C#, Clojure, Scheme, Cobol, and Pick Basic (of all things). Elixir has been my most favorite language so far.


Also curious. I've been a django user for 5 years and a rails user for 9 years. I mostly use rails as an API these days and a React app for the front end.


I'd say I sometimes miss Rails' ecosystem, but the many advantages of Phoenix and especially LiveView are worth that small downside.

To someone who uses Rails/Django with React, I'd describe LiveView as something that offers pretty much everything you're used to, but with the React part consolidated with the server-side of things.

I've been playing around with LiveView since it came out, and have been using it for 'serious' work for the past year or so, and I still regularly discover ways in which this setup simplifies things, makes development faster and more fun, and saves me from various potential security flaws or 'busiwork'.

Imagine that your store (Redux, whatever) and view (React) ran in the same place as your backend.

Direct access to the database and the rest of the backend, no need to carefully consider whether it's really worth it to increase your js payload with library x, no constant context switching, no building and maintaining of, essentially, two completely separate applications, no need to make sure your API endpoints are properly versioned, or that they don't expose data that shouldn't be exposed, or that they send only the data you need. Little to no need for rube-goldberg js pipelines, and significant less time spent dealing with synchronizing state between server and client.

I'm probably forgetting some other advantages.

There are some things where LiveView doesn't seem ideal, but I've found that even in those cases I prefer using LiveView wherever I can anyways, and then I do the specific javascripty bits wherever I need them.


This is by far the most amazing demonstration of framework capability that I've ever seen. I'm stunned.

HOW do you manage to broadcast only the minuscule change of a number to all of the connected clients with server side rendering? I'm trying to wrap my brain around it.


Chris McCord has given some talks and explained this - eg see https://www.youtube.com/watch?v=8xJzHq8ru0M at about 22 minutes in


I've been writing code for close to 10 years now and I see this and feel like what a beginner would feel trying to understand assembly code. Or someone hearing a similar but new language.

Looks to me hours of work and learning got abstracted as under the hood "magic".

It's like saying: Oh, so I've been weight training for the last 17 years and I should tell you Olympic silver is not too hard, see?

Am I right in my thinking? or is learning to be this proficient with the framework not as time taking for a novice developer as I think it to be?


There's no magic. It's functionality that's made possible by the BEAM. It's just one of those things that came out of realizing how powerful the runtime was for handling certain types of problems.

When you combine a couple of those bits together, you end up with this.

The only modern web problem that Elixir isn't ideally suited for is heavy number crunching. Otherwise it gives this amazing balance of efficiency, scalability, reliability, maintainability and capability that can't be replicated in any language that has a shared memory model.


> The only modern web problem that Elixir isn't ideally suited for is heavy number crunching.

I would caveat that in a couple of ways.

First, suppose you have a web app where some requests involve heavy number crunching and others don't. In web frameworks where 1 request ties up 1 OS thread, a burst of heavy requests could gobble up all your available connections. Phoenix would use one cheap BEAM process per request, and the BEAM's preemptive scheduler would ensure that other requests are answered in a timely way and that all the heavy ones continue to make steady progress. So although the heavy requests might be completed more slowly than in another language, the overall system would remain more responsive.

Second, if you have need for heavy computation or data structures that work better with mutability, it's possible to (eg) use Rustler (https://github.com/rusterlium/rustler) to implement that part in Rust. See https://github.com/rusterlium/rustler for a story about doing this.


I'm of a similar view to them, this felt like lots of magic or at least lots of gotchas I can see myself hitting. I saw two function definition types (def and defp), pattern matching input then requiring a caret for the variable name (?), passing in "assigns" but then referring directly to other variable names, pipes, etc. There's a lot there compared to when I've worked in Erlang.


Gotchas, probably some of those. Both in Elixir and Phoenix. It is an entire language plus an entire web framework.

A lot of people find Elixir more approachable than Erlang. But I wouldn't be surprised if Erlang is technically simpler and as such potentially easier to learn. The syntax is quite foreign to most people coming from more conventional languages while Elixir reads and writes fairly conventionally.

Now Phoenix LiveView does a lot for you, so I wouldn't dismiss the claim of having some magic in there. But once someone starts to get familiar with the stateful approach the model is fairly simple and the "magic" is less mystical. A lot of the things you don't need to pay attention to would be optimizations in markup and templates and how the JS does its job. That's where a bit of magic happens.

Most of the things you mention sound like things about the language. Which I found to be very approachable and the onboarding documentation to be great.


def and defp are probably the least magical of those. def is for public functions (can be called from other modules) and defp is for private functions (cannot be called from other modules).


Are you familiar with Ruby on Rails? Phoenix was built as a simpler equivalent, to leverage websockets, and to leverage the BEAM to be performant with high concurrency (i.e., what you generally want in a web server).

Is it encompassing a lot of magic? Yes. But the quick growth in mindshare that Ruby on Rails attained back in 2005-2010 (part of which it still retains) was due to how easy it was for a novice developer to pick it up and build something useful. Pick it up and understand all the pieces, no. Phoenix is less Express/Martini in nature, more Spring/Rails (but more pleasant than either of those to work with, I would contend, but again, that's opinion).


I think the biggest hurdle would be the Functional Programming aspects. Elixir was quite easy for me to approach coming from mostly PHP, Node.js and Python (preferred Python before Elixir).

Phoenix has a sprinkling of magic or syntactic sugar through macros and stuff but the step between Phoenix and LiveView is not that mystical to me.

I have taught a novice developer, not yet out of 2-year school for web dev, to use Elixir and the Phoenix Framework. I really should interview him about that. Write something up.

I would say that Django does more stuff under the hood than Phoenix. But they are fairly different vehicles.


> On the heels of the official LiveDashboard release, Phoenix 1.5 projects now ship with LiveDashboard by default, for real-time performance monitoring and debugging tools.

and it uses uPlot [1][2] in the metrics panel :D

[1] https://news.ycombinator.com/item?id=21207132

[2] https://news.ycombinator.com/item?id=22567922


I have been watching Phoenix/Elixir for a while and wondering if it has gained a lot more traction compared to say 2 years ago ? My choice of full web app framwork is Symfony/Laravel (PHP) or Python (Flask/Django) but I really like what Phoenix has to offer.

However, does it have a mature ecosystem now ? What about deployments and tools around it ? Does it work with generic web servers like Nginx or does it run its own http server ?


The ecosystem has been quite mature for a while. The language reached v1.0 almost 6 years ago and Phoenix v1.0 was released almost 5 years ago. The community has built a lot on top of them since then.

The deployment topic is wide, so the answer will depend on your favorite ways to deploy. If you are using Heroku or another PaaS, it has been very straight-forward since ever. If you want to ship a self-contained executable or a Docker image, the language has standardized on the tooling for assembling those in the last year or so (they are called releases). It was always possible before, just not standardized at the language level.

It runs its own http server but you can easily put it behind nginx, websockets included, by using the reverse-proxy settings. Here is an example article: https://dennisreimann.de/articles/phoenix-nginx-config.html


I’m a long time Python dev converted to Elixir (for ~3 years now, mainly web dev and data pipelines).

The tooling and developer experience in Elixir is first class and the ecosystem is highly mature.


Coming from Python as well I'm really impressed with the tooling. `mix new` is just amazing.


I would say it is quite mature. The ecosystem is a bit smaller and younger, so sometimes you'll find an insufficient library somewhere or no library at all. But I've never had a show-stopper in that regard.

I've done plenty of Django and Flask and I'd rather work with Phoenix. I still like Django plenty but only time I'd pick it is if I think the admin might save me copious time or if there is something else tying the project to Python, such as machine learning.


I run a Crypto arbitrage service www.coinvana.in built with phoenix and deployment consisting of digital ocean, nginx, ssl, mix releases, github actions among other things. At this moment, I just git push my updates to github and all pieces of deployment are taken care of.


Wouldn't you typically run Nginx (or something similar) as a reverse proxy anyways in production?


correct. I was just wondering if it also has inbuilt http server as well to process things like static files etc or is that completely on 3rd party tools like nginx (which I love btw). Kinda like in Golang where you could technically use the static file server but I always use nginx for those things.


Cowboy is Elixir's built-in HTTP server. You can configure things like Nginx or Haproxy as you would with most other frameworks.


Cowboy is not made in Elixir and it's not built-in. It's an HTTP server made in Erlang (which Elixir can call at no runtime cost): https://github.com/ninenines/cowboy


It's more an Erlang http server used by Phoenix ;)


The video is hilarious in a good way. You can hear the disbelief and amazement in Chris McCord's voice when Liveview works as he (and team) developed it.


Disbelief might be a stretch, but he is clearly extremely excited about the recent advancements and proud of what the team has been able to accomplish.

I agree that it's fun to witness that level of passion and it makes me happy that Chris is so amped about this.


Looks interesting but I am not interested in making timelines .. is this Phoenix framework general enough to make arbitrary real time web apps?


Absolutely. We have extremely varied usage in the wild. From sports/content websites with tens of millions of users (bleacher report, cars.com), to folks running social/chat services with millions of persistent connections, to folks running Phoenix on embedded systems. And as you would expect, there's a ton of "boring business app / JSON API" usage in there as well, so we have a good story about generalized use. The goal of the screencast, as I outlay in the beginning is to show how easy LiveView makes it to build interactive and real-time applications, and a social timeline was a decent way to do that ¯\_(ツ)_/¯


Happy LiveView user here :) Can confirm it can be used in many scenarios. One of my favorites is streaming realtime data to a chart. I serialize my data as JSON in the LiveView template and read it back in from a Hook. Saves me time by not having to create a separate API endpoint. e.g.

  <div
   phx-hook="MyChart"
   data-days="<%= Jason.encode!(days(@balances)) %>"
   data-amounts="<%= Jason.encode!(amounts(@balances)) %>"
  >
   <div phx-update="ignore">
   </div>
  </div>


You can see some other examples of LiveView apps at https://phoenixphrenzy.com/results


I'm currently using it to make a restaurant POS. It's very flexible. Everything composes like lego pieces in a very clean and straightforward way with surprisingly little magic.


Yes, think of it like Rails for the Elixir language.

Phoenix -> Elixir

Rails -> Ruby


But without requiring all of the ActiveSupport patches to the base language!


i'm currently using it to make a board game where updates are pushed live to everyone. it's the most pleasant experience i've ever had writing a webapp.


I've been observing Elixir and Phoenix from the outside for 4 years or so now. There was a lot of initial hype and it died down a little bit but I'm really happy to see how far it's come and how polished everything looks. The lack of static typing initially made me pause but maybe it's time to get over it. As someone who tends to program in a functional style anyway (if a language supports it), losing the overhead of OO paradigms would not be a deal breaker and probably pretty liberating.


When I see a Phoenix post, I upvote. It's so great in terms of almost everything - simple, productive, powerful, and fast. If you're a web developer, go try it out if you haven't.

I might be too greedy, but if there could be a solid JavaSript support Elixir/Phoenix just like ClojureScript that would be perfect. Phoenix and Liveview are great, but I really hope it can extend its reach to React Native and Electron so that we don't have to write too many extra things for those platforms.


Lumen may be the answer to this in the future: https://www.youtube.com/watch?v=uMgTIlgYB-U&list=PLqj39LCvnO...


Yeah, really looking forward to see this project keeps growing! I really hope we can use it in projects soon.

Implementing runtime for Elixir in JavaScript is quite challenging IMO. Kudos for Dockyard trying to tackle this.


Lack of built in user authentication kills this project for me, that's just something I don't want to deal with building my own anymore after django.


We are actually working on a `mix phx.gen.auth` generator. Check Dashbit's blog about it:

https://dashbit.co/blog/a-new-authentication-solution-for-ph...


The Phoenix Ecosystem has solutions for authentication and authorization.

ueberauth is one of the most fully featured with support for a ton of different authentication schemes (https://github.com/ueberauth/ueberauth)

But there are lots of other things that integrate with Phoenix / Plug (https://github.com/h4cc/awesome-elixir#authentication)


Pow is pretty great: https://powauth.com/


Not built-in, but you look up several great projects for auth or use something like Auth0.



I'm so happy. Just got back to my side project and Phoenix 1.5 is released.

Thank you Chris and Jose and all those who were and are involve with Phoenix.


This is pretty darn awesome. I remember looking at LiveView a few months ago and being impressed. Elixir and Phoenix are still my favorite backend to use for personal projects, but now with LiveView I'm thinking I'm going to start using it fullstack.


I like the smell of new, well designed technologies.


How would this scale for, I don't know, 10k concurrent users? Would a live chat app be reasonable?


Here's an example of using it with 2 millions users: https://www.youtube.com/watch?v=c6JcVwbOGXc


I'm assuming the parent meant how would this specific configuration of elixir + phoenix + liveview scale.


The answer is applicable. LiveView is implemented using Phoenix Channels.


I'd say live chat and many concurrent users (+ many small messages being sent around) is exactly the kind of thing that Phoenix (and LiveView, and Elixir) is basically made for.


A live chat app is its sweet spot.

It runs on the same Erlang VM that Whatsapp used to scale to hundreds of millions of users on under 30 machines and very few employees.


Excuse my lack of knowledge, but I was always under the impression that websockets are not that scalable since you are opening 1:1 connections.


Thst not true in the Elixir ecosystem. The numbers I see on my 5$ droplet are sth I haven't seen before. And that after writing 5% of code that i usually had to write in other stacks.


It's so great to see this released. The community has been excited about LiveView for a long time!


Wish they had an example on data tables, real-time search and other dashboard-like functionality.



Fantastic!

For rails people who are unaware there is already a lib that has copied this approach.

https://expo.stimulusreflex.com/demos/tabular


This is excellent and I’d love to look into this .

That being said why would I pick this over go or scala for example ?

I’m having a hard time finding a decent argument in the thread bedside syntax.

Can someone elaborate?


What? It's anything but the syntax. The automatical live updates and the latency, the diff algorithm and the size of the payload, no client/api/controllers/routes needed, the scalability and stability, and the free clustering behind the framework.

Can you rebuild this demo in Go or Scala in 15 mins or in 1 hour, correctly push any updates to the client while maintaining the robustness and sharding across the cluster? Writing stateful services correctly is very hard using an average web framework.

I need at least 1 day to implement the same in Go or Scala, only the functionality but neither the clustering nor the optimization. And I'm considering I myself a functional programmer that is very familiar with Scala.


What if you get disconnected due to bad network (LTE in transport). The reconnect will recover the state from the server or you loose everything ?


It automatically reconnects. I wrote about the client/server state here: https://news.ycombinator.com/item?id=22897436

In a nutshell, temporary state in the client (URLs, forms) are resubmitted on reconnect. The server state is typically backed by a database.


Anyone know where you'd get started with T&C's/PrivacyPolicy if you were actually taking something like this live?


Is there a tutorial or course I can purchase like beginner to all the way to deployment on Digital Ocean or something like that ?


FYI, Pleroma is a Mastodon clone written in Elixir with Phoenix, might be good to check it out.

https://git.pleroma.social/pleroma/pleroma





Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: