githubEdit

The Subscription

The subscription is created on client side when the end-user allows your application to send push messages.

A subscription is a unique identifier that represents the user's device and browser. It contains:

  • An endpoint URL provided by the push service

  • Encryption keys for securing the message payload

  • Supported content encodings for payload encryption

Creating a Subscription

On client side (Javascript), you can simply send to your server the object you receive using JSON.stringify.

circle-info

Javascript examples to get a Subscription from the web browser are not provided here. Please refer to other resources such as blog posts or library documentation.

A subscription object will look like:

{
 "endpoint":"https://updates.push.services.mozilla.com/wpush/v2/AAAAAAAA[…]AAAAAAAAA",
 "keys":{
 "auth":"XXXXXXXXXXXXXX",
 "p256dh":"YYYYYYYY[…]YYYYYYYYYYYYY"
 }
}

Understanding the Subscription Components

  • endpoint: The unique URL where your server sends notifications. Each subscription has a different endpoint.

  • keys.auth: Authentication secret for message encryption

  • keys.p256dh: Public key for Elliptic Curve Diffie-Hellman key agreement

Server-Side Processing

On server side, you can get a WebPush\Subscription object from the JSON string using the dedicated method WebPush\Subscription::createFromString.

Supported Content Encodings

By default, the content encoding aesgcm will be used. This encoding indicates how the payload of the notification should be formatted. The PushManager object from the Push API may list all acceptable encodings. In this case, it could be interesting to set these encodings to the Subscription object.

The two standard encodings are:

  • aes128gcm (recommended): Newer, more efficient encoding defined in RFC 8291

  • aesgcm (legacy): Older encoding for backwards compatibility

This will result in something like the following:

circle-exclamation

Subscription Lifecycle

1. Creation

A subscription is created when the user grants notification permission and your service worker subscribes to push notifications.

2. Storage

Your application server must store the subscription to send notifications later. Store:

  • The complete subscription object

  • Associated user information

  • Creation timestamp (useful for cleanup)

3. Usage

Use the stored subscription to send notifications at any time, even when the user is not on your website.

4. Expiration

Subscriptions can expire for several reasons:

  • User revokes notification permission

  • User clears browser data

  • Push service expires old subscriptions

  • Subscription endpoint becomes invalid

5. Cleanup

Always handle expired subscriptions:

  • Remove them from your database when you receive a 404 or 410 error

  • Implement a strategy to detect and clean abandoned subscriptions

Best Practices

Store Essential Information

Handle Multiple Subscriptions per User

A single user may have multiple subscriptions (different devices/browsers). Store all of them:

Implement Subscription Refresh

If a subscription expires, prompt the user to resubscribe:

Security Considerations

  1. Validate Endpoint URLs: Ensure endpoints are from known push services

  2. Store Securely: Treat subscriptions as sensitive data

  3. Rate Limiting: Implement rate limits to prevent abuse

  4. User Association: Always associate subscriptions with authenticated users

Subscription Uniqueness

Each subscription is unique to:

  • A specific browser

  • A specific device

  • A specific user profile (if the browser has multiple profiles)

  • A specific origin (your website domain)

This means:

  • The same user on Chrome desktop and Firefox desktop will have 2 different subscriptions

  • The same user on desktop and mobile will have 2 different subscriptions

  • If a user clears their browser data, they will get a new subscription

Testing Subscriptions

Always test your subscription handling:

Performance Optimization

Caching Subscriptions

When sending notifications to multiple users or sending frequently, implement caching strategies to improve performance:

Application-Level Caching

Use your application's cache layer (Redis, Memcached, etc.) to cache subscription lookups:

Doctrine Query Result Cache

If using Doctrine, leverage query result caching:

Batch Loading

When sending to multiple users, load subscriptions in batches to reduce database queries:

Cache Invalidation Strategy

Always invalidate the cache when subscriptions change:

Best Practices for High-Volume Sending

When sending to thousands of users:

  1. Use Background Jobs: Queue notifications for asynchronous processing

  2. Batch Subscriptions: Load subscriptions in batches of 100-1000

  3. Cache Aggressively: Cache subscription lookups for 1-4 hours

  4. Monitor Cache Hit Rate: Aim for >80% hit rate

  5. Clean Up Expired: Remove expired subscriptions immediately to reduce database size

circle-info

Note: The web-push library itself does not provide caching functionality, as this is the responsibility of your application layer. The examples above show recommended patterns for implementing caching in your application.

Subscription Lifecycle and Expiration Management

Understanding Subscription Expiration

Web Push subscriptions do not have explicit expiration dates. The subscription JSON from the browser contains no temporal information:

The only way to know a subscription has expired is to attempt sending and receive a 404 or 410 error.

Why Subscriptions Expire

  1. User Revocation - User denies notification permission

  2. Browser Data Clearing - User clears browser data

  3. App/Browser Uninstall - Complete removal

  4. Push Service Policy - Services may expire inactive subscriptions (timeframes vary by provider)

  5. VAPID Key Changes - Changing your VAPID keys invalidates old subscriptions

Tracking Subscription Health

Since subscriptions don't have built-in expiration dates, track metadata at the application level:

Identifying Likely Expired Subscriptions

Use heuristics to identify subscriptions that are probably expired:

Automated Cleanup Strategies

Strategy 1: Clean After Failed Sends

Update subscription status after each send attempt:

Strategy 2: Scheduled Cleanup Job

Run periodic cleanup to remove stale subscriptions:

Strategy 3: Proactive Health Check

Test subscriptions before important campaigns:

Push Service Expiration Policies

Different push services have different expiration policies:

Push Service
Typical Expiration Policy

FCM (Google)

60-90 days of inactivity

Mozilla Push

No automatic expiration, but may clean very old inactive subscriptions

Apple Push

~30 days of inactivity

Windows Push

Variable, typically 30-90 days

circle-exclamation

Best Practices

  1. Track Metadata: Always store createdAt, lastSuccessfulSendAt, and consecutiveFailures

  2. Update After Every Send: Mark success or failure after each notification attempt

  3. Remove Immediately on 404/410: Don't retry expired subscriptions

  4. Use Heuristics: Remove subscriptions with 3+ consecutive failures

  5. Periodic Cleanup: Run a scheduled job weekly to remove stale subscriptions

  6. Monitor Health: Track subscription health scores for analytics

  7. Re-subscription Flow: Make it easy for users to re-subscribe if needed

Example: Complete Subscription Management

circle-check

Common Issues

Subscription Not Received

  • Check that the user granted permission

  • Verify HTTPS is enabled

  • Ensure service worker is properly registered

Subscription Immediately Expires

  • Check VAPID keys match between client and server

  • Verify the push service endpoint is accessible

  • Ensure proper payload encryption

Multiple Subscriptions for Same User

This is normal and expected. Users can have multiple devices and browsers.

Next Steps

  • Learn how to create Notifications to send to your subscriptions

  • Understand Status Reports to handle delivery results

  • Set up VAPID authentication for secure sending

Last updated

Was this helpful?