> ## Documentation Index
> Fetch the complete documentation index at: https://vlyai-1c28d863.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Real-time sync

> How Convex's reactive queries auto-update on the client when data changes — no polling, no websocket plumbing.

Real-time sync is the headline feature of Convex (and therefore vly). Every Convex query is a **subscription**: when a client calls `useQuery(api.tasks.list, { teamId })`, it receives the current results *and* gets pushed updates whenever those results would change.

## How it works

```mermaid theme={null}
sequenceDiagram
    Client->>Convex: useQuery(api.tasks.list, { teamId })
    Convex-->>Client: initial result (subscribe)
    Note over Convex: Tracks query dependencies
    User2->>Convex: mutation creates task in teamId
    Convex->>Convex: re-runs affected queries
    Convex-->>Client: pushed update (new result)
    Client->>Client: re-renders
```

No polling. No manual cache invalidation. No `refetch()` calls.

## Why it matters

<CardGroup cols={2}>
  <Card title="Less code" icon="minus">
    A typical "live dashboard" is 50 lines of polling, debouncing, and stale-data handling. With reactive queries: zero.
  </Card>

  <Card title="Lower latency" icon="zap">
    Push, not pull. Updates arrive in under 100 ms after the underlying mutation commits.
  </Card>

  <Card title="Multi-user out of the box" icon="users">
    Two users editing the same data see each other's changes immediately. No extra plumbing.
  </Card>

  <Card title="Predictable cost" icon="dollar-sign">
    No "1-second polling × 10,000 users = 10k req/s" surprise bills.
  </Card>
</CardGroup>

## Common patterns

<Tabs>
  <Tab title="Live dashboard">
    A `useQuery` for each chart. As underlying data flows in, the charts auto-update.
  </Tab>

  <Tab title="Collaborative editor">
    A `useQuery` for the document, a `useMutation` to write changes. Other editors see the live state.
  </Tab>

  <Tab title="Presence">
    A `presence` table; users upsert their `lastSeen` timestamp; other clients query who's been seen in the last 30s.
  </Tab>

  <Tab title="Real-time chat">
    Standard chat: messages table, `useQuery` for the conversation, `useMutation` for new messages.
  </Tab>
</Tabs>

## Limits

* \~10,000 concurrent subscribers per query (soft; raisable)
* A query with very expensive computation will re-run on every relevant mutation; design queries to be cheap
* Subscriptions consume a small amount of bandwidth even when idle (\~1 KB/s per active subscription)

## Tips

<Tip>
  **Subscribe close to where data is consumed.** A `useQuery` near a deeply-nested component re-runs only when *its* data changes — better than passing data down through five levels of props.
</Tip>

<Tip>
  **For "send and forget" mutations, fire-and-forget is fine.** Convex mutations return promises but you don't have to await them in a useEffect; the query subscription handles the update.
</Tip>

## Related

<CardGroup cols={3}>
  <Card title="Convex queries" icon="search" href="/convex/queries">
    The function type that powers reactive sync.
  </Card>

  <Card title="Real-time sync patterns" icon="repeat" href="/architecture/realtime-sync-patterns">
    Architectural patterns.
  </Card>

  <Card title="Real-time chat recipe" icon="message-square-text" href="/recipes/realtime-chat-app">
    A worked example.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.