18 Transactions and Batch Writes

To handle multiple operations (reads and writes) atomically and efficiently, transaction and batch writes operations are used to group together operation and run as a single transaction. Oracle Backend for Firebase provides robust support for atomic multi-document operations through transactions and batch writes. Document operations such as grouping multiple document operations into a single atomic unit ensures consistency and rollback capabilities across complex workflows. These mechanisms are essential for maintaining data consistency, especially in applications that require coordinated updates across multiple documents or collections.

This section outlines the conceptual model, use cases, operational behavior, and field-level capabilities of transactions and batch writes. SDK-specific implementations are covered in Transaction and Batch Writes Examples.

18.1 Overview

Transaction and batch write mechanisms ensure atomicity, consistency, and isolation, making them ideal for collaborative apps, real-time updates, and multi-step workflows.

Transaction

A transaction is a read-modify-write operation that executes atomically. If any step fails or the underlying data changes during execution, the entire transaction is rolled back and retried.

Transactions are automatically retried if document versions change. Developers should ensure logic is idempotent and bounded.

Transactions are particularly useful when you need to read from database to check the state of a document before performing updates.

Batch Write

A batch write is a way to group multiple write operations into a single request. A batch write operation is a set of independent write operations (create, update, delete) that execute together. All operations are applied in parallel, and they either all succeed or all fail. Unlike transactions, batch writes do not support reading documents. No reads are allowed in batch writes.

Note:

In batch writes, if any operation is invalid or unauthorized, the entire batch is rejected. Exercise prudence to validate inputs before execution.

Limitations

Transaction and batch writes have the following limitations:

  • Security rule deny
    • If any operation fails during runTransaction, complete transaction is aborted.
    • Security rule will be checked for each operation executed within the transaction.
  • Timeout Period

18.2 Prerequisites

  • The application is initialized using initializeApp() with a valid configuration.

  • The user is authenticated if the target documents are protected by security rules.

  • The documents involved in the operation exist (for updates) or are valid paths (for creation).

  • Security rules explicitly allow the intended operations (create, update, delete).

  • Indexes are defined if the transaction involves conditional reads or filters.

18.3 Transaction Support

Transactions allow developers to perform multiple read and write operations atomically.

  • All operations inside a transaction succeed or fail together.

  • Transactions can include conditional logic based on the current state of the data.

  • This ensures strong consistency when multiple clients are updating the same documents concurrently.

Transactions have the following execution flow:

  1. Begin Transaction: The client initiates a transaction block.

  2. Read Phase: All required documents are read to fetch the current state of one or more documents.

  3. Apply Conditional Logic: Decide whether to proceed with updates based on the read values.

  4. Write Phase: Updates are staged based on read results. Perform setDoc, updateDoc, or deleteDoc operations.

  5. Commit: If no conflicting changes occurred, the transaction is committed. Otherwise, it is rolled back.

If any document read during the transaction changes before commit, Oracle Backend for Firebase automatically rolls back the transaction. This ensures consistency but requires idempotent logic.

A few examples use cases of transactions are:

  • Increment counters (For example, views, likes) safely.

  • Transfer values between documents (For example, balances).

  • Enforce conditional updates (For example, only update if status is "active").

Transactions are initiated and managed using three key fields in the request payload:

The following must be noted about the transaction support:

  • Transactions span multiple operations such as addDoc, updateDoc, deleteDoc, and getDocs.

  • All operations must include the same transaction_name to be grouped.

  • If any operation fails, the entire transaction is rolled back.

  • Transactions are internally managed using Oracle session context and PL/SQL transaction control.

Example 18-1 Transaction Request

Suppose that you need to increment the views counter of a recipe only if the current value is less than 1000. Additionally, add a new tag to the recipe if the condition is met.

{
  "transaction": {
    "reads": [
      {
        "path": "/users/Scott/recipes/Cookies",
        "fields": ["views"]
      }
    ],
    "condition": {
      "field": "views",
      "op": "<",
      "value": 1000
    },
    "writes": [
      {
        "type": "updateDoc",
        "path": "/users/Scott/recipes/Cookies",
        "data": {
          "views": { "increment": 1 },
          "tags": { "arrayUnion": ["popular"] }
        }
      }
    ]
  }
}

The following is the outcome:

  • If views < 1000:

    • The views field is incremented by 1.

    • The tag "popular" is added to the tags array.

  • If views >= 1000:

    • The transaction fails and no changes are applied.

When to Use Transaction

  • Conditional updates based on current document data

  • Atomicity is required for both reads and writes

  • Read-modify-write patterns (like incrementing counters)

  • Error handling and automatic retries for conflicting operations

18.4 Batch Writes

Batch writes allow developers to send multiple operations in a single array payload. Unlike transactions, batch writes do not support reads or conditional logic. Each operation is executed in sequence, and the entire batch is treated as a single transaction if begin_trans and end_trans are specified.

The batch writes structure is as follows:

  • Each object in the array represents a distinct operation.

  • Operations can include setDoc (create or overwrite a document), addDoc / updateDoc (add or update specific fields in an existing document), and deleteDoc() (remove a document entirely).

  • The batch is atomic, which means that either all operations succeed, or none are committed. All operations in a batch are committed together. If any operation fails (For instance, due to permission or invalid path), the entire batch is aborted.

The following is a general workflow:

  • Begin a batch:

    • Start a batch context.

  • Add operations: Include one or more setDoc, updateDoc, or deleteDoc operations.

  • Commit batch: Execute all operations atomically. If any operation fails, none of the changes are applied.

Example 18-2 Batch Writes

Suppose that you need to create a new recipe document, update the user’s profile with a new counter, and delete an obsolete recipe. THe batch request is as follows:

{
  "batch": {
    "operations": [
      {
        "type": "setDoc",
        "path": "/users/Scott/recipes/Cookies",
        "data": {
          "title": "Chocolate Chip Cookies",
          "ingredients": "2 cups flour,1 cup sugar,2 cups chocolate chips",
          "createdAt": "serverTimestamp"
        }
      },
      {
        "type": "updateDoc",
        "path": "/users/Scott",
        "data": {
          "recipeCount": { "increment": 1 }
        }
      },
      {
        "type": "deleteDoc",
        "path": "/users/Scott/recipes/OldRecipe"
      }
    ]
  }
}

This results in the following outcome:

  • A new recipe document is created.

  • The user’s recipeCount field is incremented by 1.

  • The obsolete recipe document is deleted.

  • If any operation fails, none of the changes are applied.

When to Use Batch Writes

  • Multiple writes to independent documents.

  • No need to read documents before writing.

  • Performance is important, and all operations are write-only.

  • Mass updates to large datasets without conditional checks.

A few example use cases of batch write are:

  • Bulk creation of documents (For example, onboarding users).

  • Mass updates to fields (For example, tagging multiple items).

  • Cleanup operations (For example, deleting expired records).

Security and Validation

  • Each operation is validated against CEL-based security rules before execution.

  • If any operation (rule) fails, the transaction is ended and rolled back.

18.5 Field-Level Modifiers

Oracle Backend for Firebase supports powerful field-level operations that enhance both transactions and batch writes. These modifiers are applied within the document payload.

Modifier Description Example

serverTimestamp

Stores the current server time.

createdAt: serverTimestamp()

increment(n)

Atomically adds/subtracts a numeric value.

views: increment(1)

arrayUnion(values)

Adds values to an array if not already present.

tags: arrayUnion("dessert")

arrayRemove(values)

Removes matching values from an array.

tags: arrayRemove("archived")

deleteField

Deletes a field from the document.

notes: deleteField()

Example 18-3 Payload

These modifiers are especially useful in real-time apps where multiple clients may update the same document concurrently.

{
  "title": "Chocolate Chip Cookies",
  "tags": arrayUnion("dessert"),
  "createdAt": serverTimestamp(),
  "views": increment(1),
  "notes": deleteField()
}