How it works
Device registration is the foundation of the push notification system. Without a registered device token, the backend cannot send any notifications — neither standard alerts nor Live Activity updates.Initial registration
On first app launch (or after a fresh install), the app requests notification permissions from the user. If granted, iOS registers with Apple’s APNs and returns a device push token. The app sends this token toPOST /devices along with metadata (platform, app version). The backend stores it in the cricket-devices table with a composite key of (userId, deviceToken).
Device tokens can change. iOS may assign a new token after an OS update, app reinstall, or restore from backup. The app re-registers on every launch to keep tokens current.
Live Activity tokens
Live Activity push tokens are separate from the standard device token. Each Live Activity instance gets its own unique token from Apple. When the app starts a Live Activity (e.g., when following a live match), it observes thepushTokenUpdates async stream on the Activity object. Once the token arrives, it’s sent to the backend.
Push-to-start tokens are a special capability that allows the backend to start a Live Activity remotely, without the user having the app open. The app registers these via POST /devices/push-to-start-token.
Signout cleanup
When a user signs out, the app callsDELETE /devices/:token to unregister the device. This prevents ghost notifications to a device that is no longer associated with an active user session.
Failure modes
| Scenario | Behavior |
|---|---|
| User denies notification permissions | No token is generated; app works but without push |
| Token changes after OS update | App re-registers on next launch; old token eventually pruned |
| Multiple devices per user | Each device gets its own record; pushes are sent to all |
| App uninstalled | Token becomes invalid; APNs returns 410 on next push attempt |
Key tables
| Table | Key Schema | Purpose |
|---|---|---|
cricket-devices | PK: userId, SK: deviceToken | Maps users to their registered device tokens |
Key endpoints
| Method | Path | Purpose |
|---|---|---|
| POST | /devices | Register a device token |
| POST | /devices/push-to-start-token | Register a push-to-start token |
| DELETE | /devices/:token | Unregister a device token |
Areas of improvement
Push-to-start token endpoint returns 200 even when no device exists. The
POST /devices/push-to-start-token endpoint in devices.ts returns { updated: 0 } with a 200 status when getDeviceForUser finds no device. The iOS client receives a success response but the token was silently dropped. A 404 or 409 would make the failure visible to the client so it could retry after registering the base device first.No periodic token freshness check. Devices update their
lastSeenAt timestamp on each registerDevice call, but there is no background job that prunes devices that have not been seen in a long time (e.g., 90+ days). Over time, the cricket-devices table will accumulate records for users who uninstalled the app without signing out. Consider a TTL attribute or a periodic cleanup job.No retry on failed device registration from iOS. In
NotificationService.swift registerDevice(), if the POST /devices call fails (network error, 5xx), the error is logged but there is no retry. The next opportunity to register is the next app launch. If the user launches the app on poor connectivity, they could go an entire session without push notifications.