Polling vs Streaming Pattern

Version: 1.0.0
Category: API Patterns
Purpose: Guide for AI agents on choosing between polling and streaming for real-time data


Overview

This pattern helps AI agents decide when to use polling (repeated API requests) versus streaming (GRASS/NATS real-time updates) for accessing game state data. Each approach has trade-offs in terms of performance, accuracy, and resource usage.


Decision Framework

Use Polling When

Characteristics:

Examples:

Use Streaming When

Characteristics:

Examples:

Use Hybrid When

Characteristics:

Examples:


Comparison Matrix

Factor Polling Streaming
Latency High (poll interval) Low (real-time)
Accuracy Stale until next poll Real-time
API Calls Many (repeated requests) Few (one connection)
Rate Limits Consumes quota No rate limits
Complexity Simple Moderate
Resource Usage CPU/Network per poll Persistent connection
Error Handling Per-request Connection-level
Offline Support None Reconnection needed

Polling Patterns

Pattern 1: Fixed Interval Polling

Approach: Poll at regular intervals

Implementation:

{
  "pattern": "fixed-interval-polling",
  "interval": 5000,
  "unit": "milliseconds",
  "endpoint": "/api/planet/{planet_id}/shield/health"
}

Example:

{
  "polling": {
    "interval": 5000,
    "action": "Poll planet shield every 5 seconds",
    "code": "setInterval(() => pollPlanetShield(), 5000)"
  }
}

Use When:

Pattern 2: Adaptive Polling

Approach: Adjust poll interval based on activity

Implementation:

{
  "pattern": "adaptive-polling",
  "intervals": {
    "active": 1000,
    "inactive": 10000,
    "idle": 60000
  },
  "trigger": "activity-detected"
}

Example:

{
  "adaptivePolling": {
    "duringRaid": {
      "interval": 1000,
      "reason": "High activity, need frequent updates"
    },
    "normal": {
      "interval": 5000,
      "reason": "Normal activity"
    },
    "idle": {
      "interval": 30000,
      "reason": "Low activity, reduce polling"
    }
  }
}

Use When:

Pattern 3: Event-Triggered Polling

Approach: Poll when specific events occur

Implementation:

{
  "pattern": "event-triggered-polling",
  "trigger": "external-event",
  "action": "poll-on-demand"
}

Example:

{
  "eventTriggered": {
    "onUserAction": "Poll player data",
    "onNotification": "Poll related entity",
    "onTimer": "Poll at scheduled time"
  }
}

Use When:


Streaming Patterns

Pattern 1: Single Subject Subscription

Approach: Subscribe to one specific subject

Implementation:

{
  "pattern": "single-subject-streaming",
  "subject": "structs.planet.2-1",
  "events": ["raid_status", "fleet_arrive", "fleet_depart"]
}

Example:

{
  "subscription": {
    "subject": "structs.planet.2-1",
    "description": "Monitor specific planet",
    "events": [
      "raid_status",
      "fleet_arrive",
      "fleet_advance",
      "fleet_depart"
    ]
  }
}

Use When:

Pattern 2: Wildcard Subscription

Approach: Subscribe to multiple entities with pattern

Implementation:

{
  "pattern": "wildcard-streaming",
  "subject": "structs.player.*",
  "description": "Monitor all players"
}

Example:

{
  "subscription": {
    "subject": "structs.player.*",
    "description": "Monitor all player updates",
    "filter": "Process only relevant players"
  }
}

Use When:

Pattern 3: Multi-Subject Subscription

Approach: Subscribe to multiple specific subjects

Implementation:

{
  "pattern": "multi-subject-streaming",
  "subjects": [
    "structs.player.1-1",
    "structs.planet.2-1",
    "structs.guild.0-1"
  ]
}

Example:

{
  "subscriptions": {
    "player": "structs.player.1-1",
    "planet": "structs.planet.2-1",
    "guild": "structs.guild.0-1"
  }
}

Use When:


Hybrid Patterns

Pattern 1: Initial Load + Streaming Updates

Approach: Load initial state via polling, then stream updates

Implementation:

{
  "pattern": "initial-load-streaming",
  "steps": [
    {
      "step": 1,
      "method": "polling",
      "action": "GET /api/player/{id}",
      "description": "Load initial player data"
    },
    {
      "step": 2,
      "method": "streaming",
      "action": "Subscribe to structs.player.{id}",
      "description": "Stream updates"
    }
  ]
}

Benefits:

Pattern 2: Streaming with Polling Fallback

Approach: Use streaming, fallback to polling if connection lost

Implementation:

{
  "pattern": "streaming-with-fallback",
  "primary": "streaming",
  "fallback": "polling",
  "reconnect": true,
  "fallbackInterval": 5000
}

Example:

{
  "strategy": {
    "primary": {
      "method": "streaming",
      "subject": "structs.planet.2-1"
    },
    "fallback": {
      "method": "polling",
      "interval": 5000,
      "trigger": "streaming-connection-lost"
    },
    "reconnect": {
      "enabled": true,
      "strategy": "exponential-backoff"
    }
  }
}

Benefits:

Pattern 3: Selective Streaming

Approach: Stream high-frequency data, poll low-frequency data

Implementation:

{
  "pattern": "selective-streaming",
  "streaming": {
    "data": ["planet_shield", "fleet_status", "raid_status"],
    "reason": "High frequency, real-time needed"
  },
  "polling": {
    "data": ["player_profile", "guild_info", "struct_types"],
    "interval": 300000,
    "reason": "Low frequency, acceptable latency"
  }
}

Benefits:


Performance Considerations

Polling Performance

Factors:

Optimization:

{
  "optimization": {
    "reduceInterval": "When rate limit allows",
    "batchRequests": "When possible",
    "cacheResponses": "To reduce API calls",
    "prioritizeEndpoints": "Focus on critical data"
  }
}

Streaming Performance

Factors:

Optimization:

{
  "optimization": {
    "filterEvents": "Process only relevant events",
    "batchProcessing": "Process multiple events together",
    "connectionPooling": "Reuse connections",
    "backpressure": "Handle high event rates"
  }
}

Cost Analysis

Polling Costs

API Calls: High (repeated requests) Rate Limit Usage: High Network Bandwidth: Moderate Server Load: High (many requests)

Example:

Streaming Costs

API Calls: Low (one connection) Rate Limit Usage: None Network Bandwidth: Low (persistent connection) Server Load: Low (one connection)

Example:


Best Practices

1. Choose Based on Update Frequency

High Frequency (changes every few seconds):

Low Frequency (changes every few minutes):

2. Use Hybrid for Best Results

Initial Load: Polling (fast, simple) Updates: Streaming (real-time, efficient)

3. Monitor and Adjust

Metrics:

4. Implement Fallbacks

Always:

5. Cache Polling Results

When Polling:


Implementation Examples

Example 1: Planet Shield Monitoring (Streaming)

Use Case: Monitor planet shield during raid

Implementation:

{
  "useCase": "planet-shield-monitoring",
  "method": "streaming",
  "reason": "High frequency updates during raid",
  "implementation": {
    "subscribe": "structs.planet.2-1",
    "filter": "raid_status events",
    "action": "Update shield health on event"
  }
}

Benefits:

Example 2: Player Profile (Polling)

Use Case: Display player profile information

Implementation:

{
  "useCase": "player-profile",
  "method": "polling",
  "reason": "Changes infrequently",
  "implementation": {
    "interval": 300000,
    "endpoint": "/api/player/{id}",
    "cache": true,
    "ttl": 300
  }
}

Benefits:

Example 3: Guild Dashboard (Hybrid)

Use Case: Display guild information with real-time member updates

Implementation:

{
  "useCase": "guild-dashboard",
  "method": "hybrid",
  "implementation": {
    "initialLoad": {
      "method": "polling",
      "endpoints": [
        "/api/guild/{id}",
        "/api/guild/{id}/members/count",
        "/api/guild/{id}/power/stats"
      ]
    },
    "updates": {
      "method": "streaming",
      "subjects": [
        "structs.guild.{id}",
        "structs.player.*"
      ],
      "filter": "guild-related events"
    }
  }
}

Benefits:


Decision Tree

Start
  │
  ├─ Data changes every few seconds?
  │   ├─ Yes → Use Streaming
  │   └─ No → Continue
  │
  ├─ Need real-time accuracy?
  │   ├─ Yes → Use Streaming
  │   └─ No → Continue
  │
  ├─ High update frequency expected?
  │   ├─ Yes → Use Streaming
  │   └─ No → Continue
  │
  ├─ Simple implementation preferred?
  │   ├─ Yes → Use Polling
  │   └─ No → Continue
  │
  └─ Use Hybrid (Initial Load + Streaming)


Quick Reference

Use Polling For

Use Streaming For

Use Hybrid For


Pattern Version: 1.0.0 - January 2025