This episode covers ACID in the Vitess context: fully guaranteed single-shard transactions, cross-shard transactions with their limitations, XA support, locking behavior, stale reads, and best practices for maintaining consistency in a distributed cluster.

Finance, e-commerce, and booking applications depend on transactions: sequences of operations that must all succeed or all fail. Episode 9 covers how Vitess handles transactions when data is spread across many shards — an area where scale and ACID guarantees often collide.
Episode 9 roadmap: ACID in the Vitess context, single-shard transactions, cross-shard transactions and XA, locking and stale reads, then consistency best practices. This episode determines how safely you can entrust critical data to Vitess.
ACID: Atomicity (all or nothing), Consistency (data is valid after a transaction), Isolation (transactions don't interfere with each other), and Durability (data survives crashes). Vitess inherits ACID guarantees from MySQL, but with nuances that depend on the transaction's scope.
The key to understanding it: ACID guarantees in Vitess are fully honored within a single shard. As soon as a transaction spans more than one shard, some guarantees become weaker — and you need to be aware of these trade-offs when designing applications.
If all operations in a transaction touch data in the same shard — which is usually guaranteed when all queries use the sharding key column — Vitess provides full ACID guarantees just like regular MySQL. Vitess routes the entire transaction to one VTTablet, and the transaction runs as if directly on MySQL.
BEGIN
INSERT INTO orders (order_id, user_id, amount)
VALUES (1001, 42, 250000)
UPDATE wallet SET balance = balance - 250000
WHERE user_id = 42
COMMITBecause user_id = 42 and order_id belong to the same user (co-located), the whole transaction above runs in one shard — full ACID guarantees. BEGIN, COMMIT, and ROLLBACK are all supported at VTGate.
What if a transaction touches data in two different shards? Example: transferring funds from a user in shard A to a user in shard B. That's a cross-shard transaction, and this is where the complexity appears.
Vitess handles cross-shard transactions with two approaches:
vtctlclient SetKeyspaceDurabilityPolicy \
-durability-policy=semi_sync commerceThe vtctlclient SetKeyspaceDurabilityPolicy command sets the durability policy, part of the configuration that affects how transactions and failover maintain consistency.
Warning
Cross-shard transactions without 2PC don't provide global atomicity. If your application needs cross-shard atomicity — for example, transferring funds between accounts on different shards — consider 2PC, or redesign so related operations are always co-located in the same shard.
MySQL uses locking for isolation: row locks prevent two transactions from writing the same row concurrently. In single-shard Vitess, locking works like MySQL. In cross-shard scenarios, locking can't atomically lock data across two different MySQL instances — which is again why co-located design is so strongly recommended.
SELECT ... FOR UPDATE is supported and useful for maintaining consistency during staged updates. Because VTGate forwards it to the right shard, make sure this query uses the sharding key column so it locks the correct rows in one shard.
Reading from a replica can produce a stale read — data that hasn't fully replicated from the primary. Vitess gives this control to the application:
replica_consistency.shard_consistency=strong or make sure reads go through the primary.SELECT balance FROM wallet WHERE user_id = 42The SELECT balance query above runs through VTGate. Based on the configured policy, VTGate decides whether this read goes to the primary or a replica — the application doesn't need to know the details.
MySQL provides several isolation levels, and this choice affects transaction behavior in Vitess:
REPEATABLE READ — MySQL's default. Data read stays consistent within a transaction; suitable for most workloads.READ COMMITTED — only already committed data is visible; reduces lock contention.READ UNCOMMITTED — reads uncommitted data; fastest but must not be used for important data.SERIALIZABLE — the strictest guarantee at the cost of the most locking.SELECT @@transaction_isolationSELECT @@transaction_isolation shows the current session isolation level. In Vitess, most workloads use the default REPEATABLE READ — and because the strongest guarantees only hold within a single shard, looser isolation levels offer no real benefit for cross-shard transactions.
Success
The most powerful principle: "one transaction, one shard". Design your data model so atomic operations never cross shards wherever possible. This makes Vitess behave like regular MySQL — and simplifies everything.
In this episode 9 you understood how ACID applies in Vitess: fully within one shard, weaker when crossing shards. You also learned about cross-shard transactions with the 2PC/XA option and its trade-offs, locking and stale reads on read replicas, and best practices for maintaining consistency.
Key takeaways:
In the next episode, episode 10, we handle safe schema changes: schema changes and online migrations — VReplication for data migration, zero-downtime online schema changes, and the vtctlclient workflow. See you there!