@@ -575,6 +575,21 @@ insert([
575575 { text: "Buy groceries", completed: false },
576576 { text: "Walk dog", completed: false },
577577])
578+
579+ // Insert with optimistic updates disabled
580+ myCollection.insert(
581+ { text: "Server-validated item", completed: false },
582+ { optimistic: false }
583+ )
584+
585+ // Insert with metadata and optimistic control
586+ myCollection.insert(
587+ { text: "Custom item", completed: false },
588+ {
589+ metadata: { source: "import" },
590+ optimistic: true // default behavior
591+ }
592+ )
578593` ` `
579594
580595##### ` update `
@@ -598,6 +613,27 @@ update([todo1.id, todo2.id], (drafts) => {
598613update(todo.id, { metadata: { reason: "user update" } }, (draft) => {
599614 draft.text = "Updated text"
600615})
616+
617+ // Update without optimistic updates
618+ update(
619+ todo.id,
620+ { optimistic: false },
621+ (draft) => {
622+ draft.status = "server-validated"
623+ }
624+ )
625+
626+ // Update with both metadata and optimistic control
627+ update(
628+ todo.id,
629+ {
630+ metadata: { reason: "admin update" },
631+ optimistic: false
632+ },
633+ (draft) => {
634+ draft.priority = "high"
635+ }
636+ )
601637` ` `
602638
603639##### ` delete `
@@ -611,6 +647,67 @@ delete([todo1.id, todo2.id])
611647
612648// Delete with metadata
613649delete(todo.id, { metadata: { reason: "completed" } })
650+
651+ // Delete without optimistic updates (waits for server confirmation)
652+ delete(todo.id, { optimistic: false })
653+
654+ // Delete with metadata and optimistic control
655+ delete(todo.id, {
656+ metadata: { reason: "admin deletion" },
657+ optimistic: false
658+ })
659+ ` ` `
660+
661+ #### Controlling optimistic behavior
662+
663+ By default , all mutations (` insert ` , ` update ` , ` delete ` ) apply optimistic updates immediately to provide instant feedback in your UI . However , there are cases where you may want to disable this behavior and wait for server confirmation before applying changes locally .
664+
665+ ##### When to use ` optimistic: false `
666+
667+ Consider disabling optimistic updates when :
668+
669+ - ** Complex server - side processing ** : Inserts that depend on server - side generation (e .g ., cascading foreign keys , computed fields )
670+ - ** Validation requirements ** : Operations where backend validation might reject the change
671+ - ** Confirmation workflows ** : Deletes where UX should wait for confirmation before removing data
672+ - ** Batch operations ** : Large operations where optimistic rollback would be disruptive
673+
674+ ##### Behavior differences
675+
676+ ** ` optimistic: true ` (default )** :
677+ - Immediately applies mutation to the local store
678+ - Provides instant UI feedback
679+ - Requires rollback if server rejects the mutation
680+ - Best for simple , predictable operations
681+
682+ ** ` optimistic: false ` ** :
683+ - Does not modify local store until server confirms
684+ - No immediate UI feedback , but no rollback needed
685+ - UI updates only after successful server response
686+ - Best for complex or validation - heavy operations
687+
688+ ` ` ` typescript
689+ // Example: Critical deletion that needs confirmation
690+ const handleDeleteAccount = () => {
691+ // Don't remove from UI until server confirms
692+ userCollection.delete(userId, { optimistic: false })
693+ }
694+
695+ // Example: Server-generated data
696+ const handleCreateInvoice = () => {
697+ // Server generates invoice number, tax calculations, etc.
698+ invoiceCollection.insert(invoiceData, { optimistic: false })
699+ }
700+
701+ // Example: Mixed approach in same transaction
702+ tx.mutate(() => {
703+ // Instant UI feedback for simple change
704+ todoCollection.update(todoId, (draft) => {
705+ draft.completed = true
706+ })
707+
708+ // Wait for server confirmation for complex change
709+ auditCollection.insert(auditRecord, { optimistic: false })
710+ })
614711` ` `
615712
616713## Usage examples
0 commit comments