Pigeon - iOS and Android push notifications for Elixir



After just over two years in development, this latest version of Pigeon is what I finally consider done in regards to my original vision for the project. v1.1 brings several needed API-breaking changes that should have been rolled into v1.0, but were otherwise overshadowed by the complexity of the FCM http2 implementation. Special thanks to @talklittle for his help on this release.

What is Pigeon? It’s a library for sending iOS, Android, and Amazon Android push notifications. Check out the project: https://github.com/codedge-llc/pigeon

What’s New

Kadabra Bumped to v0.3.2

Kadabra is an HTTP/2 client I wrote from scratch specifically to support Pigeon. v0.3+ brings significant stability improvements (and might actually run a bit faster). This bumps the minimum requirements to Elixir v1.4 and OTP 19.2

Runtime Worker Configs

APNS/FCM/ADM worker connections are now started with custom structs. The old config style is still valid, but it is recommended to use the new style.

# config.exs
config :pigeon, workers: [
  {YourApp.Pigeon, :apns_config},

# your_app_pigeon.ex
defmodule YourApp.Pigeon do
  def apns_config do
      name: :apns_default,
      mode: :prod,
      cert: System.get_env("APNS_CERT"),
      key: System.get_env("APNS_KEY"),
      reconnect: false,
      port: 2197,
      ping_period: 300_000

Note: :apns_default, :fcm_default, and :adm_default still need to be specified as names in your config if you want pigeon to push to them by default.

Standardized Notification Responses

Notifications now contain the push response on the notification itself. This makes sending batches of notifications more straightforward. APNS and ADM now have a :response key indicating success or failure.

FCM.NotificationResponse has been done away in favor of this new style, though the syntax is a bit different. :response is a keyword list of [{response, "reg id"}] for per-regID responses. There is a second :status key on the notification that indicates whether the whole batch was successful.

Example usage for async response handling on FCM

def handle_response(%FCM.Notification{status: :success, response: responses}) do
  Enum.map(responses, & handle_regid(&1))
def handle_response(_else) do
  # some sort of error

def handle_regid({:update, {old, new}), do: #update
def handle_regid({:invalid_registration, regid), do: #remove
def handle_regid({:not_registered, regid}), do: #remove
def handle_regid({:unavailable, regid), do: #retry

FCM.push(notif, on_response: &handle_response/1)

Roadmap Ahead

Forcus is now going to shift to tackling some of the smaller features that have been on the backburner. Among these:

  • JWT token support for APNS
  • Topic subscriptions for FCM
  • Better onboarding for contributors (mock APNS servers anyone?)

Thanks to everyone who has contributed to the project over the past couple years. As someone who was previously never very involved with open source, I feel like I’ve learned a lot in the process.

How to build a push notification server in Elixir/Erlang?

Congratulations @hpopp! Just wanted to say you’re doing a great job as the maintainer of Pigeon, and collaborating with you on pull requests and issues has been a pleasure.

Also I’ve been running Pigeon in production for nearly a year, and it’s been pretty stable, not to mention a breeze to set up. Thanks for your contributions to the Elixir ecosystem!


Does pigeon implement the full IPoAC Protocol? :slight_smile:


Maybe in a future release. I hear supervision is a bit complicated when they die.


v1.2.0 Released

Now with support for APNS JWT configuration! Special thanks to @Lankester for the feature.

It’s very simple to configure! Pigeon can auto-detect whether you are using a certificate or token config.

config :pigeon, :apns,
  apns_default: %{
    key: "AuthKey.p8",
    key_identifier: "ABC1234567",
    team_id: "DEF8901234",
    mode: :dev

:key is configured just like :cert, which can be a file path, file contents, string or tuple.

Kadabra Updates

Pigeon now uses Kadabra 0.4.2, which brings more http2 stability improvements. Various race condition errors during connection shutdown should now be fixed!

Roadmap Ahead

The only remaining major feature is FCM web push encryption support. Once implemented, focus will shift to improving the reliability of error handling for failed push notifications. There are certain Kadabra API changes in the works that will make this task much easier. It’s finally starting to mature into a more general purpose http2 client. Take a look at the repo if you haven’t already.