Pigeon: push notifications for Elixir across APNS, FCM and Amazon ADM
iOS and Android push notifications for Elixir
At a glance
- What is it?
- Pigeon is the Elixir library Codedge maintains for sending iOS and Android push notifications, with a module per push service and a dispatcher and adapter extension point for anything else. Version 2 was a rewrite with a migration guide, and the library tracks the Elixir versions that still get security patches.
- Who is it for?
- Pigeon fits an Elixir team sending mobile push notifications who wants one dependency covering APNS, FCM and Amazon ADM rather than three, and who is willing to follow the v2 line and read a migration guide. It does not fit a project that cannot set platform credentials, since the test suite needs environment variables for them, and it does not fit someone expecting a default dispatcher configuration to be the right one for a high volume send.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 44 days ago.
- What is it written in?
- Mainly Elixir, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One library for the three push services a mobile app actually needs
Pigeon describes itself in one line as iOS, APNS, Android, FCM and Amazon Android, ADM, push notifications for Elixir, and that line is the whole scope. The reason a single library exists rather than three is that the surface area of each push API is large and the parts you actually touch are small. You want to send a message, with a title, a body, some data payload, to one device token or to a topic. The credential format, the HTTP/2 connection handling and the platform-specific payload shape differ, but the call site does not need to. The project is published on Hex as the pigeon package, with module documentation for each service, and the repository is under the codedge-llc organisation, which is the company that maintains it.
Adding it is a mix.exs entry and a version floor
The installation is a dependency declaration in mix.exs.
def deps do
[
{:pigeon, "~> 2.1"}
]
endThe interesting part is the version policy that follows it. Pigeon supports every Elixir version that still receives security patches, currently 1.16 and later, and the README says the minimum version moves forward when Elixir drops a branch from support. That is a deliberate choice and an unusual one in the ecosystem. Rather than pinning to whatever Elixir the library happened to be written against, the supported floor tracks the language's own maintenance reality, so you are not forced to upgrade the language to use the library, and you are not left on a library that stopped caring about your runtime. It does mean the library will raise its floor over time, and a team on an older Elixir will find the version constraint moving.
A module per service, and the docs are the entry point
The getting started section is three links, one per service, and the instruction to check the module documentation for your push notification service. Pigeon.ADM covers Amazon Android, Pigeon.APNS covers Apple iOS, and Pigeon.FCM covers the Firebase Cloud Messaging v1 API. The specific mention of the v1 API is a version detail worth noticing, since FCM has an older interface still floating around in most tutorials, and a library that names v1 explicitly is a library that has been updated for the current API. The structure implies that each service module owns its own configuration, its own connection handling and its own message shape, and that you reach for the one you need rather than configuring a single unified client that handles all three.
Dispatchers are pluggable at runtime, not just at compile time
The advanced part of the library is the dispatcher, and the README frames it in terms of scale. Pigeon can spin up dynamic dispatchers for a variety of advanced use cases, such as supporting dozens of dispatcher configurations or custom connection pools. The distinction that matters is between a dispatcher configured once at application start and a dispatcher created at runtime for a particular purpose. If your app needs a different pool of connections per tenant, per region or per message class, a static configuration forces you to build the union of all of them up front and keep them all alive. A runtime dispatcher lets you construct exactly the one you need, use it, and let it go. The documentation pointer is to the Pigeon.Dispatcher module.
An adapter interface for services Pigeon does not ship
If you need a push service that is not one of the three, the README asks whether you want to write a Pigeon adapter for it and points at the Pigeon.Adapter module for instructions. This is the extension point that keeps the library from being a closed set. An adapter is the seam between the generic notification concept and one provider's protocol, so a team with an enterprise push service, a self-hosted gateway or an internal relay can implement the interface once and then use the same sending code as for APNS. The two extension points together, dispatcher for how connections and configuration are managed, adapter for what protocol is spoken, are what make Pigeon usable in an organisation that has more than one push destination.
The test suite needs real credentials, which shapes how you test
The contributing section has an honest line about testing. Unit tests can be run with mix test or mix coveralls.html, and environment variables will need to be set for various credentials, with the full list in the config/test.exs file. That is a meaningful constraint for anyone integrating the library. A test suite that requires live platform credentials is not a unit test suite in the usual sense, it is an integration suite that happens to use the unit test runner, and it means the pipeline needs secrets configured for APNS, FCM and ADM, or for whichever subset you actually use. The config directory in the repository, and the coveralls.json file for coverage reporting, show that this is a project with a working continuous integration setup rather than a token one. There is also a .tool-versions file, which pins the Elixir and OTP versions the project itself develops against.
v2 was a rewrite, and the migration guide is the thing to read
The README has a short section on upgrading from v1.6 with a link to a migration guide, and that is a signal about the scale of the change. A 2.0 release with a dedicated guide rather than a short changelog usually means the public API moved. The release history supports that reading: v2.0.0 on 2024-12-09, v2.0.1 on 2024-12-28, and then a long gap before v2.1.0 on 2026-09-08, which is the version the current dependency example points at. If you are on v1.6, the upgrade path involves reading that guide rather than bumping the constraint, and you should expect to revisit your dispatcher and adapter code. The repository also has a CHANGELOG.md at the root, which is where you look for the detail the README does not carry.
MIT licensed, with the house style spelled out for contributors
The licence is MIT, with copyright held by Codedge LLC for the period 2015 to 2026, and the LICENSE file in the repository has the full terms. Two contributor conventions are worth noting because they tell you what the project cares about. Formatting uses Elixir's mix format together with Prettier, and the README asks you to add editor hooks to run it after a save, respecting the project's .formatter.exs, with a .prettierignore file for the parts Prettier should leave alone. Commit subjects use the Karma style. Both are small things, but they are the kind of thing that a maintained library gets right so that every patch merges without a formatting debate. The repository is not archived and the last push was on 2026-09-08, the same day as the v2.1.0 release.
Editorial conclusion
Pigeon fits an Elixir team sending mobile push notifications who wants one dependency covering APNS, FCM and Amazon ADM rather than three, and who is willing to follow the v2 line and read a migration guide. It does not fit a project that cannot set platform credentials, since the test suite needs environment variables for them, and it does not fit someone expecting a default dispatcher configuration to be the right one for a high volume send. Verify first which Elixir version you are on, since support follows the versions still receiving security patches, and read the migration guide before upgrading from v1.6.
Frequently asked questions
How do I add Pigeon to an Elixir project?
Add it as a mix.exs dependency with {:pigeon, "~> 2.1"} in the deps list. Pigeon supports every Elixir version that still receives security patches, currently 1.16 and later, and the minimum moves forward when Elixir drops a branch from support.
Which push notification services does Pigeon support?
Three services have their own modules: Pigeon.APNS for Apple iOS, Pigeon.FCM for the Firebase Cloud Messaging v1 API, and Pigeon.ADM for Amazon Android. The README points you at the module documentation for whichever one you use.
Can I use a push service that Pigeon does not support?
Yes. The README says you can write your own adapter for an unsupported push notification service, with the instructions in the Pigeon.Adapter module documentation. Pigeon can also create dispatchers dynamically at runtime for advanced cases such as dozens of dispatcher configurations or custom connection pools.
How do I run the Pigeon tests?
Run mix test or mix coveralls.html. Environment variables need to be set for the various credentials, and the README points to the config/test.exs file in the repository for the full list.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/codedge-llc-pigeon)Was this useful?