The Problem
Mobile game marketers juggle push notification campaigns, personalized offers, re-engagement sequences, and seasonal events simultaneously. For CCFish, a fishing game with thousands of daily active players across multiple time zones, manually managing these campaigns is impossible at scale. Marketers either blast generic notifications to everyone (hurting retention) or skip engagement entirely (hurting revenue).
The Solution
CCFish uses a serverless engagement engine running on Cloudflare Workers that automates the entire campaign lifecycle. The system listens for player events (login streaks, level-ups, purchases, inactivity), evaluates eligibility rules in real-time, and delivers targeted notifications through the optimal channel -- push, in-game offer, or email -- all without human intervention.
Architecture Overview
The engagement pipeline has four layers:
- **Event Ingestion Layer:** Cloudflare Workers capture player events via a lightweight API endpoint at `/api/events`. Each event includes player ID, event type, timestamp, and context metadata (current level, last purchase date, session duration). Events are batched and written to D1 with a 5-second buffer to reduce write contention.
- **Rule Evaluation Engine:** A Workers-based rules engine evaluates each event against active campaign definitions stored in D1. Campaign rules are expressed as JSON conditions -- for example, "send offer if player hasn't purchased in 7 days AND level > 10." The engine runs in ~15ms per event, fast enough for real-time evaluation at the edge.
- **Channel Dispatch:** When a rule triggers, the dispatcher selects the best channel based on player preferences and campaign configuration. Push notifications go through Firebase Cloud Messaging, in-game offers are served via CCFish's offer API, and email digests use a separate Worker that queues batches hourly.
- **Analytics Feedback Loop:** Every engagement action is logged back to D1 with open/click/conversion data. Campaign managers see real-time dashboards showing which campaigns are driving revenue, and the system auto-pauses underperforming campaigns after 72 hours.
Step 1: Defining Campaign Rules in JSON
Campaigns are defined as JSON documents stored in D1. Here's a real campaign definition for re-engaging lapsed players:
```json
{
"campaign_id": "reengage-week-7",
"name": "7-Day Inactivity Offer",
"trigger": {"event": "session_end", "conditions": {"days_since_last_login": 7}},
"audience": {"min_level": 5, "exclude_recent_purchasers": true},
"action": {"type": "in_game_offer", "offer_id": "welcome_back_pack", "discount_pct": 50},
"cooldown_hours": 168,
"channels": ["push", "in_game"]
}
```
Step 2: Serverless Event Processing
The event ingestion Worker runs at the edge, colocated with CCFish's game servers. When a session ends, the Worker checks the player's last login date from D1. If 7+ days have passed and the player qualifies (level 5+, no recent purchase), the campaign engine fires. The entire check completes in under 50ms, invisible to the player.
```javascript
export default {
async fetch(request, env) {
const event = await request.json();
const player = await env.DB.prepare(
"SELECT last_login, level, total_purchases FROM players WHERE id = ?"
).bind(event.player_id).first();
const campaigns = await env.DB.prepare(
"SELECT * FROM campaigns WHERE status = 'active'"
).all();
for (const c of campaigns.results) {
if (matchCampaign(c, event, player)) {
await dispatchAction(c, event.player_id);
}
}
}
}
```
Step 3: Channel Dispatch with Fallback
The dispatcher tries channels in priority order based on player preference. If push notifications are disabled, it falls back to in-game offer. If the player hasn't opened the app in 14 days, it sends an email instead. This multi-channel approach achieved a 3.4x higher conversion rate compared to blast notifications during testing.
Coordinating across channels required careful deduplication. The system uses KV as a distributed lock to prevent double-sending -- each campaign+player combination gets a TTL key. If the key exists, the dispatch is skipped regardless of which Worker instance fires first. This pattern eliminated the 7% duplicate notification rate observed in early testing.
Step 4: Seasonal Event Automation
Beyond reactivation campaigns, the same engine powers seasonal events like the Lunar New Year tournament and Summer Fishing Festival. Event-specific campaign definitions are loaded into D1 72 hours before the event start date via a cron trigger. The engine auto-activates them at the scheduled time, sends teaser push notifications to qualified players, and deactivates them when the event window closes. This automation eliminated 8 hours of manual deployment time per event.
Cost Analysis
Running the entire engagement engine costs $3.84/month on Cloudflare Workers free tier (included in the 100K requests/day allocation). D1 storage for campaign definitions and event logs adds $0 at the 5M rows/month tier. Compared to a dedicated engagement platform like Braze or Mixpanel (starting at $1,500/month), CCFish saves over $17,000/year by using serverless components.
Results After 8 Weeks
- **340% increase** in reactivated lapsed players (7+ days inactive)
- **$0.02 per engagement** -- serverless Worker costs are near-zero
- **12 campaign variants** running simultaneously, each A/B testing different offers
- **89% reduction** in manual campaign setup time (campaigns are now configured via CMS, not code)
- **Zero downtime** across 8 weeks of production operation
Key Takeaways
- Serverless engagement automation is achievable without a dedicated infrastructure team. Cloudflare Workers handle the entire pipeline from event ingestion to multi-channel dispatch.
- Campaign rules stored as JSON in D1 enabled non-technical team members to create and modify campaigns through a simple admin interface.
- The feedback loop (logging every engagement outcome) turned campaign management from guesswork into data-driven optimization.
- Start with one campaign type (inactivity re-engagement), validate the pipeline, then expand to seasonal events, purchase incentives, and referral prompts.