Table overview
All persistent storage lives in DynamoDB. There are no relational databases. Each table is owned by a single repository, though multiple services may read from it via that repository.LA v2 replaced several tables:
activity-subscriptions is now live-activities, match-processing-state is now active-matches, and prematch-notifications and state-hashes have been removed entirely.Table details
cricket-fixtures
The central table. Stores every match the system knows about.
GSIs:
Accessed by: FixtureService (read/write), FixtureSyncJob (write), DisplayStateBuilder (read)
Access patterns:
The
live-index GSI has been removed. The active-matches table now serves as the source of truth for which matches are currently being polled, replacing the sparse GSI pattern.live-activities
Tracks Live Activity sessions. When a user starts a Live Activity on iOS, their update token and session metadata are stored here. Replaces the oldactivity-subscriptions table.
GSIs:
Key attributes:
updateToken (APNs Live Activity push token), status (active/ended/suspended), sessionStartedAt, endedAt, endReason, suspendedAt, ttl
TTL: Yes — sessions expire after the match ends.
Accessed by: LiveActivityRepository (read/write), LACoordinator (read), ApnsDeliveryService (read)
Access patterns:
The SK is
userId#deviceId (composite), enabling multi-device support. A user with iPhone + iPad has 2 separate session records for the same match. The userId-index GSI allows querying all of a user’s active sessions across matches.active-matches
Tracks all matches currently being polled, along with their processing state. Replaces both the oldmatch-processing-state table and the live-index GSI on fixtures. Each record is approximately 5KB and contains everything the event detection pipeline needs to detect changes.
Key attributes:
status, instanceId (which server instance owns this match), lastTickAt, matchPhase, previousBallId, previousScore, previousStatus, previousBatting, previousBowling, last30Balls, cooldowns, ttl
TTL: Yes — records expire after the match ends + buffer.
Accessed by: ActiveMatchRepository (read/write), MatchOrchestrator (write), ScorePoller (read/write), MatchEventBus (read)
Access patterns:
The
previousScore, previousBatting, previousBowling, and last30Balls fields store the state from the last poll tick. The event detection pipeline diffs current data against these previous values to determine what changed. The cooldowns map tracks per-event-type cooldown expiry timestamps.cricket-teams
Static team reference data synced from SportMonks.
Accessed by: TeamService (read/write), DisplayStateBuilder (read)
Access patterns:
cricket-team-seasons
Per-season stats for each team within a league season.
Accessed by: TeamSeasonService (read/write)
Access patterns:
cricket-leagues
League/competition reference data.
Accessed by: LeagueService (read/write), DisplayStateBuilder (read)
Access patterns:
cricket-devices
Maps users to their registered push notification device tokens. Now supports multi-device with additional device metadata.
Key attributes:
platform, apnsToken, pushToStartToken, osVersion, appVersion, ttl
TTL: Yes — stale device registrations expire automatically.
Accessed by: DeviceService (read/write), ApnsDeliveryService (read)
Access patterns:
Device registration enforces single-device-per-user: it queries all records for the user, deletes any with a different
deviceToken, then upserts the current one. The osVersion and appVersion fields are captured on registration for debugging push delivery issues.cricket-match-follows
Tracks which users are following which matches (for push notifications on score changes).
Accessed by: MatchFollowService (read/write), ApnsDeliveryService (read)
Access patterns:
cricket-locks
Distributed locking table. Prevents multiple backend instances from processing the same match concurrently.
Key attributes:
owner (instance ID), expiresAt (epoch timestamp for auto-release)
Accessed by: LockService (read/write)
Access patterns:
DisplayStateCache
Caches the fully-computed display state for a match. Avoids recomputing on every API request.
TTL: Yes — cache entries expire and are rebuilt on next request.
Accessed by: DisplayStateCacheService (read/write)
Access patterns:
The cache key is
DISPLAY#{matchId}#{teamId}, allowing per-team display state caching. Client-side TTL validation is performed in addition to DynamoDB TTL — if ttl has passed, the GetItem returns null even before DynamoDB deletes the record.cricket-fixture-cache
Caches raw fixture data from SportMonks to reduce API calls.
TTL: Yes — cached data expires based on match state (live matches have shorter TTLs).
Accessed by: FixtureCacheService (read/write), SportMonksClient (via provider)
GSIs:
Access patterns: