Achievements and Badges System for Mobile App Gamification
An achievements system affects retention not because users like icons. It works through completion psychology: unfinished progress bar triggers desire to close it. Achievement that's visible but unreachable is frustrating. Visible and easily achievable — is engaging. This is an engineering task with psychological context.
Data Model
Three key entities:
Achievement — achievement template: id, title, description, icon_url, criteria (event type + threshold), xp_reward, badge_type (bronze/silver/gold/platinum). Criteria stored as JSON: {"event":"workout_completed","count":10} or {"event":"streak_days","count":7}.
UserAchievement — unlock fact: user_id, achievement_id, progress (current value), unlocked_at (null if not unlocked).
AchievementEvent — event log for progress recalculation: user_id, event_type, value, occurred_at. This is important — progress recalculation must be idempotent and recoverable from log.
Unlock Logic and Checking
Two approaches: event-driven (check all relevant achievements on each event) and batch (periodic recalculation of all users). For most apps — event-driven on backend.
Client sends event (e.g. workout_completed) → backend increments counter in UserAchievement.progress → if progress >= criteria.count and unlocked_at IS NULL → set unlocked_at, record XP, send push via APNs/FCM.
Critical: operation must be atomic. Concurrent requests from one user on two devices must not double-unlock achievement. Postgres: UPDATE with WHERE unlocked_at IS NULL RETURNING * in transaction.
Display on Client
Three badge states: locked (with progress bar), unlocked (full color), newly unlocked (unlock animation).
Unlock animation is a moment you can't mess up. On iOS: UIViewPropertyAnimator + Lottie for complex animations. On Flutter: AnimationController + Lottie widget. Animation file (.json Lottie) for each badge type — bronze/silver/gold separate. Don't do this with GIF — worse quality, less control.
Toast or full-screen moment? Depends on achievement weight. Regular achievement — bottom sheet or overlay for 2–3 seconds. Rare (gold/platinum) — full-screen celebration with confetti (Confetti package on Flutter, custom CAEmitterLayer on iOS).
Progress and Showcase
"My Achievements" screen: grouped by category, locked achievements visible with progress bar (motivational), unlocked with date. Don't hide locked achievements — kills motivation loop.
Unlocked achievement counter in user profile, total XP from achievements (if you have level system). Badge sharing to social — UIActivityViewController with custom preview (UIActivityItemProvider).
Timeline Guidelines
Basic system with 20–30 achievements, event-driven backend and unlock animation — 2–3 days for client with ready backend, 1–2 weeks with backend. Extended with custom Lottie animations, categories, sharing and unlock analytics — 3–4 weeks. Pricing is calculated individually.







