I accomplish this with a mix of Firebase, JS, PHP, MySQL and a cronjob.
Some notifications are passive - someone adding someone as a friend for example. These kinds of notifications I just push to the user via Firebase and JS. When someone adds someone as a friend, an entry gets written to the friendee's notifications path and Firebase being a realtime system, if the friendee is logged in, they'll see it right away. Notifications can be dismissed (deleted) of course.
If you wanted to make sure the user sees these kinds of notifications, you could also push the entry to the db (below) and whatever happens first, happens first. If the cronjob triggers, the notification gets rolled up and sent. If someone dismisses the notification in the website, delete the entry from the db as it no longer needs to be sent via the cronjob.
Other notifications are done via email - a new article is posted to a page someone follows, for example. In this case, the entry gets written to a MySQL db. As multiple articles across multiple pages can be posted in 1 day, nothing happens until the cronjob fires. The cronjob simply loops through the table once a day, checking if any emails need to be sent; consolidates the emails - I call this a rollup - and merges the emails into 1. So if 3 articles are posted, the user will get 1 email, not 3.