Subscription Schema

Planned — not yet live. Subscription management is not yet implemented. The schema below reflects the intended Firestore structure based on the product doc.

Subscription and ride pack records are stored as a sub-collection on the user document. They are not a top-level Firestore collection.

Firestore Document (users/{userId}/subscriptions/{subscriptionId})

Field Type Required Constraints Description
id string yes non-empty Subscription ID (matches document ID); sourced from RevenueCat
type "subscription" \| "ridePack" yes enum Whether this is a recurring subscription or a one-time ride pack
status "active" \| "expired" \| "cancelled" yes enum Current entitlement status
ridePack.totalRides number no integer > 0; only when type = "ridePack" Total rides included in the pack (5 or 10)
ridePack.ridesUsed number no integer ≥ 0; only when type = "ridePack" Rides consumed so far
purchasedAt Timestamp yes When the subscription or ride pack was purchased
expiresAt Timestamp yes Expiry time; 1 year from purchasedAt for ride packs; end of billing period for subscriptions

Only one subscription document can have status: active at a time. Multiple ridePack documents may be active simultaneously. Ride pack rides are consumed before subscription entitlement.

// Recurring subscription
{
  "id": "sub_rc_abc123",
  "type": "subscription",
  "status": "active",
  "ridePack": null,
  "purchasedAt": "2025-01-01T00:00:00.000Z",
  "expiresAt": "2026-01-01T00:00:00.000Z",
}

// Ride pack
{
  "id": "sub_rc_xyz789",
  "type": "ridePack",
  "status": "active",
  "ridePack": {
    "totalRides": 10,
    "ridesUsed": 3,
  },
  "purchasedAt": "2025-06-01T00:00:00.000Z",
  "expiresAt": "2026-06-01T00:00:00.000Z", // 1 year from purchase
}

Indexes

Fields Query Type Reason
status asc + expiresAt asc Composite Find active subscriptions nearing expiry
type asc + status asc Composite Check for an existing active subscription before purchase