Skip to content

Database & Scaling Strategy โ€‹

Last Updated: 2026-01-11
Status: Active โ€” guiding pilot through Year 3 infrastructure decisions


Overview โ€‹

This document outlines Lantern's database selection rationale, scaling thresholds, migration triggers, and cost considerations. It also addresses how location-based features (Google Maps API, geofencing) impact infrastructure decisions.

TL;DR: Firestore handles our needs for 3-5 years. Focus on merchant adoption, not premature optimization.


Current Architecture โ€‹

Firestore (Primary Database) โ€‹

  • What we use it for:

    • User profiles (encrypted location, preferences, Wave history)
    • Merchant data (venue info, offers, analytics)
    • Offer redemptions & check-in logs
    • Encrypted notification queues
  • Why Firestore:

    • Rich querying: Compound indexes for "nearby offers user hasn't redeemed"
    • Offline-first: IndexedDB persistence for PWA (enabled in firebase.js)
    • Real-time: Document listeners for live offer updates
    • Security: Granular Firestore Security Rules
    • Scalability: Horizontal scaling built-in (no sharding needed)

Implementation Details โ€‹

  • Persistence: IndexedDB with memory fallback (see firebase.js)
  • Location Privacy: Ephemeral location checks only (never store raw coordinates)
  • Encryption: Client-side encryption before Firestore writes (see encryption.js)

Scale Limits & Thresholds โ€‹

Firestore Capacity (What You Actually Get) โ€‹

Free Tier (Spark Plan) โ€‹

  • 50K document reads/day
  • 20K document writes/day
  • 20K document deletes/day
  • 1 GiB storage
  • Use case: Pilot phase (5-10 merchants, <1K users)

Blaze Plan (Pay-as-you-go) โ€‹

  • Reads: $0.06 per 100K documents
  • Writes: $0.18 per 100K documents
  • Deletes: $0.02 per 100K documents
  • Storage: $0.18/GB/month
  • No hard limits โ€” scales to millions of ops/day

Real-World Benchmarks โ€‹

ScaleUsersOperations/DayMonthly CostNotes
Pilot<1K50K-100K$0 (free tier)5-10 merchants, light usage
Early Growth1K-10K500K-1M$50-150Typical SaaS startup
Scaling10K-100K5M-10M$200-800Regional platform
Enterprise100K-1M50M-100M$2K-5KMulti-region, heavy traffic
Breaking Point1M+100M+$5K-15K+Consider hybrid architecture

Lantern Year 1 projection: 40 merchants ร— ~500 users/merchant = 20K users
โ†’ ~1M operations/day = $50-100/month (0.02% of Firestore's comfort zone)


Firebase Realtime Database vs Firestore โ€‹

FeatureFirestore โœ… (Recommended)Realtime Database
QueryingRich (compound indexes, range queries, ordering)Limited (shallow queries only)
ScalabilityUnlimited horizontal scale~200K concurrent connections/instance
Data ModelDocument/collection (structured)JSON tree (denormalized)
Offline SupportExcellent (IndexedDB)Good (local cache)
PricingPer-operationPer-GB-downloaded
Real-timeDocument listenersFull tree sync
Best forComplex queries, structured dataSimple chat, live scoreboards

Decision Matrix for Lantern โ€‹

Firestore wins because we need:

  • Compound queries: "offers within 5km of user who hasn't redeemed yet"
  • Structured data: Users, merchants, offers, redemptions as separate collections
  • Offline-first: PWA requires IndexedDB persistence
  • Security rules: Fine-grained access control per document

Realtime DB would be better for:

  • Simple key-value stores
  • Global state sync (all users see same data)
  • <50ms latency for every update (e.g., multiplayer games, typing indicators)

Verdict: Stick with Firestore. Our use case is location-based discovery, not real-time chat.


Google Maps API Impact โ€‹

API Integration Points โ€‹

1. Places API (Venue Search & Discovery) โ€‹

  • Use case: Merchant onboarding (verify business exists, get coordinates)
  • Cost: $32 per 1K requests (Place Details)
  • Pilot usage: ~100-200 requests/month (manual merchant onboarding)
  • Year 1 cost: <$10/month

2. Geolocation API (Browser-based) โ€‹

  • Use case: Get user's current location for "nearby offers"
  • Cost: Free (browser API, no Google quota)
  • Implementation: navigator.geolocation.getCurrentPosition()

3. Maps JavaScript API (Optional: Display map UI) โ€‹

  • Use case: Show merchant locations on map view
  • Cost: $7 per 1K map loads (Dynamic Maps)
  • Pilot cost: <$10/month (most users just see list view)
  • Optimization: Lazy load map only when user taps "Map View"

4. Geocoding API (Optional) โ€‹

  • Use case: Convert addresses to coordinates
  • Cost: $5 per 1K requests
  • When needed: Merchant address input (if not using Places API)

Cost Projections with Google Maps โ€‹

ScaleUsersMaps Loads/MonthPlaces LookupsMonthly Cost% of Total Infra
Pilot100500-1K100-200$5-10<10%
Early Growth1K5K-10K500-1K$50-100~30%
Scaling10K50K-100K5K-10K$500-1K~30%
Enterprise100K500K-1M50K-100K$5K-10K~20%

Key Insight: Google Maps costs scale linearly with user activity but remain <30% of total infrastructure costs (Firebase + Cloudflare + Maps). Payment processing fees dwarf all API costs.

Optimization Strategies:

  1. Cache Place Details: Store merchant coordinates in Firestore (don't re-query)
  2. Lazy load maps: Only load JavaScript API when user taps "Map View"
  3. Static maps for previews: Use Static Maps API ($2/1K loads) for thumbnails
  4. Batch geocoding: Geocode all merchant addresses once during onboarding

Database Impact: Minimal โ€‹

  • Google Maps responses are cached in Firestore (merchant collection)
  • User location is ephemeral (never stored, only used for proximity checks)
  • No additional database load from Maps integration

Geofencing Implementation & Impact โ€‹

Geofencing Strategy โ€‹

1. Client-Side Haversine Distance โ€‹

  • How it works: Browser gets GPS โ†’ calculates distance to merchant โ†’ enables "Light Lantern" if <200m
  • Firestore query: Geohash-based filtering (see implementation below)
  • Database impact: Low โ€” 1 read per location check (~5-10K reads/day for 1K users)
  • Cost: <$5/month

2. Server-Side Verification (Fraud Prevention) โ€‹

  • How it works: Client submits redemption + encrypted location โ†’ Cloud Function validates โ†’ writes to Firestore
  • Database impact: Medium โ€” 1 write + 1 read per redemption (~500-1K ops/day)
  • Cost: Cloud Functions $0.40/million invocations + Firestore writes ($0.18/100K)
  • Total cost: <$10/month for pilot

3. QR Code Verification (High-Value Offers) โ€‹

  • How it works: Merchant shows QR code โ†’ user scans โ†’ server validates merchant signature
  • Database impact: Low โ€” 1 read to verify QR signature
  • Use case: BOGO offers, >$20 value redemptions
  • Cost: Negligible (<$1/month)

Geofencing Data Model โ€‹

Firestore Structure โ€‹

javascript
// merchants/{merchantId}
{
  name: "Coffee Shop",
  location: {
    lat: 32.7157,
    lng: -117.1611,
    geohash: "9mudgbe0c",  // For proximity queries
    radius: 200  // meters
  },
  offers: [...]
}

// offers/{offerId}
{
  merchantId: "abc123",
  geohash: "9mudgbe0c",  // Indexed for "nearby offers" query
  redemptionCount: 42,
  maxRedemptions: 100,
  perUserLimit: 1
}

// redemptions/{redemptionId}
{
  userId: "xyz789",
  offerId: "offer456",
  timestamp: "2026-01-11T10:30:00Z",
  verifiedLocation: true,  // Server-side validation flag
  verificationMethod: "geofence" | "qr-code"
}

Geohash Indexing for Proximity Queries โ€‹

Implementation: Use geofire-common library

javascript
import { geohashForLocation, geohashQueryBounds } from 'geofire-common'

// 1. When merchant creates offer, store geohash
const geohash = geohashForLocation([lat, lng])
await setDoc(doc(db, 'offers', offerId), {
  ...offerData,
  geohash,
  location: { lat, lng, radius: 200 }
})

// 2. Query offers within 5km of user
const center = [userLat, userLng]
const radiusInM = 5000
const bounds = geohashQueryBounds(center, radiusInM)

const promises = bounds.map((b) => {
  const q = query(
    collection(db, 'offers'),
    orderBy('geohash'),
    startAt(b[0]),
    endAt(b[1])
  )
  return getDocs(q)
})

const snapshots = await Promise.all(promises)
// Filter results by actual distance (geohash is approximate)

Database Operations:

  • Writes: 1 geohash calculation per offer creation (negligible cost)
  • Reads: 2-4 Firestore queries per "nearby offers" check (~10-20 reads)
  • Index: Composite index on geohash (auto-created by Firestore)

Cost Impact:

  • 1K users checking location 5x/day = 50K reads/day = 1.5M reads/month
  • Cost: 1.5M reads ร— $0.06/100K = $0.90/month ๐ŸŽฏ

GCP Migration Path (When Needed) โ€‹

Firebase is GCP under the hood. Migration is gradual, not binary.

Migration Triggers (Not Before Year 3-5) โ€‹

TriggerSymptomSolutionTimeline
Query latency >500msComplex joins, heavy aggregationsAdd Cloud SQL (Postgres) for relational dataMonth 18-24
Analytics queries slow FirestoreMerchant dashboards timeoutStream to BigQuery for analyticsMonth 12-18
>1M ops/dayFirestore costs >$1K/monthAdd Redis cache for hot dataMonth 24-36
Multi-region complianceGDPR, data residency lawsCloud Spanner or regional FirestoreYear 3+
Sub-10ms query latencyReal-time Wave interactionsMemorystore (Redis) + CDN edge cachingYear 2-3

Hybrid Architecture (Long-Term Vision) โ€‹

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                      Client (PWA)                       โ”‚
โ”‚  - IndexedDB offline cache                              โ”‚
โ”‚  - Encrypted local storage                              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                           โ”‚
                           โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                   Cloud Load Balancer                   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                           โ”‚
        โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
        โ–ผ                  โ–ผ                  โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚   Firestore  โ”‚  โ”‚  Cloud Functions โ”‚  โ”‚ Memorystore โ”‚
โ”‚ (user data,  โ”‚  โ”‚  (business logic,โ”‚  โ”‚   (Redis)   โ”‚
โ”‚  offers,     โ”‚  โ”‚   auth, webhooks)โ”‚  โ”‚ (hot cache) โ”‚
โ”‚  redemptions)โ”‚  โ”‚                  โ”‚  โ”‚             โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
        โ”‚                  โ”‚
        โ–ผ                  โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  BigQuery    โ”‚  โ”‚   Cloud SQL     โ”‚
โ”‚ (analytics,  โ”‚  โ”‚  (relational    โ”‚
โ”‚  reporting)  โ”‚  โ”‚   merchant data)โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Migration sequence:

  1. Year 1-2: Firestore only (current)
  2. Year 2-3: Firestore + BigQuery (analytics offload)
  3. Year 3-4: Firestore + BigQuery + Redis (hot cache)
  4. Year 4-5: Firestore + BigQuery + Redis + Cloud SQL (relational data)

Cost Comparison at 1M Active Users:

ArchitectureMonthly CostUse Case
Firestore alone$500-1,500Simple apps, <10M ops/day
Firestore + BigQuery$800-2,000Analytics-heavy
Firestore + Redis$1,200-2,500Low-latency reads
Full GCP stack (SQL + Datastore + Redis + BigQuery)$2,500-5,000Enterprise multi-region

Cost Bottlenecks (In Order of Impact) โ€‹

Pilot โ†’ Year 3 Cost Breakdown โ€‹

Cost CategoryPilot (100 users)Year 1 (20K users)Year 3 (100K users)% of Total
Payment Processing (Stripe)$240/month$1,500/month$15,000/month85-90%
Google Maps API$5-10$50-100$500-1,0003-5%
Firestore$0 (free)$50-150$500-1,0003-5%
Cloud Functions$0 (free)$10-20$100-2001-2%
Cloudflare Hosting$0 (free)$0 (free)$0 (free)0%
Total Infrastructure~$245~$1,610~$16,600100%

Key Insight: Payment processing dominates costs (85-90%). Database optimization is <5% of total spend.

Priority order for cost optimization:

  1. ๐Ÿ”ฅ Negotiate Stripe rates (2.9% โ†’ 2.5% saves $1K/month at scale)
  2. ๐Ÿ“ Cache Google Maps data (saves $200-500/month)
  3. ๐Ÿ’พ Optimize Firestore queries (saves $50-100/month)
  4. โšก Add Redis cache (costs $100/month but improves UX)

Action Items โ€‹

Immediate (Pilot Phase) โ€‹

  • [x] Enable Firestore offline persistence โœ… (already enabled in firebase.js)
  • [ ] Implement geohash indexing for proximity queries
    • Use geofire-common library
    • Create composite index: offers collection โ†’ geohash field
    • Document in Firestore rules
  • [ ] Set Firebase budget alerts
    • Firebase Console โ†’ Usage & Billing โ†’ Budget Alerts
    • Alert threshold: $50/month (10x expected pilot cost)
  • [ ] Create Firestore composite indexes
    • offers collection: [geohash, redemptionCount]
    • redemptions collection: [userId, timestamp]
    • Run firebase deploy --only firestore:indexes
  • [ ] Document data model
    • Create docs/engineering/architecture/DATA_MODEL.md
    • Define collections, fields, security rules, indexes

Year 1 (Growth Phase) โ€‹

  • [ ] Upgrade to Blaze plan when free tier limits hit (~1K users)
  • [ ] Implement geofence server-side validation (Cloud Function)
    • Verify user location matches redemption location
    • Flag suspicious redemptions (>5km from venue)
    • Log fraud metrics to Firestore
  • [ ] Add Google Maps caching
    • Store Place Details in Firestore merchants collection
    • Cache for 90 days, refresh on merchant update
  • [ ] Monitor query performance
    • Enable Firestore performance monitoring
    • Set up Cloud Logging alerts for >500ms queries

Year 2-3 (Scaling Phase) โ€‹

  • [ ] Add BigQuery analytics pipeline
    • Stream Firestore writes to BigQuery
    • Build merchant analytics dashboards
    • Offload reporting queries from Firestore
  • [ ] Evaluate Redis cache if query latency >300ms
    • Cache hot merchant offers (updated hourly)
    • Cache user profiles (invalidate on update)
    • Use Memorystore (managed Redis on GCP)
  • [ ] Review migration triggers (quarterly)
    • Query latency P95
    • Monthly Firestore costs
    • User-reported performance issues


Changelog โ€‹

DateChangeRationale
2026-01-11Initial versionDocument scaling strategy & migration triggers

Next Review: 2026-07-01 (after pilot completion, 6 months)

Built with VitePress