Zurga

Zurga

In a quest to optimize the amount of data sent between the server and client I recently decided to try to use MessagePack instead of JSON. The payloads are about 75% of the size in JSON, which is nice. I have not noticed any performance issues related to encoding and decoding.

There is a StackOverflow answer that I used for the basis for this post and @chrismccord helped me with a crucial bit of information. To get LiveUploads to work, a bit of extra code is necessary.

If you spot any improvements or errors, please tell me and I will update the code.

In assets/app.js you import the MessagePack client:

import {Encoder, Decoder} from "@msgpack/msgpack";
const encoder = new Encoder({ ignoreUndefined: true });
const decoder = new Decoder();

....
const liveSocket = new LiveSocket("/live", Socket, {
  // hooks  and params stuff
  encode: (payload, callback) => {
    // We convert binary payloads to a Uint8Array, so MessagePack will send pack it.
    if (payload.payload instanceof ArrayBuffer) {
      payload.payload = new Uint8Array(payload.payload)
    }
    callback(encoder.encode(payload));
  },
  decode: (payload, callback) => callback(decoder.decode(payload)),
})

The serializer looks like this :

defmodule MyAppWeb.MsgpackSerializer do
  @behaviour Phoenix.Socket.Serializer

  alias Phoenix.Socket.Reply
  alias Phoenix.Socket.Message
  alias Phoenix.Socket.Broadcast

  def fastlane!(%Broadcast{} = msg) do
    msg = %Message{topic: msg.topic, event: msg.event, payload: msg.payload}

    {:socket_push, :binary, encode_to_binary(msg)}
  end

  def encode!(%Reply{} = reply) do
    msg = %Message{
      topic: reply.topic,
      event: "phx_reply",
      ref: reply.ref,
      payload: %{status: reply.status, response: reply.payload}
    }

    {:socket_push, :binary, encode_to_binary(msg)}
  end

  def encode!(%Message{} = msg) do
    {:socket_push, :binary, encode_to_binary(msg)}
  end

  defp encode_to_binary(msg) do
    msg |> Map.from_struct() |> Msgpax.pack!()
  end

  def decode!(message, _opts) do
    decoded = Msgpax.unpack!(mesage)
    payload = Map.get(decoded, "payload")

    # LiveUpload sends us binary, but MessagePack is always binary so we cannot use the opcode in the opts.
    if is_binary(payload) and not String.valid?(payload) do
      Map.put(decoded, "payload", {:binary, payload})
    else
      decoded
    end
    |> Phoenix.Socket.Message.from_map!()
  end
end

And then in your Enpoint module use the serializer in the socket:

socket("/live", Phoenix.LiveView.Socket,
  websocket: [
    serializer: [{MyAppWeb.MsgpackSerializer, "2.0.0"}]
  ]
)

Showing Posts 1 to 1

Zurga

Zurga OP

Update, the check in serializer does not work when an array of zeroes is sent. It is probably better to check the “event” key in the message directly.

So the decode!/2 function in the serializer should probably use the following check:

if decoded["event"] == "chunk" do
— All posts loaded —

Where Next? Top

Trending in Guides/Tuts Top

c4lliope
# ~/src/livebook/.iex.exs System.cmd("xdg-open", [ LivebookWeb.Endpoint.access_url() ] ) Because Livebook requires a unique passcode on ...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews