Seata Distributed Transactions: AT/TCC/SAGA Selection, Internals & Production Pitfalls

This comprehensive guide covers Seata's four transaction modes (AT, TCC, SAGA, XA) with deep internals, production configuration, code examples, nine critical pitfalls with solutions, a real-world failure postmortem, and an architectural decision framework for microservice data consistency.

Internet Backend Architecture Stack
Internet Backend Architecture Stack
Internet Backend Architecture Stack
Seata Distributed Transactions: AT/TCC/SAGA Selection, Internals & Production Pitfalls

Why Microservices Need Distributed Transactions

In a monolith, a single database and local ACID transactions guarantee all-or-nothing commits. Microservices split domains into separate services and databases (e.g., Order, Inventory, Account, Marketing). A synchronous call chain like create order → deduct inventory → deduct balance can leave the system in a half-committed state if the last step fails, causing permanent dirty data.

Seata's Four Transaction Modes: Comparison & Selection

Seata provides XA, AT, TCC, and SAGA. The article presents a production-grade selection matrix:

AT

Core Principle: Two-phase commit + undo_log snapshots for auto rollback

Code Intrusion: Very low (annotation only)

Performance Overhead: 5%-10%

Consistency Level: Eventual (weak)

Production Scenarios: 90% ordinary business, short synchronous chains

TCC

Core Principle: Manual Try/Confirm/Cancel compensation

Code Intrusion: Very high (full manual coding)

Performance Overhead: 15%-25%

Consistency Level: Strong

Production Scenarios: Funds, accounts, inventory, trading core paths

SAGA

Core Principle: Forward execution + reverse compensation, long transactions split into segments

Code Intrusion: Medium

Performance Overhead: Lower

Consistency Level: Eventual

Production Scenarios: Long-running flows, minute-level transactions, tickets, approvals

XA

Core Principle: Database-native two-phase commit

Code Intrusion: Low

Performance Overhead: Very high

Consistency Level: Strong

Production Scenarios: Basically abandoned in production

Architect Selection Rules

Ordinary business, short sync chain, high dev efficiency → AT

Trading, funds, balance, inventory — zero dirty data tolerance → TCC

Long processes, approvals, cross-service ultra-long chains → SAGA

XA → discard (lock contention, extremely low throughput)

AT Mode Deep Dive

Core Idea

Phase 1: execute business SQL, capture before/after snapshots, store in local undo_log table, commit local transaction. Phase 2: if all branches succeed, TC sends global commit → delete undo_log; if any branch fails/times out, TC sends global rollback → read before-image from undo_log and reverse-apply to restore data.

Phase 1 Steps

Intercept SQL, query DB before update → record Before snapshot

Execute business Insert/Update/Delete

Query latest data → record After snapshot

Write both snapshots to local undo_log table

Commit local DB transaction

Key point: Phase 1 already persists business data; it is not a prepare-only phase.

Why AT Is Fast & Non-Intrusive

SQL interception auto-generates snapshots — zero business code changes

Phase 1 commits local transaction immediately — no long lock holding

Phase 2 only deletes logs or restores data — extremely fast

Production-Grade AT Setup (Seata 1.7.0)

1. Create undo_log Table (every participating DB)

CREATE TABLE `undo_log` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `branch_id` bigint NOT NULL COMMENT 'branch transaction ID',
  `xid` varchar(128) NOT NULL COMMENT 'global transaction ID',
  `context` varchar(128) NOT NULL COMMENT 'context',
  `rollback_info` longblob NOT NULL COMMENT 'rollback info',
  `log_status` int NOT NULL COMMENT 'log status 0 normal 1 deleted',
  `log_created` datetime NOT NULL,
  `log_modified` datetime NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Seata transaction rollback log table';

2. Add Dependency

<dependency>
  <groupId>io.seata</groupId>
  <artifactId>seata-spring-boot-starter</artifactId>
  <version>1.7.0</version>
</dependency>

3. Production YAML (Nacos Registry)

seata:
  application:
    name: seata-server
  registry:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      namespace: public
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
  transaction:
    global-timeout: 60000
    default-mode: AT
  client:
    undo:
      log-serialization: jackson
      clean-period: 86400000

4. Core Business Code

@Service
public class OrderServiceImpl implements OrderService {
  @Resource private OrderMapper orderMapper;
  @Resource private StockFeignClient stockFeignClient;
  @Resource private AccountFeignClient accountFeignClient;

  @Override
  @GlobalTransactional(rollbackFor = Exception.class)
  public void createOrder(OrderCreateDTO dto) {
    // 1. Local order creation
    Order order = new Order();
    order.setOrderNo(UUID.randomUUID().toString());
    order.setUserId(dto.getUserId());
    order.setAmount(dto.getAmount());
    order.setStatus(1);
    orderMapper.insert(order);

    // 2. Remote inventory deduction
    stockFeignClient.deductStock(dto.getSkuId(), dto.getNum());

    // 3. Remote balance deduction (simulate exception to trigger rollback)
    accountFeignClient.deductBalance(dto.getUserId(), dto.getAmount());
  }
}

Adding @GlobalTransactional automatically enlists the entire cross-service chain into a distributed transaction.

Nine Production Pitfalls & Fixes

Complex SQL / batch updates / multi-table joins unsupported — AT parses SQL for snapshots; complex statements break parsing. Fix: split into simple single-table statements.

Spring @Transactional nested inside @GlobalTransactional — overwrites Seata context, disabling distributed transaction. Fix: only @GlobalTransactional on outer method; forbid @Transactional inside.

Async threads lose XID context — thread pools don't inherit parent XID, branches fall outside global transaction. Fix: manually propagate XID to child threads.

Global timeout causes hanging transactions — long chains or network jitter trigger TC rollback while local business continues, reversing data. Fix: increase timeout per chain length; add timeout monitoring alerts.

Retries without idempotency cause duplicate orders/payments — Seata retries on timeout; non-idempotent endpoints double-charge. Fix: enforce idempotency on all distributed transaction endpoints via unique business keys.

undo_log table grows unbounded — millions of rows slow snapshot queries and stress DB. Fix: enable scheduled cleanup (e.g., delete completed logs older than 7 days).

Read replicas cause snapshot inconsistency — stale reads from replicas produce mismatched before/after images, rollback fails. Fix: force reads to primary within transaction.

Non-transactional methods intercepted / empty rollback — methods without DB ops generate empty snapshots, corrupting state. Fix: exclude non-DB methods from interception.

XID mismatch across versions/environments — different Seata versions or deployments generate incompatible XIDs, branches can't join global transaction. Fix: unify Seata version and XID generation rules across all environments.

TCC Mode for Strong Consistency

AT provides eventual consistency with a brief inconsistency window — unacceptable for funds, inventory, core trading. TCC enforces strong consistency via three manual phases:

Try : validate params, lock resources, freeze balance/inventory

Confirm : actually deduct, confirm transaction

Cancel : release locks, unfreeze, restore inventory, refund balance

Advantages: full manual control eliminates inconsistency window; no snapshot dependency avoids AT rollback failures; financial-grade zero-risk. Drawback: high code intrusion, large dev effort, must handle idempotency, anti-hanging, empty rollback manually — only for core paths.

SAGA Mode for Long-Running Flows

Minute-level processes, multi-node chains, approvals, async flows — AT/TCC suffer from timeouts and resource locking. SAGA splits a long transaction into a sequence of local transactions:

Each step executes forward; on success, proceed to next.

On any failure, invoke corresponding compensating operations in reverse order.

Benefits: no long locks, no blocking, fits ultra-long business chains.

Real-World Failure Postmortem

Symptom

Intermittent (3-5 orders/week): order created, inventory deducted, balance deduction failed → data inconsistency.

Root Cause Analysis

Account service timeout triggered global rollback.

Order and Inventory services had already committed local transactions in Phase 1.

Order rolled back correctly; Inventory rollback failed because complex batch SQL prevented snapshot parsing .

Resolution

Refactor inventory batch updates into single-row updates.

Increase interface timeouts and global transaction timeout.

Enforce idempotency on all transaction endpoints; add reconciliation batch job as safety net.

Result: distributed transaction inconsistencies reduced to zero.

Microservice Transaction Architecture Closure

Async / MQ decoupled scenarios → Local Message Table (lightweight, stable, zero ops cost).

Ordinary synchronous short chains → Seata AT (high dev efficiency, good performance).

Funds, inventory, core trading → Seata TCC (strong consistency guarantee).

Long processes, approvals, tickets → Seata SAGA (fits long transactions).

XA → completely abandoned in production.

All distributed transaction endpoints: idempotency is baseline, monitoring is assurance, reconciliation is last line of defense .

There is no silver bullet for distributed transactions; scenario matching, rational selection, and pitfall avoidance are the core of architectural stability.
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

microservicesIdempotencydistributed transactionsundo_logSeatatwo-phase commitAT modeSAGA modeTCC modeXA modeproduction pitfallscompensation transactions
Internet Backend Architecture Stack
Written by

Internet Backend Architecture Stack

Over ten years of hands-on Java backend architecture experience, focusing on sharing mainstream internet technologies such as Java backend, microservices, distributed systems, high concurrency, performance optimization, and source code analysis. Building a platform for Java technologists to exchange and grow, collaborating with peers to advance together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.