Real-time analytics & workflow platform / April 2020 — present
LetLetMe FPL Platform
A maintained full-stack Fantasy Premier League platform that turns fast-moving external data into live analytics, tournament workflows, notifications, and companion experiences.
Live product screenTournament workflow backed by synchronized product state.
Reach800+ users
SurfacesWeb, WeChat and bot delivery
RuntimeLive data, scheduled jobs and recovery workflows
01 / Overview
Owning the product loop.
Builder and maintainer across product, backend services, data workflows and cloud delivery.
Product and architecture decisions across web, API, processing and delivery surfaces
Scheduled ingestion, normalization, scoring, cache/database synchronization and recovery paths
Deployment and operation across Vercel, Cloudflare, VPS services, Docker and GitHub Actions
02 / System context
Live data rarely fails cleanly.
Live sports data changes quickly, while product views, tournament state, notifications and derived scores need to agree. The system therefore needs explicit freshness rules and recovery paths instead of treating caching as a transparent performance layer.
Engineering focus
Keeping live scores, tournament state and notifications consistent when upstream data changes.
03 / Architecture
From provider payloads to product state.
External live data is ingested and normalized before synchronized writes update relational storage and Redis. APIs and workflow services expose that state to product clients and notification channels.
01External sources
Live fixtures, players, events and scoring inputs
02Scheduled ingestion
Fetch, validate, normalize and score
03Source of truth
PostgreSQL/MySQL domain records
04Live cache
Redis-backed freshness-sensitive reads
05Product APIs
REST, GraphQL and workflow services
06Client surfaces
Web, WeChat and Telegram delivery
04 / Key decisions
Three choices that shaped reliability.
01
Separate ingestion from user-facing reads
Problem
External sources can be slow or temporarily inconsistent.
Decision
Run ingestion and normalization as scheduled background workflows, then serve product reads from controlled storage and cache layers.
Trade-off
Product reads use controlled freshness windows instead of fetching providers on demand, so scheduled workflows need deliberate monitoring and recovery.
Result
User-facing routes do not depend directly on external-provider response time.
02
Make cache repair an operating workflow
Problem
Redis and relational records can drift after partial failures or delayed jobs.
Decision
Add verification, rebuild and rerun paths rather than assuming every synchronization step succeeds.
Trade-off
Repair paths add operational code and explicit checks, but avoid using a full cache reset as the default response to partial failure.
Result
The system can recover deliberately without treating cache resets as the default response.
03
Keep product surfaces behind shared rules
Problem
Web, bot and companion experiences consume overlapping domain state.
Decision
Centralize scoring and workflow rules in backend services and expose them through APIs.
Trade-off
Shared APIs require stable contracts and careful changes, but keep each client from recreating domain rules.
Result
Clients can evolve independently without duplicating core calculations.
05 / Operating concerns
Freshness, recovery and shared rules.
01 / Freshness
Make staleness visible and intentional
Scheduled refresh windows and controlled read layers keep product behaviour understandable when upstream data changes quickly.
02 / Recovery
Treat repair as part of the product runtime
Verification, rebuild and rerun paths give partial failures a deliberate recovery route instead of relying on manual cache clearing.
03 / Consistency
Keep shared rules behind the API boundary
Web, companion and bot experiences consume the same scoring and workflow behaviour from backend services.
06 / Evidence & outcomes
A maintained product in use.
Used by 800+ users across its product surfaces.
Maintained and operated continuously as a personal product since April 2020.
Shared scoring and tournament rules serve web, WeChat and bot experiences.
Live product screenFreshness-sensitive analytics served through explicit cache behaviour.Live product screenA companion workflow using the same backend rules and live state.
07 / Reflection
Reliability became a product concern.
Operating LetLetMe over time reinforced that reliability is a product behaviour, not a single infrastructure component.
Learned
Cached data needs an explicit lifecycle: when it becomes fresh, how it can drift, and how the system restores agreement after interruption.
Next
Continue tightening observability and recovery workflows as the product and its live-data surfaces evolve.