Hammad
Hammad

Reputation: 2137

Send web push notification to all subscribers in one call

I am implementing web push notifications with service workers in my website. I have a job website and new job is posted after every hour. I want to notify the subscriber of new job when it is posted. I have done the implementation in getting user subscribed and written node server as well to send push notification by generating VAPID keys.

I have a question, I feel when I need to send push notification to all subscribers then do I need to send new call for each user or there is some mechanism to send it in one call to all subscribers.

For example, if I have 100,000 then do I need to make 100,000 calls or there is some other way to send 1 call and notify all 100,000 subscribers about the new job update in one go?

I definitely feel that I will be throttled by relevant browser service if I send thousands of calls in one go.

Is there a way to do it with one call?

Here is my current code route from express server of sending notification to all subscribers.

const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
const Subscription = mongoose.model('subscribers');
const q = require('q');
const webPush = require('web-push');
const keys = require('./../config/keys');
router.post('/', (req, res) => {
    const payload = {
        title: req.body.title,
        message: req.body.message,
        url: req.body.url,
        ttl: req.body.ttl,
        icon: req.body.icon,
        image: req.body.image,
        badge: req.body.badge,
        tag: req.body.tag
    };

Subscription.find({}, (err, subscriptions) => {
    if (err) {
        console.error(`Error occurred while getting subscriptions`);
        res.status(500).json({
            error: 'Technical error occurred'
        });
    } else {
        let parallelSubscriptionCalls = subscriptions.map((subscription) => {
            return new Promise((resolve, reject) => {
                const pushSubscription = {
                    endpoint: subscription.endpoint,
                    keys: {
                        p256dh: subscription.keys.p256dh,
                        auth: subscription.keys.auth
                    }
                };

                const pushPayload = JSON.stringify(payload);
                const pushOptions = {
                    vapidDetails: {
                        subject: 'http://example.com',
                        privateKey: keys.privateKey,
                        publicKey: keys.publicKey
                    },
                    TTL: payload.ttl,
                    headers: {}
                };
                webPush.sendNotification(
                    pushSubscription,
                    pushPayload,
                    pushOptions
                ).then((value) => {
                    resolve({
                        status: true,
                        endpoint: subscription.endpoint,
                        data: value
                    });
                }).catch((err) => {
                    reject({
                        status: false,
                        endpoint: subscription.endpoint,
                        data: err
                    });
                });
            });
        });
        q.allSettled(parallelSubscriptionCalls).then((pushResults) => {
            console.info(pushResults);
        });
        res.json({
            data: 'Push triggered'
        });
    }
});

});

router.get('/', (req, res) => {
    res.json({
        data: 'Invalid Request Bad'
    });
});
module.exports = router;

Upvotes: 1

Views: 3465

Answers (2)

If you want to make just one API call, you can use Firebase for that. You can just subscribe your users to a "topic" and then make just one API call to FCM endpoint specifying this topic in request body and let Google handle all the work to send push notifications to your subscribers. Also you can use your current VAPID keys in your firabase project.

Upvotes: 1

collimarco
collimarco

Reputation: 35400

Currently the web push standard doesn't allow to send the same notification to multiple recipients: if you deal directly with the browser push service you will need to make a different call for each recipient.

I have already asked this on the official Github repo in 2016: https://github.com/w3c/push-api/issues/208

If you want to offload your application, you can use a push service that does the job on your behalf: then you make one API call to the push service and it makes the thousands of calls to the browser push service.

For throttling currently I haven't seen any problem, even with several millions of notifications per hour.

Upvotes: 3

Related Questions