[ PROMPT_NODE_23357 ]
Mobile Backend
[ SKILL_DOCUMENTATION ]
# Mobile Backend Patterns
> **This file covers backend/API patterns SPECIFIC to mobile clients.**
> Generic backend patterns are in `nodejs-best-practices` and `api-patterns`.
> **Mobile backend is NOT the same as web backend. Different constraints, different patterns.**
---
## ? MOBILE BACKEND MINDSET
```
Mobile clients are DIFFERENT from web clients:
├── Unreliable network (2G, subway, elevator)
├── Battery constraints (minimize wake-ups)
├── Limited storage (can't cache everything)
├── Interrupted sessions (calls, notifications)
├── Diverse devices (old phones to flagships)
└── Binary updates are slow (App Store review)
```
**Your backend must compensate for ALL of these.**
---
## ? AI MOBILE BACKEND ANTI-PATTERNS
### These are common AI mistakes when building mobile backends:
| ❌ AI Default | Why It's Wrong | ✅ Mobile-Correct |
|---------------|----------------|-------------------|
| Same API for web and mobile | Mobile needs compact responses | Separate mobile endpoints OR field selection |
| Full object responses | Wastes bandwidth, battery | Partial responses, pagination |
| No offline consideration | App crashes without network | Offline-first design, sync queues |
| WebSocket for everything | Battery drain | Push notifications + polling fallback |
| No app versioning | Can't force updates, breaking changes | Version headers, minimum version check |
| Generic error messages | Users can't fix issues | Mobile-specific error codes + recovery actions |
| Session-based auth | Mobile apps restart | Token-based with refresh |
| Ignore device info | Can't debug issues | Device ID, app version in headers |
---
## 1. Push Notifications
### Platform Architecture
```
┌─────────────────────────────────────────────────────────────────┐
│ YOUR BACKEND │
├─────────────────────────────────────────────────────────────────┤
│ │ │
│ ┌──────────┴──────────┐ │
│ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ FCM (Google) │ │ APNs (Apple) │ │
│ │ Firebase │ │ Direct or FCM │ │
│ └────────┬────────┘ └────────┬────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Android Device │ │ iOS Device │ │
│ └─────────────────┘ └─────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
```
### Push Types
| Type | Use Case | User Sees |
|------|----------|-----------|
| **Display** | New message, order update | Notification banner |
| **Silent** | Background sync, content update | Nothing (background) |
| **Data** | Custom handling by app | Depends on app logic |
### Anti-Patterns
| ❌ NEVER | ✅ ALWAYS |
|----------|----------|
| Send sensitive data in push | Push says "New message", app fetches content |
| Overload with pushes | Batch, dedupe, respect quiet hours |
| Same message to all | Segment by user preference, timezone |
| Ignore failed tokens | Clean up invalid tokens regularly |
| Skip APNs for iOS | FCM alone doesn't guarantee iOS delivery |
### Token Management
```
TOKEN LIFECYCLE:
├── App registers → Get token → Send to backend
├── Token can change → App must re-register on start
├── Token expires → Clean from database
├── User uninstalls → Token becomes invalid (detect via error)
└── Multiple devices → Store multiple tokens per user
```
---
## 2. Offline Sync & Conflict Resolution
### Sync Strategy Selection
```
WHAT TYPE OF DATA?
│
├── Read-only (news, catalog)
│ └── Simple cache + TTL
│ └── ETag/Last-Modified for invalidation
│
├── User-owned (notes, todos)
│ └── Last-write-wins (simple)
│ └── Or timestamp-based merge
│
├── Collaborative (shared docs)
│ └── CRDT or OT required
│ └── Consider Firebase/Supabase
│
└── Critical (payments, inventory)
└── Server is source of truth
└── Optimistic UI + server confirmation
```
### Conflict Resolution Strategies
| Strategy | How It Works | Best For |
|----------|--------------|----------|
| **Last-write-wins** | Latest timestamp overwrites | Simple data, single user |
| **Server-wins** | Server always authoritative | Critical transactions |
| **Client-wins** | Offline changes prioritized | Offline-heavy apps |
| **Merge** | Combine changes field-by-field | Documents, rich content |
| **CRDT** | Mathematically conflict-free | Real-time collaboration |
### Sync Queue Pattern
```
CLIENT SIDE:
├── User makes change → Write to local DB
├── Add to sync queue → { action, data, timestamp, retries }
├── Network available → Process queue FIFO
├── Success → Remove from queue
├── Failure → Retry with backoff (max 5 retries)
└── Conflict → Apply resolution strategy
SERVER SIDE:
├── Accept change with client timestamp
├── Compare with server version
├── Apply conflict resolution
├── Return merged state
└── Client updates local with server response
```
---
## 3. Mobile API Optimization
### Response Size Reduction
| Technique | Savings | Implementation |
|-----------|---------|----------------|
| **Field selection** | 30-70% | `?fields=id,name,thumbnail` |
| **Compression** | 60-80% | gzip/brotli (automatic) |
| **Pagination** | Varies | Cursor-based for mobile |
| **Image variants** | 50-90% | `/image?w=200&q=80` |
| **Delta sync** | 80-95% | Only changed records since timestamp |
### Pagination: Cursor vs Offset
```
OFFSET (Bad for mobile):
├── Page 1: OFFSET 0 LIMIT 20
├── Page 2: OFFSET 20 LIMIT 20
├── Problem: New item added → duplicates!
└── Problem: Large offset = slow query
CURSOR (Good for mobile):
├── First: ?limit=20
├── Next: ?limit=20&after=cursor_abc123
├── Cursor = encoded (id + sort values)
├── No duplicates on data changes
└── Consistent performance
```
### Batch Requests
```
Instead of:
GET /users/1
GET /users/2
GET /users/3
(3 round trips, 3x latency)
Use:
POST /batch
{ requests: [
{ method: "GET", path: "/users/1" },
{ method: "GET", path: "/users/2" },
{ method: "GET", path: "/users/3" }
]}
(1 round trip)
```
---
## 4. App Versioning
### Version Check Endpoint
```
GET /api/app-config
Headers:
X-App-Version: 2.1.0
X-Platform: ios
X-Device-ID: abc123
Response:
{
"minimum_version": "2.0.0",
"latest_version": "2.3.0",
"force_update": false,
"update_url": "https://apps.apple.com/...",
"feature_flags": {
"new_player": true,
"dark_mode": true
},
"maintenance": false,
"maintenance_message": null
}
```
### Version Comparison Logic
```
CLIENT VERSION vs MINIMUM VERSION:
├── client >= minimum → Continue normally
├── client < minimum → Show force update screen
│ └── Block app usage until updated
└── client 5% per version
├── P95 latency > 2 seconds
├── Specific version crash spike
├── Auth failure spike (attack?)
└── Push delivery failure spike
```
---
## ? MOBILE BACKEND CHECKLIST
### Before API Design
- [ ] Identified mobile-specific requirements?
- [ ] Planned offline behavior?
- [ ] Designed sync strategy?
- [ ] Considered bandwidth constraints?
### For Every Endpoint
- [ ] Response as small as possible?
- [ ] Pagination cursor-based?
- [ ] Proper caching headers?
- [ ] Mobile error format with actions?
### Authentication
- [ ] Token refresh implemented?
- [ ] Silent re-auth flow?
- [ ] Multi-device logout?
- [ ] Secure token storage guidance?
### Push Notifications
- [ ] FCM + APNs configured?
- [ ] Token lifecycle managed?
- [ ] Silent vs display push defined?
- [ ] Sensitive data NOT in push payload?
### Release
- [ ] Version check endpoint ready?
- [ ] Feature flags configured?
- [ ] Force update mechanism?
- [ ] Monitoring headers required?
---
> **Remember:** Mobile backend must be resilient to bad networks, respect battery life, and handle interrupted sessions gracefully. The client cannot be trusted, but it also cannot be hung up—provide offline capabilities and clear error recovery paths.
Source: claude-code-templates (MIT). See About Us for full credits.