Choosing a backend

createChatHandler separates conversation persistence (ChatStore) from attachment storage (StorageAdapter). Both are factories called after authentication with the verified userId.

code
type ChatStoreFactory = (userId: string) => ChatStore;
type StorageAdapterFactory = (userId: string) => StorageAdapter;

Options

NeedFactory
Self-hosted Postgres conversationscreateDrizzleChatStore()
Private Supabase attachmentscreateSupabaseStorage()
Hosted conversationscreateHostedChatStore({ apiKey })
Hosted attachmentscreateHostedStorage({ apiKey })
Custom database/object storeYour own user-bound factory

Persistence is currently required; there is no silent default store. Storage is optional and uploads are disabled when it is absent.

code
export const { GET, POST, DELETE } = createChatHandler({
  getUserId: getChatUserId,
  model,
  store: createDrizzleChatStore(),
  storage: createSupabaseStorage(),
});

Mix the axes deliberately: Drizzle plus Supabase, hosted store plus custom storage, or fully custom implementations. All custom stores/adapters must uphold the ownership and private-attachment invariants.