The upside of node-apn + fcm-node is that it's the least complicated solution in terms of dependencies. On the other hand, integrating two separate libraries wasn't very appealing.
node-pushserver is a full fledged server rather than a library, so it has its own storage (MongoDB) but on the other hand it's only meant to be hosted internally as it doesn't have any security mechanisms. I would need to do a significant amount of rework to get it to work on Heroku together with Postgres, so this was a non-starter.
Next I looked at using third party services on top of the platform gateways: Pushwoosh, Urban Airship and Amazon SNS. Pushwoosh and Urban Airship didn't seem to offer any clear advantage in terms of API or documentation over SNS, while SNS offers extra features because it supports other platforms (eg Windows) and delivery mechanisms (eg SMS) in addition to iOS and Android, which could become useful in the future. I ended up selecting SNS.
The resulting components in the system look like this:
In order to receive push notifications, the device has to register with its platform's notification service:
Once it's registered, here is how a notification gets sent:
ARN - Amazon Resource Name, a scheme for identifying resources and API endpoints.
Application - a sort of an entry point into the API; an application has to be created for each platform, with device endpoints grouped under an application
Token - push ID retrieved by the device upon registering with the push notification service.
Endpoint - address of a given device or topic to send notification to
Topic - a channel, a way of sending notifications to multiple devices; individual devices can be subscribed to zero or more topics.
When I was reading documentation on Android push notifications, I found references to FCM and GCM. GCM has been superseded by FCM, although GCM continues to function and this is actually what SNS relies on.
SNS doesn't actually provide a uniform interface across platforms. Instead, separate payloads have to be specified for each platform unless you happen to be sending a simple text message:
Note also that platform specific payloads have to be stringified, and then the whole combined payload has to be stringified before it's sent to SNS.
Production and development on APNs have to be set up separately, leading to confusing results if the wrong push ID is used.
Ad hoc or production builds will be set up for production APNs access, whereas development builds will be set up for development APNs access.
When I was reading about APNs, I found references to a "feedback service". This used to provide information about devices which have become inactive. However, it turns out that this has been removed, and individual requests to APNs now return a status. Consequently, APNs marks the device endpoint as inactive if it receives a failure response from APNs.
Action buttons have to be defined in the message payload, and there is some corresponding setup to be done on the mobile client side.
It's apparently possible to use GCM on iOS as well as Android, but it's not going to be as efficient because it isn't built into the OS.
On Android, notifications can be marked as normal or high priority. The delivery of normal priority notifications can be delayed.
If you liked this post, maybe you'll enjoy one of my books?