Membership & Quota System

Complete guide to membership plans, features, quota tracking, and usage logs

5 Tables Quota Tracking Usage Logging

πŸ“‹ Overview

The Membership & Quota System manages subscription plans with feature-based quota tracking and usage logging. This enables tiered access control based on membership levels.

  • Membership Plans - Define subscription tiers with pricing and duration
  • Feature Limits - Configure what each plan includes (API calls, posts, storage)
  • Quota Tracking - Real-time monitoring of current period usage
  • Usage Logging - Complete audit trail of all usage transactions

πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         MEMBERSHIP & QUOTA SYSTEM                             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                             β”‚
β”‚  β”‚ memberships │────▢│membership_features  β”‚                             β”‚
β”‚  β”‚              β”‚     β”‚(Plan Definitions)    β”‚                             β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                             β”‚
β”‚         β”‚                                                                   β”‚
β”‚         β–Ό                                                                    β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                                       β”‚
β”‚  β”‚user_memberships  │◀─── app_users.user_id                                β”‚
β”‚  β”‚(Active Subs)     β”‚                                                        β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                                       β”‚
β”‚         β”‚                                                                   β”‚
β”‚         β–Ό                                                                    β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                              β”‚
β”‚  β”‚user_membership_quotas     β”‚  ← Updated frequently                        β”‚
β”‚  β”‚(Current Period Usage)    β”‚    (after each action)                       β”‚
β”‚  β”‚                          β”‚                                              β”‚
β”‚  β”‚ - feature_key            β”‚                                              β”‚
β”‚  β”‚ - limit_value            β”‚  NULL = unlimited                            β”‚
β”‚  β”‚ - used_value             β”‚  Current usage count                          β”‚
β”‚  β”‚ - remaining_value        β”‚  Auto-calculated                              β”‚
β”‚  β”‚ - period_start/end       β”‚  For periodic resets                           β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                              β”‚
β”‚           β”‚                                                                 β”‚
β”‚           β–Ό                                                                  β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                                       β”‚
β”‚  β”‚user_usage_logs   β”‚  ← Append-only audit trail                           β”‚
β”‚  β”‚(Transaction Hist)β”‚    (Every usage event)                                β”‚
β”‚  β”‚                  β”‚                                                       β”‚
β”‚  β”‚ - action_type    β”‚  api_call, post_create, etc.                         β”‚
β”‚  β”‚ - quantity       β”‚  Number of units consumed                            β”‚
β”‚  β”‚ - resource_id    β”‚  Reference to created item                           β”‚
β”‚  β”‚ - metadata       β”‚  Context information                                 β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                                       β”‚
β”‚                                                                              β”‚
β”‚  QUOTA CHECK FLOW:                                                           β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”‚
β”‚  β”‚ 1. User initiates action (e.g., Create Post)                        β”‚     β”‚
β”‚  β”‚ 2. Get user's active membership                                      β”‚     β”‚
β”‚  β”‚ 3. Get quota for feature_key='posts'                                 β”‚     β”‚
β”‚  β”‚ 4. Check: remaining_value > 0 OR remaining_value IS NULL            β”‚     β”‚
β”‚  β”‚ 5. If OK:                                                            β”‚     β”‚
β”‚  β”‚    - Log to user_usage_logs                                          β”‚     β”‚
β”‚  β”‚    - Update user_membership_quotas (used_value++, remaining--)       β”‚     β”‚
β”‚  β”‚    - Process request                                                β”‚     β”‚
β”‚  β”‚ 6. If exceeded: Return error with upgrade suggestion                β”‚     β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚
β”‚                                                                              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“Š Table Reference

memberships

Defines available membership plans with pricing and duration.

membership_features

Defines what features each membership plan includes and their limits.

user_memberships

User's active and historical subscriptions.

user_membership_quotas

Current period quota tracking. Updated after each usage.

user_usage_logs

Append-only transaction history. Complete audit trail of all usage.

πŸ’Ž Default Membership Plans

Free

β‚Ή0 β€’ Lifetime

  • β€’ 100 API calls/month
  • β€’ 10 posts/month
  • β€’ 100MB storage

Basic

β‚Ή199/month β€’ 30 days

  • β€’ 1,000 API calls/month
  • β€’ 50 posts/month
  • β€’ 500MB storage

Pro

β‚Ή499/month β€’ 30 days

  • β€’ 10,000 API calls/month
  • β€’ 500 posts/month
  • β€’ 2GB storage

Premium

β‚Ή999/month β€’ 30 days

  • β€’ 50,000 API calls/month
  • β€’ 2,000 posts/month
  • β€’ 10GB storage

Enterprise

β‚Ή9,999/year β€’ 365 days

  • β€’ Unlimited API calls
  • β€’ Unlimited posts
  • β€’ Unlimited storage

πŸ’» Usage Examples

// Check quota before allowing action
$quota = UserMembershipQuota::where('user_id', $userId)
    ->where('feature_key', 'posts')
    ->where('period_start', '<=', now())
    ->where('period_end', '>', now())
    ->first();

if ($quota && ($quota->remaining_value > 0 || $quota->remaining_value === null)) {
    // Allow action
} else {
    // Quota exceeded
    return response()->json([
        'error' => 'Quota exceeded',
        'message' => 'You have reached your monthly post limit.',
        'upgrade_suggestion' => 'Upgrade to Pro plan for 500 posts/month',
    ], 429);
}

// Log usage and update quota
DB::transaction(function() use ($userId, $featureKey) {
    // Log the usage
    UserUsageLog::create([
        'user_id' => $userId,
        'feature_key' => $featureKey,
        'action_type' => 'post_create',
        'quantity' => 1,
        'resource_id' => $postId,
        'metadata' => ['title' => $post->title],
    ]);

    // Update quota
    $quota = UserMembershipQuota::where('user_id', $userId)
        ->where('feature_key', $featureKey)
        ->first();

    $quota->increment('used_value');
    if ($quota->limit_value !== null) {
        $quota->update(['remaining_value' => $quota->limit_value - $quota->used_value]);
    }
});

// Get user's current membership with features
$membership = UserMembership::where('user_id', $userId)
    ->where('status', 'active')
    ->where(function($q) {
        $q->whereNull('end_date')
          ->orWhere('end_date', '>', now());
    })
    ->with('membership.features')
    ->first();