Understanding How to Store Web Push Endpoints : <p>I'm trying to get started implementing <a href="https://developer.mozilla.org/en-US/docs/Web/API/Push_API" rel="noreferrer">Web Push</a> in one of my apps. In the examples I have found, the client's endpoint URL is generally stored in memory with a comment saying something like:</p>

<blockquote>
  <p>In production you would store this in your database...</p>
</blockquote>

<p>Since only registered users of my app can/will get push notifications, my plan was to store the endpoint URL in the user's meta data in my database. So far, so good.</p>

<p>The problem comes when I want to allow the same user to receive notifications on multiple devices. In theory, I will just add a new endpoint to the database for each device the user subscribes with. However, in testing I have noticed that endpoints change with each subscription/unsubscription on the <em>same device</em>. So, if a user subscribes/unsubscribes several times in a row on the same device, I wind up with several endpoints saved for that user (all but one of which are bad).</p>

<p>From <a href="http://blog.pushpad.xyz/2016/05/the-push-api-and-its-wild-unsubscription-mechanism/" rel="noreferrer">what I have read</a>, there is no reliable way to be notified when a user unsubscribes or an endpoint is otherwise invalidated. So, how can I tell if I should remove an old endpoint before adding a new one?</p>

<p>What's to stop a user from effectively mounting a denial of service attack by filling my db with endpoints through repeated subscription/unsubscription?</p>

<p>That's more meant as a joke (I can obvioulsy limit the total endpoints for a given user), but the problem I see is that when it comes time to send a notification, I will blast notification services with hundreds of notifications for invalid endpoints.</p>

<hr>

<p>I want the subscribe logic on my server to be:</p>

<ol>
<li>Check if we already have an endpoint saved for this user/device combo</li>
<li>If not add it, if yes, update it</li>
</ol>

<p>The problem is that I can't figure out how to reliably do #1.</p>
