Snowflake Transactions for Atomic Publication
How explicit transactions, DDL auto-commit and MERGE semantics affect a publish step that must update facts, history and watermarks together.
SnowflakeAdvanced3 min readUpdated 11 Oct 2026
Why a publish step needs a transaction
A batch publication typically changes several tables: customer history, facts, a batch ledger and watermarks. If it stops halfway, dashboards show partial data and the watermark may claim work that never landed. Wrap the business changes in one explicit transaction:
BEGIN TRANSACTION;
-- 1. idempotency: has this batch already committed?
-- (runner checks batch_ledger and exits with ALREADY_PUBLISHED if so)
-- 2. close changed customer versions, insert new ones
UPDATE dim_customer d SET valid_to = :upper, is_current = FALSE
FROM stg_customers s
WHERE d.customer_id = s.customer_id AND d.is_current AND d.attr_hash <> s.attr_hash;
INSERT INTO dim_customer (...) SELECT ... FROM stg_customers s WHERE ...;
-- 3. facts
MERGE INTO fact_sales t USING stg_sales s
ON t.order_id = s.order_id AND t.line_id = s.line_id
WHEN MATCHED THEN UPDATE SET ...
WHEN NOT MATCHED THEN INSERT (...) VALUES (...);
-- 4. control state
INSERT INTO batch_ledger (batch_id, upper_bound, committed_at) VALUES (:batch, :upper, CURRENT_TIMESTAMP());
UPDATE watermarks SET committed_upper = :upper WHERE pipeline_id = :pipeline;
COMMIT;Gotchas
- DDL auto-commits. A
CREATE TABLEinside your "transaction" commits everything before it. Create staging tables beforeBEGIN. - A matched-row
MERGEupdate is Type 1, not SCD2. History needs a close-and-insert step. - Statement errors do not always roll back automatically. Have your runner issue
ROLLBACKon any failure and verify the session state. - Lost responses happen. If the client times out after sending
COMMIT, check the ledger andQUERY_HISTORYby query ID before retrying — don't blindly resubmit.
What it does not give you
Files written to S3, notifications and BI refreshes are outside the database transaction. This is atomic within Snowflake, not distributed exactly-once.
Finished this note?
