Hacker News new | past | comments | ask | show | jobs | submit login

Phoenix / LiveBeats author here – happy to answer any questions about Phoenix, LiveBeats, or Fly.io. We had a ton of fun building this. It's way more fun to see where folks are connecting to and what kind of pings they get than I would have thought. I also just put out a screencast showing how easy it is to deploy a new phoenix instance on another continent and watch it cluster together with the rest automatically: https://www.youtube.com/watch?v=JrqBudJd2YM&feature=youtu.be



That video is really cool, it's so impressive how the Elixir/Phoenix/Fly combination works together. Just for context could you give an idea of what that app would cost to run at the scale you're demoing there per month? I think it's 7 DB instances + 7 DB volumes + 5 app instances + 5 app volumes at the end of that video, but not sure what instance sizes etc. you're looking at for this.

Also totally random question - how come the flag for the chrismccord user is different for the two users at 9:25 https://youtu.be/JrqBudJd2YM?t=565? Is that just something in your app, or is there something in Fly reporting at a different granularity? I'm not familiar with the flag in the left window so might be missing something obvious!


You can run LiveBeats on the smallest instances. You end up needing 2 small VMs and 2 10GB disks per region. So it costs about $6.80 per region to get started. ~$150/mo to run in all our regions with the small VMs. Most apps only need 3-6 regions to get really great performance.

The interesting thing about adding regions is that it also scales capacity horizontally. The way we route traffic means we can max out a region then spillover to the next one. And the way LiveBeats uses disks, each new region adds 10GB of song storage too.

Chris gets this stuff for free so he put way bigger CPUs and disks on the databases than they really need.

---Edit---

I did that wrong. It's ~$6.80 per region. Not ~$13.60 per region.


LiveBeats is hotlinking https://fly.io/ui/images/<region>.svg and Kurt updated a few of the US region images to be more specific vs blanket flag. The browser on the right is chrome, with the cached old image, and left is safari with the new one :)


Just wow. This is so cool!

I watched your presentation some years ago when you first demoed Phoenix LiveView. I think I and all my work buddies put our personal projects on hold waiting for a beta to come out so we could play with it! It's been fun to see this project mature so well.

Are the things happening with this little project here or with LiveBook what you had in mind when you made LiveView? Or have projects more manifested themselves as you've been able to prove out the capabilities of LiveView?

Anyway, thanks for making web development fun again!


Hey Chris. Great demo. It got me interested enough in Elixir to order a book. Does LiveView work well bi-directionally? For example, is there a demo of implementing Google Docs in it? Curious about the whole class of issues there vs. broadcasting changes from a single publisher -> many consumers.


Livebook, which is an elixir code notebook built with LiveView includes collaborative editing with presence, so it absolutely can be used in that domain. LiveView is built on phoenix channels, so it's all bidirectional communication. The client can send events from JavaScript. We use js hooks for the pings in LiveBeats for example:

    //js
    Hooks.Ping = {
      mounted(){
        this.handleEvent("pong", () => {
          let rtt = Date.now() - this.nowMs
          this.el.innerText = `ping: ${rtt}ms`
          this.timer = setTimeout(() => this.ping(rtt), 1000)
        })
        this.ping(null)
      },
      destroyed(){ clearTimeout(this.timer) },
      ping(rtt){
        this.nowMs = Date.now()
        this.pushEvent("ping", {rtt: rtt})
      }
    }

    //liveview
    defp handle_event("ping", %{"rtt" => rtt}, socket) do
      {:halt,
       socket
       |> rate_limited_ping_broadcast(socket.assigns.current_user, rtt)
       |> push_event("pong", %{})}
    end


Check out livebook.dev, it's pretty mindblowing! It's like Jupyter but for Elixir, and fully collaborative. It's about as close to Google Docs as I've seen.


Have been looking at the fly/Phoenix combo for a while

The one thing I can't wrap my head around is scaling, and the cost of scaling.

If this app magically exploded to 10,000 users at one time:

1. How do I scale with Fly.io? Can I autoscale, but somehow cap at a cost?

2. What parts of the stack would I have to pay attention to? Erlang/Elixir seem to handle a lot of the complication?

3. Are there (hidden?) costs that would concern me at fly.io with 10,000 simultaneous users? Or is there a clear way to estimate the costs at different points?

thank you - this looks very promising and (more importantly) fun!


Depending on your workload, a single Elixir (BEAM) node will happily serve 10k users without breaking a sweat


This is true but you also need to account for memory usage.

With Live View it's kind of easy to shoot yourself in the foot and end up going out of memory very quickly unless you already know the pitfalls beforehand and know how to counter them all.

For example, if you were storing 1MB of data for each connection and you had 10,000 users suddenly your server is going to require 10gb of memory or your server is going to crash. If you went even more viral and had 100k users now you need 100gb of memory. If you scale things back to 100kb per connection that's still 10gb of memory for 100k users.

You can use a LV feature called temporary assigns to help counter this for certain things but this requires knowing about that beforehand and also coding around using that feature.

You need to constantly make decisions like, well I want access to the user-agent of the person on the site but if I save that on the socket then that alone might be around 1k of data. If I have 50,000 users on my site, just having access to the user-agent means your server is using ~50mb.

Basically once you start dealing with storing state for each connected user in its own process you have a whole category of things to think about vs developing a more traditional app that's stateless. That doesn't mean LV is bad, but it's a much different animal than having a stateless web app serving 100k requests on a tiny server and putting a CDN / caching layer in front of it.


thanks nickjj

"a stateless web app serving 100k requests on a tiny server and putting a CDN / caching layer in front of it"

That's a great question. For "live" stuff, it seems to me that Pheonix brings so much joy and simplicity, I'd happy pay for memory and hopefully scale in a sustainable way. This is all theoretical until we get a successful app, but it's good to see the future paths :)


It's very useful but I also think (and this is strongly a personal opinion) that too much live components break the core ethos of the web.

For example, personally I don't want everything changing on my screen in real-time, I want to consume content on my own terms. When I want the content to refresh I will reload the page. Otherwise it creates too much distractions with the screen bouncing around and content changing under your feet that's out of your control.

I think you can tastefully update areas of a page where it provides very high value but that's IMO the exception not the norm. Of course if you want to build another Discord or a live chat (or something like LiveBeats) then sure that's great.

This idea of using WebSockets for everything (even transitioning pages) amplifies the issue even more, but I think it's ideal for things like notifications and what LiveBeats does for keeping the audio player in sync across clients. That's why I really like Hotwire as an alternative to Live View, it uses stateless HTTP for everything and you can still do partial page updates for the person who rendered the page. Then you can optionally opt-into using WebSockets when broadcasting events to more than the person who rendered the page. It's also back-end agnostic. You get the best of both worlds, being able to use HTTP for just about everything and then sprinkle in WebSockets for the real-time broadcasted events. This lets you continue using a tiny server + CDN without worrying about memory being hold onto for each process and you can opt into event broadcast functionality as needed.


Some small sugesstions When a file upload finish is not very clear that It finished, maybe you can change the color of the bar(or add an icon) to signal that it finished

also, I don't know if it was just me but the upload popup didn't work only the drag and drop one.

apart from that very cool project I also am an elixir developer but haven't had the chance to test liveview but it looks very good


Good suggestions. There is indeed a bug on chrome when clicking on the file link vs drag and drop. Something about dispatchEvent("click") vs .click(). Will fix in a bit!


Hi Chris,

Is there any chance this[0] could be reopened?

The problem I have with a JS hook is that if you do a "socket |> push_event() |> push_redirect()" the hook is actually destroyed before writing the cookie.

Currently I'm using "Process.send_after(self())" to delay the redirect, it's not that ideal.

[0]https://github.com/phoenixframework/phoenix_live_view/issues...




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

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

Search: