Skip to main content

Overview

GraphQL subscriptions provide real-time updates when data changes on the server. 5Stack uses WebSocket connections to deliver live updates for matches, tournaments, chat messages, and player statistics.

Subscription Setup

Subscriptions require a WebSocket connection to the GraphQL endpoint:
import { createClient } from 'graphql-ws';
import { GraphQLWsLink } from '@apollo/client/link/subscriptions';

const wsClient = createClient({
  url: 'wss://{API_DOMAIN}/v1/graphql',
  connectionParams: {
    credentials: 'include',
  },
});

const wsLink = new GraphQLWsLink(wsClient);

Subscription Structure

Subscriptions are generated using the generateSubscription helper:
import { generateSubscription } from '@/graphql/graphqlGen';
import { $ } from '@/generated/zeus';

const subscription = generateSubscription({
  // Your subscription fields here
});

Match Subscriptions

Subscribe to Match Updates

Get real-time updates when a match changes:
import { generateSubscription } from '@/graphql/graphqlGen';
import { simpleMatchFields } from '@/graphql/simpleMatchFields';
import { $ } from '@/generated/zeus';

const subscription = generateSubscription({
  matches_by_pk: [
    { id: $('match_id', 'uuid!') },
    simpleMatchFields
  ]
});
Usage in Vue components:
<script>
import { generateSubscription } from '@/graphql/graphqlGen';
import { simpleMatchFields } from '@/graphql/simpleMatchFields';
import { $ } from '@/generated/zeus';

export default {
  apollo: {
    $subscribe: {
      match: {
        query: generateSubscription({
          matches_by_pk: [
            { id: $('match_id', 'uuid!') },
            simpleMatchFields
          ]
        }),
        variables() {
          return {
            match_id: this.matchId
          };
        },
        result({ data }) {
          this.match = data.matches_by_pk;
        }
      }
    }
  },
  data() {
    return {
      matchId: 'your-match-uuid',
      match: null
    };
  }
}
</script>
This subscription will fire whenever the match status changes, lineups update, maps are vetoed, or scores change.

Subscribe to Match Lineup Stats

Get real-time player statistics during a live match:
import { generateSubscription } from '@/graphql/graphqlGen';
import { matchLineups } from '@/graphql/matchLineupsGraphql';
import { $ } from '@/generated/zeus';

const subscription = generateSubscription({
  match_lineups: [
    {
      where: {
        match_id: { _eq: $('matchId', 'uuid!') }
      }
    },
    matchLineups
  ]
});
This subscription includes live updates for:
  • Player kills, deaths, and assists (KDA)
  • Headshot percentage
  • Damage dealt
  • Flash assists
  • Multi-kills (2K, 3K, 4K, 5K)
  • Utility usage statistics

Subscribe to Live Matches

Watch all currently active matches:
import { generateSubscription } from '@/graphql/graphqlGen';
import { simpleMatchFields } from '@/graphql/simpleMatchFields';

const subscription = generateSubscription({
  matches: [
    {
      where: {
        status: { _in: ['Live', 'Veto'] }
      },
      order_by: [{ started_at: 'desc' }]
    },
    simpleMatchFields
  ]
});

Tournament Subscriptions

Subscribe to Tournament Updates

Get real-time updates for tournament status and bracket changes:
import { generateSubscription } from '@/graphql/graphqlGen';
import { simpleTournamentFields } from '@/graphql/simpleTournamentFields';
import { $ } from '@/generated/zeus';

const subscription = generateSubscription({
  tournaments_by_pk: [
    { id: $('tournament_id', 'uuid!') },
    simpleTournamentFields
  ]
});

Subscribe to Tournament Matches

Watch all matches in a tournament:
import { generateSubscription } from '@/graphql/graphqlGen';
import { simpleMatchFields } from '@/graphql/simpleMatchFields';
import { $ } from '@/generated/zeus';

const subscription = generateSubscription({
  matches: [
    {
      where: {
        tournament_id: { _eq: $('tournament_id', 'uuid!') }
      },
      order_by: [{ scheduled_at: 'asc' }]
    },
    simpleMatchFields
  ]
});

Server Subscriptions

Subscribe to Dedicated Server Status

Monitor a game server’s status:
import { generateSubscription } from '@/graphql/graphqlGen';
import { $ } from '@/generated/zeus';

const subscription = generateSubscription({
  servers_by_pk: [
    { id: $('serverId', 'uuid!') },
    {
      id: true,
      name: true,
      status: true,
      current_map: true,
      current_players: true,
      max_players: true,
      ip: true,
      port: true
    }
  ]
});

Subscribe to Available Servers

import { generateSubscription } from '@/graphql/graphqlGen';

const subscription = generateSubscription({
  servers: [
    {
      where: {
        status: { _eq: 'Available' },
        enabled: { _eq: true }
      }
    },
    {
      id: true,
      name: true,
      region: true,
      max_players: true
    }
  ]
});

Database Subscriptions

Subscribe to Database Backups

Monitor database backup operations:
import { generateSubscription } from '@/graphql/graphqlGen';

const subscription = generateSubscription({
  db_backups: [
    {},
    {
      id: true,
      name: true,
      size: true,
      status: true,
      created_at: true,
      completed_at: true,
      error_message: true
    }
  ]
});
Usage example:
<script>
export default {
  apollo: {
    $subscribe: {
      backups: {
        query: generateSubscription({
          db_backups: [
            {},
            {
              id: true,
              name: true,
              size: true,
              status: true,
              created_at: true
            }
          ]
        }),
        result({ data }) {
          this.backups = data.db_backups;
        }
      }
    }
  }
}
</script>

Player Subscriptions

Subscribe to Player Updates

Watch changes to a player’s profile:
import { generateSubscription } from '@/graphql/graphqlGen';
import { playerFields } from '@/graphql/playerFields';
import { $ } from '@/generated/zeus';

const subscription = generateSubscription({
  players_by_pk: [
    { steam_id: $('steam_id', 'String!') },
    playerFields
  ]
});

Subscribe to Player ELO Changes

import { generateSubscription } from '@/graphql/graphqlGen';
import { $ } from '@/generated/zeus';

const subscription = generateSubscription({
  players_by_pk: [
    { steam_id: $('steam_id', 'String!') },
    {
      steam_id: true,
      name: true,
      elo: true,
      elo_history: [
        {
          order_by: [{ created_at: 'desc' }],
          limit: 10
        },
        {
          elo: true,
          created_at: true,
          match_id: true
        }
      ]
    }
  ]
});

Chat Subscriptions

Subscribe to Chat Messages

Receive real-time chat messages for a lobby:
import { generateSubscription } from '@/graphql/graphqlGen';
import { $ } from '@/generated/zeus';

const subscription = generateSubscription({
  chat_messages: [
    {
      where: {
        lobby_id: { _eq: $('lobby_id', 'uuid!') }
      },
      order_by: [{ created_at: 'asc' }],
      limit: 100
    },
    {
      id: true,
      message: true,
      created_at: true,
      player: {
        steam_id: true,
        name: true,
        avatar_url: true,
        role: true
      }
    }
  ]
});

Subscription Patterns

Unsubscribing

Always clean up subscriptions when components unmount:
export default {
  beforeUnmount() {
    // Apollo automatically unsubscribes when component unmounts
    // Manual cleanup for custom subscriptions:
    if (this.$apollo?.subscriptions) {
      Object.keys(this.$apollo.subscriptions).forEach(key => {
        this.$apollo.subscriptions[key].unsubscribe();
      });
    }
  }
}

Conditional Subscriptions

Start subscriptions conditionally:
export default {
  apollo: {
    $subscribe: {
      match: {
        query: generateSubscription({ /* ... */ }),
        skip() {
          // Skip subscription if no match ID
          return !this.matchId;
        },
        variables() {
          return { match_id: this.matchId };
        }
      }
    }
  }
}

Handling Errors

export default {
  apollo: {
    $subscribe: {
      match: {
        query: generateSubscription({ /* ... */ }),
        variables() {
          return { match_id: this.matchId };
        },
        result({ data }) {
          this.match = data.matches_by_pk;
        },
        error(error) {
          console.error('Subscription error:', error);
          this.$toast({
            variant: 'destructive',
            title: 'Connection Error',
            description: 'Failed to receive live updates'
          });
        }
      }
    }
  }
}

Performance Considerations

Only subscribe to the specific fields you need. Avoid subscribing to large datasets or deeply nested relationships unless necessary.
Filter subscriptions at the database level using where clauses instead of filtering in the client.
Use limit clauses to restrict the number of records returned, especially for lists.
For rapidly changing data, consider debouncing updates in your UI to reduce re-renders.

WebSocket Connection Management

Connection States

Monitor WebSocket connection state:
const wsClient = createClient({
  url: 'wss://{API_DOMAIN}/v1/graphql',
  connectionParams: {
    credentials: 'include',
  },
  on: {
    connected: () => console.log('WebSocket connected'),
    closed: () => console.log('WebSocket closed'),
    error: (error) => console.error('WebSocket error:', error)
  }
});

Reconnection

The GraphQL WebSocket client automatically handles reconnection with exponential backoff. You can customize this behavior:
const wsClient = createClient({
  url: 'wss://{API_DOMAIN}/v1/graphql',
  retryAttempts: 5,
  retryWait: (retries) => {
    // Exponential backoff: 1s, 2s, 4s, 8s, 16s
    return new Promise(resolve => 
      setTimeout(resolve, Math.min(1000 * Math.pow(2, retries), 30000))
    );
  }
});

Next Steps

Queries

Learn about querying initial data

Mutations

Trigger subscriptions with mutations

Build docs developers (and LLMs) love