Storing Chats as Synced Data
Your backend calls the model, never the client, so model API keys stay on your server. The code that calls the model can live in your backend API, a separate process, or a background job, as long as it can write to your source database. Because the client reads and writes only to its local database:- A chat opens without a network request.
- A reply in progress survives a page refresh, and shows in every tab and device where the chat is open.
- A message sent offline waits in the upload queue until the client reconnects.
- If several users can access a chat, for example through a chat members table in your Sync Streams, they all see new messages and replies as they arrive.
Tables
Create achats table and a messages table. Give AI-generated messages a status column so that the client can show whether a reply is pending, being generated, done, stopped, or failed. If generation fails, store the error message on the row as well.
Sync Streams
Define two Sync Streams. Thechats stream syncs the user’s chats, and the client subscribes to chat_messages for the chat that is open:
Generating Replies
- When the user sends a message, the client writes two rows in one local transaction: the user’s message, and an empty message for the AI reply, with a pending status. The UI shows the pending reply right away, even offline.
- The client SDK uploads both rows to your backend through
uploadData()in your backend connector. - The backend claims the pending reply with a conditional update, so that only one backend process works on it.
- The backend sends the chat history to the AI model.
- When the model finishes, the backend saves the full text and marks the reply as done.