DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • AWS Managed Database Observability: Monitoring DynamoDB, ElastiCache, and Redshift Beyond CloudWatch
  • Jakarta Query: Unifying Queries Across SQL and NoSQL in Jakarta EE 12
  • Top NoSQL Databases and Use Cases
  • Jakarta NoSQL 1.0: A Way To Bring Java and NoSQL Together

Trending

  • Can Claude Skills Replace Playwright Agents? A Practical View for QA Engineers
  • Working With Cowork: Don’t Be Confused
  • Optimizing High-Volume REST APIs Using Redis Caching and Spring Boot (With Load Testing Code)
  • Code Quality Had 5 Pillars. AI Broke 3 and Created 2 We Can’t Measure
  1. DZone
  2. Data Engineering
  3. Databases
  4. Atomic Writes in NoSQL: A Multi-Cloud Deep Dive

Atomic Writes in NoSQL: A Multi-Cloud Deep Dive

We analyze atomic write strategies in AWS, GCP, Azure, and Alibaba, demonstrating how MultiCloudJ ensures unified, consistent transaction semantics across NoSQL

By 
Sandeep Pal user avatar
Sandeep Pal
·
Dec. 23, 25 · Analysis
Likes (3)
Comment
Save
Tweet
Share
1.8K Views

Join the DZone community and get the full member experience.

Join For Free

Atomic writes used to be one of the important reasons we stuck with relational databases. The rule was simple: either all your updates succeed, or they all fail. But as we moved to NoSQL databases in distributed systems, we often traded that safety for scale. Now, the pendulum is swinging back. Developers building microservices and server-less apps are realizing that writing manual undo logic (compensating transactions) is a nightmare, and they want their NoSQL databases to handle that heavy lifting again.

However, atomicity isn't standard across the cloud. AWS, Azure, GCP, and Alibaba all offer transaction capabilities, but they have wildly different rules regarding locking, limits, idempotency, and consistency guarantees.

When building multi-cloud Java applications with NoSQL dependencies, you face the challenge of normalizing divergent provider semantics to ensure true portability.

This is where MultiCloudJ comes in. In this article, we’ll break down exactly how atomic writes work inside AWS DynamoDB, Google Firestore, Azure Cosmos DB, and Alibaba Tablestore. Then, we will show how MultiCloudJ abstracts away these vendor-specific complexities to provide a unified, consistent way to handle atomic writes across any cloud.

Atomic Writes vs. Batch Writes: A Critical Distinction

Before diving in, it’s important to clarify terminology. Many developers mistakenly assume a batch operation is atomic. That assumption leads to subtle data corruption and unexpected partial states. Let's understand the core differences between batched writes and atomic write:

Feature batch write atomic writes(Transactions)
Primary Goal Performance. Reduces network latency by combining requests. Consistency. Ensures data integrity (ACID). 
Failure Mode Partial. Some items may succeed while others fail. All-or-Nothing. If one item fails, the entire group rolls back.
Risk Can lead to data corruption or "zombie" records if error handling isn't perfect. Higher latency and cost, but guarantees a clean consistent state.


Provider-by-Provider Comparison of Atomic Write Features

Here’s a crisp comparison across the four major cloud NoSQL services:

Provider Atomic Writes support Granularity Idempotency Support
AWS DynamoDB Yes Across Tables Yes
GCP Firestore Yes Across Collections Yes
Azure Cosmos DB Yes Within Partition Key Yes
Alibaba Tablestore Yes Within Partition Key Partial

Let's delve deeper into this:

AWS DynamoDB:

DynamoDB sets a high bar for NoSQL consistency, supporting true ACID transactions across multiple tables and items within the same AWS Region. As defined in the official AWS TransactWriteItems documentation:

"TransactWriteItems is a synchronous and idempotent write operation that groups up to 100 write actions in a single all-or-nothing operation."

Key Capabilities:

  • Scope: Supports up to 100 operations in a single transaction (increased from the original 25) across different tables in the same region and account.
  • Flexibility: Allows a mix of Put, Update, Delete, and ConditionCheck actions across different tables.
  • Safety: Built-in idempotency tokens (ClientRequestToken) ensure that if a network error occurs during a retry, the write isn't applied twice, a critical feature for financial ledgers. However, note that the idempotency is guaranteed with the same token for just 10 minutes. 

Limitations:

  • TransactWriteItems do not directly contains the read requests as part of transaction. In fact, there is TransactionReadItems for that purpose.
  • Limit to just 25 items in TransactionWriteItems.

Google Cloud Firestore: 

Firestore supports atomic multi-document transactions across collections. Its client SDKs manage the transaction loop for you (including automatic retries on contention), whereas DynamoDB exposes transactional APIs (TransactWriteItems, TransactGetItems) where you typically handle retries and error handling explicitly in the application code.

Key Capabilities

  • Global Scope: Supports atomic writes across any number of documents and collections within the database instance.
  • Read and Writes in the same transaction: Support all types of get and put operations in the same transaction. However, read should be before the write for the item.
  • Automatic Retries: If a write conflict occurs (e.g., concurrent modification), the client SDK automatically re-attempts the entire write operation.
  • No hard limit on number of documents in transaction but can contain up-to 500 transformations to a single document in a transaction.

Limitations

  • Client-Side Dedup: No built-in idempotency token. You must implement your own logic to prevent duplicate processing if a network error occurs during the commit.
  • Online Only: Atomic transactions fail immediately if the client is offline; they cannot be queued.


Azure Cosmos DB: 

Cosmos DB prioritizes speed and predictability. To achieve this, it offers full ACID support via TransactionalBatch, but with a strict architectural boundary: The Logical Partition.

Key Capabilities:

  • Partition-Scoped Atomicity: Transactions can include up to 100 operations, but every item in the batch must share the same Partition Key.
  • Performance: Because transactions never span across physical servers (shards), they are extremely fast and retain Cosmos DB's low-latency guarantees.

Limitations

  • No Cross-Partition Transactions: If your business logic requires atomically updating two items with different partition keys, Cosmos DB cannot do it natively.
  • No Native Idempotency and Retries: Developers must build their own safety nets for network retries and timeouts. Applications are responsible for handling 429 (Throttling) errors and ensuring writes aren't duplicated during retries.

Alibaba Cloud Tablestore: 

Tablestore (OTS) also provides local transactions bound to a single partition key-similar to Cosmos DB. It adopts a traditional "interactive" transaction model but confines it to a single partition key. Instead of sending all writes in one packet, you open a transaction, receive a Transaction ID, and use that ID for subsequent writes before finally committing.

Key Capabilities:

  • Interactive Lifecycle: Uses StartLocalTransaction, CommitTransaction, and AbortTransaction APIs, giving the client control over the logic flow.
  • Isolation: Operations performed with the active Transaction ID are isolated from other readers until committed.
  • 60-Second Validity: The Transaction ID remains valid for up to 60 seconds. This allows for complex client-side logic (calculations between reads and writes) while holding the lock.

Limitations

  • Scope Limit:Strictly limited to a single partition key. Cross-partition updates must be handled asynchronously.
  • Time-Bound Risk: If your client crashes or pauses (e.g., a long Java GC pause) and exceeds the 60-second window, the transaction expires and data is lost.
  • No "Fire-and-Forget": Because it is stateful, you must explicitly handle the Abort signal if a step fails, otherwise you risk leaving locks open until they timeout.

Cross-Cloud Design Lessons: What Developers Should Care About

If you are building multi-cloud architectures, portable NoSQL abstractions, or systems that may migrate between clouds, instead of dealing with cloud specific features, you can rely on MultiCloudJ for semantics and keep the following in mind:

Granularity Is Not Consistent Across Providers

  • DynamoDB and Firestore: Cross-collection/table
  • Cosmos and Tablestore: Single partition only

You cannot assume multi-partition atomicity unless you stay inside AWS or GCP Firestore. Therefore, if if you want to make your application truly portable across multiple clouds, you shouldn't design for cross-partition atomic writes.

Idempotency Guarantees Vary

  • DynamoDB: Server-side idempotency tokens
  • Others: No native idempotency

For high-volume workloads, add your own idempotency keys (UUIDs, request IDs, etc.).

Retry Semantics Differ

  • DynamoDB: Built-in deduplication
  • Firestore: Client-driven retry loops
  • Cosmos/Tablestore: Must implement manual retry logic

Your application should standardize retry behavior if targeting multiple clouds.

Cross-Cloud Abstractions

Cross-Cloud Abstractions Must Target the Lowest Common Denominator for portability. In MultiCloudJ, the least common denominator at partition scope is supported, this is the safest universal model.

Example using atomic writes in MultiCloudJ:

Java
 
@AllArgsConstructor
@Data
@NoArgsConstructor
static class Book {
  private String title;
  private Person author;
  private String publisher;
  private float price;
  private Map<String, Integer> tableOfContents;
  private Object docRevision;
}

CollectionOptions collectionOptions = new CollectionOptions.CollectionOptionsBuilder()
  .withTableName(tableName)
  .withPartitionKey(KEY_TITLE)
  .withSortKey(KEY_PUBLISHER)
  .withRevisionField(REVISION_FIELD)
  .withAllowScans(true)
  .build();

DocStoreClient client = DocStoreClient.builder("aws") 
  .withRegion(REGION)
  .withCollectionOptions(collectionOptions)
  .build();


// Create multiple books with atomic writes
client.getActions()
  .enableAtomicWrites() // <- set this and all subsequent writes will be atomic
  .create(new Document(new Book("RedBook", SAMPLE_PERSON, "CA", 4.99f, null, null)))
  .create(new Document(new Book("GreenBook", SAMPLE_PERSON, "NY", 5.99f, null, null)))
  .create(new Document(new Book("BlueBook", SAMPLE_PERSON, "TX", 6.99f, null, null)))
  .run();

for detailed example: you can ref examples in MultiCloudJ.

Conclusion: Atomic Writes Are Universal in Need, But Not in Implementation

Every major cloud NoSQL database now supports atomic writes or transactions, but not in the same way:

  • AWS DynamoDB: Cross-table, idempotent, strongest semantics
  • GCP Firestore: Cross-collection, but client-driven retries
  • Azure Cosmos DB: Fast, partition-scoped atomicity
  • Alibaba Tablestore: Partition-scoped atomicity with temporary transaction IDs

The success of a multi-cloud application hinges on its data strategy. If you don't account for differences in partition keys and idempotency across providers, you risk unpredictable behavior and data inconsistency.

Solving this usually means writing complex boilerplate code to bridge different provider SDKs. MultiCloudJ solves this friction. It provides a standardized interface for transaction management, meaning you don't have to learn the low-level intricacies of every provider to achieve atomic writes.

Amazon DynamoDB Database NoSQL

Opinions expressed by DZone contributors are their own.

Related

  • AWS Managed Database Observability: Monitoring DynamoDB, ElastiCache, and Redshift Beyond CloudWatch
  • Jakarta Query: Unifying Queries Across SQL and NoSQL in Jakarta EE 12
  • Top NoSQL Databases and Use Cases
  • Jakarta NoSQL 1.0: A Way To Bring Java and NoSQL Together

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook