Skip to main content

Statistics & Limits Audit

Overview

This document tracks all statistics fields, their sources, and implementation status.

Organization Limits (OrganizationLimitsResponse)

✅ Fully Implemented

FieldSourceStatusNotes
tierOrganization.tier✅ SetFrom organization record
max_projectsOrganization.max_projects✅ SetSet by tier in organizations.py:get_tier_limits()
max_usersOrganization.max_users✅ SetSet by tier
max_devicesOrganization.max_devices✅ SetSet by tier
max_storage_gbOrganization.max_storage_gb✅ SetSet by tier
max_mqtt_inbound_messagesOrganization.max_mqtt_inbound_messages✅ SetSet by tier
max_mqtt_outbound_messagesOrganization.max_mqtt_outbound_messages✅ SetSet by tier
max_ecr_imagesOrganization.max_ecr_images✅ SetSet by tier

✅ Calculated Correctly

FieldCalculationStatusLocation
current_projectsCOUNT(projects) WHERE org_idorganizations.py:372-376
current_usersCOUNT(organization_members)organizations.py:378-380
current_devicesCOUNT(fleet_devices) JOIN projectsorganizations.py:385-390
current_storage_gbSUM(project_stats.current_month_storage_bytes) / 1GBorganizations.py:420-421
current_mqtt_inbound_messagesSUM(project_stats.current_month_mqtt_inbound_messages)organizations.py:422
current_mqtt_outbound_messagesSUM(project_stats.current_month_mqtt_outbound_messages)organizations.py:423
current_ecr_imagesSUM(project_stats.current_ecr_images)organizations.py:424

✅ Enforcement

ResourceEnforcement PointStatusLocation
ProjectsProject creationprojects.py:198-199 via LimitService
UsersInvitation creationorganizations.py:495-499 via LimitService
DevicesDevice registrationfleet.py:97-98 via LimitService
StorageNot yet enforced⚠️Should check before file uploads
MQTT InboundNot yet enforced⚠️Should check in Lambda/IoT Rule
MQTT OutboundNot yet enforced⚠️Should check before publishing
ECR ImagesImage push checkprojects.py:733-734 via LimitService

Project Statistics (ProjectStatsResponse)

Database Fields (project_stats table)

FieldTypeUpdated ByStatusNotes
current_month_logsint❌ Manual⚠️Needs automation via StatsUpdaterService
current_month_sessionsint❌ Manual⚠️Needs automation via StatsUpdaterService
current_month_mqtt_messagesint❌ Manual⚠️Legacy field, kept for compatibility
current_month_mqtt_inbound_messagesint✅ LimitService.increment_mqtt_inbound()Called by Lambda/API
current_month_mqtt_outbound_messagesint✅ LimitService.increment_mqtt_outbound()Called by Lambda/API
current_month_api_callsint❌ Manual⚠️Should use middleware to track
current_month_deploymentsint❌ Manual⚠️Track in deployment API
current_month_storage_bytesint❌ Manual⚠️Needs StatsUpdaterService
total_docker_storage_bytesint❌ Manual⚠️Query ECR API
total_s3_storage_bytesint❌ Manual⚠️Query S3/CloudWatch
total_logs_storage_bytesint❌ Manual⚠️Estimate from log count
current_ecr_imagesint✅ StatsUpdaterServiceQueries ECR API
current_month_docker_upload_bytesint❌ Manual⚠️Track in ECR push
current_month_docker_download_bytesint❌ Manual⚠️Track in device pulls
current_month_data_transfer_bytesint❌ Manual⚠️CloudWatch metrics
total_devicesint✅ StatsUpdaterServiceCOUNT(fleet_devices)
active_devicesint✅ StatsUpdaterServiceCOUNT WHERE status=ONLINE/ACTIVE
total_sessionsint✅ StatsUpdaterServiceCOUNT(sessions)
total_logsint✅ StatsUpdaterServiceCOUNT(error_logs)
lifetime_logsint✅ reset_monthly_stats()Accumulated monthly
lifetime_sessionsint✅ reset_monthly_stats()Accumulated monthly
lifetime_mqtt_messagesint✅ increment methodsAccumulated on each message
lifetime_api_callsint❌ Manual⚠️Needs middleware tracking
last_calculated_atdatetime✅ StatsUpdaterServiceUpdated on stats refresh
month_start_datedatetime✅ reset_monthly_stats()Reset monthly

AWS Integration Status

✅ Implemented

AWS ServiceMetricIntegrationStatus
ECRImage countStatsUpdaterService._update_ecr_metrics()
RDSDatabase connectionsqlalchemy
S3Bucket existsstorageBucket in CDK

⚠️ Needs Implementation

AWS ServiceMetricWhere to ImplementPriority
IoT Core CloudWatchPublishIn.Success (inbound)Lambda function or scheduled job🔴 HIGH
IoT Core CloudWatchPublishOut.Success (outbound)Lambda function or scheduled job🔴 HIGH
S3 CloudWatchBucketSize (storage)StatsUpdaterService🟡 MEDIUM
ECRImageSize (storage)StatsUpdaterService🟡 MEDIUM
CloudWatch LogsLog storageStatsUpdaterService🟢 LOW

1. MQTT Message Counter Lambda

Trigger: AWS IoT Rule on all MQTT topics Purpose: Increment mqtt_inbound counters in real-time Code Location: backend/lambdas/mqtt-counter/
# Pseudo-code
def handler(event, context):
    topic = event['topic']
    device_id = extract_device_id(topic)

    # Get project from device
    project = get_project_by_device(device_id)

    # Increment counter
    if topic.startswith('$aws/things/{device}/shadow'):
        increment_mqtt_inbound(project.id)

2. Hourly Stats Updater Lambda

Trigger: EventBridge (every hour) Purpose: Update all project stats from AWS services Code Location: backend/lambdas/stats-updater/
def handler(event, context):
    for project in get_all_projects():
        stats_updater = StatsUpdaterService(db)
        stats_updater.update_project_stats(project)

3. Monthly Stats Reset Lambda

Trigger: EventBridge (1st of month at 00:00 UTC) Purpose: Reset monthly counters and archive to lifetime Code Location: backend/lambdas/monthly-reset/
def handler(event, context):
    for project in get_all_projects():
        stats_updater = StatsUpdaterService(db)
        stats_updater.reset_monthly_stats(project)

Action Items

🔴 Critical (Needed for MVP)

  1. Implement MQTT message tracking Lambda
    • Create IoT Rule to capture all device messages
    • Lambda function to increment inbound/outbound counters
    • Deploy to CDK stack
  2. Add MQTT limit enforcement
    • Check limits before allowing device to publish (IoT Policy?)
    • Check limits before backend publishes to device
    • Return 402 error when limit exceeded
  3. Fix storage tracking
    • Query S3 bucket size via CloudWatch
    • Query ECR image sizes
    • Update storage fields in stats

🟡 Important (Post-MVP)

  1. Add API call tracking middleware
    • FastAPI middleware to count requests
    • Increment current_month_api_calls
    • Enforce API rate limits
  2. Add deployment tracking
    • Increment counter when capsule is deployed
    • Track in sessions API
  3. Create scheduled Lambda for stats updates
    • Deploy hourly stats updater
    • Deploy monthly reset function

🟢 Nice to Have

  1. Add CloudWatch dashboards
    • Visualize MQTT message rates
    • Show storage trends
    • Alert on approaching limits
  2. Historical data warehouse
    • Archive monthly stats to S3/Redshift
    • Enable trend analysis
    • Billing report generation

Testing Checklist

  • Create free tier organization
  • Verify all limits are set correctly
  • Create project and verify device limit enforcement
  • Register device up to limit
  • Try to register one more device (should fail with 402)
  • Send MQTT messages and verify counters increment
  • Check that limit enforcement works for MQTT
  • Push ECR images up to limit
  • Try to push one more (should fail)
  • Verify frontend displays all limits correctly
  • Check that stats endpoint returns all fields
  • Test monthly reset (mock date to next month)

CDK Stack Integration

Required Environment Variables

# Backend service needs these
ECR_REPOSITORY_URI=<from CDK output>
AWS_REGION=us-west-2
AWS_IOT_ENDPOINT=<account>.iot.us-west-2.amazonaws.com
S3_BUCKET=<from CDK>

Required IAM Permissions

Backend ECS Task Role:
  • ecr:ListImages - List images in repository
  • ecr:DescribeImages - Get image details (size)
  • cloudwatch:GetMetricStatistics - Query MQTT metrics
  • s3:GetBucketSize - Query bucket size (via CloudWatch)
  • iot:ListThings - List devices (for filtering)
Lambda Execution Role (mqtt-counter):
  • dynamodb:GetItem / dynamodb:UpdateItem - Access project_stats
  • Or use RDS Proxy to access PostgreSQL

Summary

✅ Working

  • Organization limits are properly defined
  • Limit enforcement for projects, users, devices, ECR images
  • Basic stats collection (devices, sessions, logs)
  • Frontend displays limits correctly

⚠️ Needs Attention

  • MQTT message tracking is NOT implemented - counters exist but never increment
  • Storage tracking is incomplete - no S3/ECR size queries
  • Stats are created but never updated - need scheduled updates
  • Monthly reset is not automated - need Lambda trigger

🔴 Critical Missing Pieces

  1. IoT Rule + Lambda for MQTT tracking
  2. MQTT limit enforcement in publish operations
  3. Scheduled Lambda for stats updates
  4. S3/ECR storage size queries