Repository: polarsignals/frostdb
Pull request #609 (2023-12-04 19:46:56)

Deprecate txn metadta
Should also remove the concept of the high watermark and tx pool as it no longer makes sense with the lsm being atomic and no write tearing. 


Patch:
diff --git a/db.go b/db.go
index 067e3c0..8571b63 100644
--- a/db.go
+++ b/db.go
@@ -373,8 +373,7 @@ type DB struct {
 	// Databases monotonically increasing transaction id
 	tx atomic.Uint64
 	// highWatermark maintains the highest consecutively completed txn.
-	highWatermark       atomicTxn
-	txnMetadataProvider func(uint64) []byte
+	highWatermark atomic.Uint64
 
 	// TxPool is a waiting area for finished transactions that haven't been added to the watermark
 	txPool *TxPool
@@ -409,15 +408,6 @@ type DataSink interface {
 
 type DBOption func(*DB) error
 
-// WithUserDefinedTxnMetadataProvider enables the user to provide custom
-// metadata associated with any txn.
-func WithUserDefinedTxnMetadataProvider(f func(tx uint64) []byte) DBOption {
-	return func(db *DB) error {
-		db.txnMetadataProvider = f
-		return nil
-	}
-}
-
 func WithCompactionAfterOpen(compact bool, tableNames []string) DBOption {
 	return func(db *DB) error {
 		db.compactAfterRecovery = compact
@@ -568,7 +558,7 @@ func (s *ColumnStore) DB(ctx context.Context, name string, opts ...DBOption) (*D
 				Name: "frostdb_tx_high_watermark",
 				Help: "The highest transaction number that has been released to be read",
 			}, func() float64 {
-				return float64(db.highWatermark.Load().TxnID)
+				return float64(db.highWatermark.Load())
 			}),
 			snapshotMetrics: newSnapshotMetrics(reg),
 		}
@@ -692,28 +682,28 @@ func (db *DB) recover(ctx context.Context, wal WAL) error {
 		level.Info(db.logger).Log(
 			"msg", "failed to load latest snapshot", "db", db.name, "err", err,
 		)
-		snapshotTx.TxnID = 0
+		snapshotTx = 0
 	}
 	snapshotLogArgs := make([]any, 0)
-	if snapshotTx.TxnID != 0 {
+	if snapshotTx != 0 {
 		snapshotLogArgs = append(
 			snapshotLogArgs,
-			"snapshot_tx", snapshotTx.TxnID,
+			"snapshot_tx", snapshotTx,
 			"snapshot_load_duration", time.Since(snapshotLoadStart),
 		)
-		if err := db.cleanupSnapshotDir(ctx, snapshotTx.TxnID); err != nil {
+		if err := db.cleanupSnapshotDir(ctx, snapshotTx); err != nil {
 			// Truncation is best-effort. If it fails, move on.
 			level.Info(db.logger).Log(
 				"msg", "failed to truncate snapshots not equal to loaded snapshot",
 				"err", err,
-				"snapshot_tx", snapshotTx.TxnID,
+				"snapshot_tx", snapshotTx,
 			)
 		}
-		if err := wal.Truncate(snapshotTx.TxnID); err != nil {
+		if err := wal.Truncate(snapshotTx); err != nil {
 			level.Info(db.logger).Log(
 				"msg", "failed to truncate WAL after loading snapshot",
 				"err", err,
-				"snapshot_tx", snapshotTx.TxnID,
+				"snapshot_tx", snapshotTx,
 			)
 		}
 	}
@@ -721,17 +711,17 @@ func (db *DB) recover(ctx context.Context, wal WAL) error {
 	// persistedTables is a map from a table name to the last transaction
 	// persisted.
 	persistedTables := map[string]uint64{}
-	var lastTx Txn
+	var lastTx uint64
 
 	start := time.Now()
-	if err := wal.Replay(snapshotTx.TxnID, func(tx uint64, record *walpb.Record) error {
+	if err := wal.Replay(snapshotTx, func(tx uint64, record *walpb.Record) error {
 		if err := ctx.Err(); err != nil {
 			return err
 		}
 		switch e := record.Entry.EntryType.(type) {
 		case *walpb.Entry_TableBlockPersisted_:
 			persistedTables[e.TableBlockPersisted.TableName] = tx
-			if tx > snapshotTx.TxnID {
+			if tx > snapshotTx {
 				// The loaded snapshot has data in a table that has been
 				// persisted. Delete all data in this table, since it has
 				// already been persisted.
@@ -765,11 +755,11 @@ func (db *DB) recover(ctx context.Context, wal WAL) error {
 	// Writes are performed concurrently to speed up replay.
 	var writeWg errgroup.Group
 	writeWg.SetLimit(runtime.GOMAXPROCS(0))
-	if err := wal.Replay(snapshotTx.TxnID, func(tx uint64, record *walpb.Record) error {
+	if err := wal.Replay(snapshotTx, func(tx uint64, record *walpb.Record) error {
 		if err := ctx.Err(); err != nil {
 			return err
 		}
-		lastTx = Txn{TxnID: tx, TxnMetadata: record.TxnMetadata}
+		lastTx = tx
 		switch e := record.Entry.EntryType.(type) {
 		case *walpb.Entry_NewTableBlock_:
 			entry := e.NewTableBlock
@@ -930,7 +920,7 @@ func (db *DB) recover(ctx context.Context, wal WAL) error {
 	}
 
 	resetTxn := snapshotTx
-	if lastTx.TxnID > resetTxn.TxnID {
+	if lastTx > resetTxn {
 		resetTxn = lastTx
 	}
 
@@ -960,7 +950,7 @@ func (db *DB) recover(ctx context.Context, wal WAL) error {
 			[]any{
 				"msg", "db recovered",
 				"wal_replay_duration", time.Since(start),
-				"watermark", resetTxn.TxnID,
+				"watermark", resetTxn,
 			},
 			snapshotLogArgs...,
 		)...,
@@ -1178,11 +1168,11 @@ func (db *DB) Table(name string, config *tablepb.TableConfig) (*Table, error) {
 		}
 	}
 
-	tx, _, metadata, commit := db.begin()
+	tx, _, commit := db.begin()
 	defer commit()
 
 	id := generateULID()
-	if err := table.newTableBlock(0, tx, metadata, id); err != nil {
+	if err := table.newTableBlock(0, tx, id); err != nil {
 		return nil, err
 	}
 
@@ -1248,7 +1238,7 @@ func (p *DBTableProvider) GetTable(name string) (logicalplan.TableReader, error)
 
 // beginRead returns the high watermark. Reads can safely access any write that has a lower or equal tx id than the returned number.
 func (db *DB) beginRead() uint64 {
-	return db.highWatermark.Load().TxnID
+	return db.highWatermark.Load()
 }
 
 // begin is an internal function that Tables call to start a transaction for writes.
@@ -1257,16 +1247,11 @@ func (db *DB) beginRead() uint64 {
 //	the write tx id
 //	The current high watermark
 //	A function to complete the transaction
-func (db *DB) begin() (uint64, uint64, []byte, func()) {
-	txnID := db.tx.Add(1)
+func (db *DB) begin() (uint64, uint64, func()) {
+	txn := db.tx.Add(1)
 	watermark := db.highWatermark.Load()
-	var txnMetadata []byte
-	if db.txnMetadataProvider != nil {
-		txnMetadata = db.txnMetadataProvider(txnID)
-	}
-	return txnID, watermark.TxnID, txnMetadata, func() {
-		txn := Txn{TxnID: txnID, TxnMetadata: txnMetadata}
-		if mark := db.highWatermark.Load().TxnID; mark+1 == txnID {
+	return txn, watermark, func() {
+		if mark := db.highWatermark.Load(); mark+1 == txn {
 			// This is the next consecutive transaction; increase the watermark.
 			db.highWatermark.Store(txn)
 		}
@@ -1280,7 +1265,7 @@ func (db *DB) begin() (uint64, uint64, []byte, func()) {
 // Wait makes no differentiation between completed and aborted transactions.
 func (db *DB) Wait(tx uint64) {
 	for {
-		if db.highWatermark.Load().TxnID >= tx {
+		if db.highWatermark.Load() >= tx {
 			return
 		}
 		time.Sleep(10 * time.Millisecond)
@@ -1288,7 +1273,7 @@ func (db *DB) Wait(tx uint64) {
 }
 
 // HighWatermark returns the current high watermark.
-func (db *DB) HighWatermark() Txn {
+func (db *DB) HighWatermark() uint64 {
 	return db.highWatermark.Load()
 }
 
@@ -1297,16 +1282,16 @@ func (db *DB) HighWatermark() Txn {
 // expected transaction will log correctly to the WAL. Note that db.wal is not
 // used since callers might be calling resetToTxn before db.wal has been
 // initialized or might not want the WAL to be reset.
-func (db *DB) resetToTxn(txn Txn, wal WAL) {
-	db.tx.Store(txn.TxnID)
+func (db *DB) resetToTxn(txn uint64, wal WAL) {
+	db.tx.Store(txn)
 	db.highWatermark.Store(txn)
 	if wal != nil {
 		// This call resets the WAL to a zero state so that new records can be
 		// logged.
-		if err := wal.Reset(txn.TxnID + 1); err != nil {
+		if err := wal.Reset(txn + 1); err != nil {
 			level.Warn(db.logger).Log(
 				"msg", "failed to reset WAL when resetting DB to txn",
-				"txnID", txn.TxnID,
+				"txnID", txn,
 				"err", err,
 			)
 		}
diff --git a/gen/proto/go/frostdb/snapshot/v1alpha1/snapshot.pb.go b/gen/proto/go/frostdb/snapshot/v1alpha1/snapshot.pb.go
index b7f2c2e..c79dbcd 100644
--- a/gen/proto/go/frostdb/snapshot/v1alpha1/snapshot.pb.go
+++ b/gen/proto/go/frostdb/snapshot/v1alpha1/snapshot.pb.go
@@ -78,9 +78,6 @@ type FooterData struct {
 	unknownFields protoimpl.UnknownFields
 
 	TableMetadata []*Table `protobuf:"bytes,1,rep,name=table_metadata,json=tableMetadata,proto3" json:"table_metadata,omitempty"`
-	// TxnMetadata is the user-defined metadata associated with the txn at which
-	// this snapshot was performed.
-	TxnMetadata []byte `protobuf:"bytes,2,opt,name=txn_metadata,json=txnMetadata,proto3" json:"txn_metadata,omitempty"`
 }
 
 func (x *FooterData) Reset() {
@@ -122,13 +119,6 @@ func (x *FooterData) GetTableMetadata() []*Table {
 	return nil
 }
 
-func (x *FooterData) GetTxnMetadata() []byte {
-	if x != nil {
-		return x.TxnMetadata
-	}
-	return nil
-}
-
 type Table struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -406,77 +396,75 @@ var file_frostdb_snapshot_v1alpha1_snapshot_proto_rawDesc = []byte{
 	0x74, 0x64, 0x62, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x61,
 	0x6c, 0x70, 0x68, 0x61, 0x31, 0x1a, 0x23, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2f, 0x74,
 	0x61, 0x62, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x63, 0x6f,
-	0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x78, 0x0a, 0x0a, 0x46, 0x6f,
+	0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x55, 0x0a, 0x0a, 0x46, 0x6f,
 	0x6f, 0x74, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x12, 0x47, 0x0a, 0x0e, 0x74, 0x61, 0x62, 0x6c,
 	0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
 	0x32, 0x20, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73,
 	0x68, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x54, 0x61, 0x62,
 	0x6c, 0x65, 0x52, 0x0d, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
-	0x61, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x78, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
-	0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x74, 0x78, 0x6e, 0x4d, 0x65, 0x74, 0x61,
-	0x64, 0x61, 0x74, 0x61, 0x22, 0xdd, 0x02, 0x0a, 0x05, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x12,
-	0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
-	0x6d, 0x65, 0x12, 0x3b, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01,
-	0x28, 0x0b, 0x32, 0x23, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2e, 0x74, 0x61, 0x62,
-	0x6c, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x54, 0x61, 0x62, 0x6c,
-	0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
-	0x4e, 0x0a, 0x0c, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18,
-	0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2e,
-	0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61,
-	0x31, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x6c, 0x6f,
-	0x63, 0x6b, 0x52, 0x0b, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12,
-	0x4d, 0x0a, 0x10, 0x67, 0x72, 0x61, 0x6e, 0x75, 0x6c, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64,
-	0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x66, 0x72, 0x6f, 0x73,
-	0x74, 0x64, 0x62, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x61,
-	0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x72, 0x61, 0x6e, 0x75, 0x6c, 0x65, 0x52, 0x0f, 0x67,
-	0x72, 0x61, 0x6e, 0x75, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x1a, 0x64,
-	0x0a, 0x0a, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x12, 0x0a, 0x04,
-	0x75, 0x6c, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x75, 0x6c, 0x69, 0x64,
-	0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04,
-	0x73, 0x69, 0x7a, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x6d, 0x69, 0x6e, 0x5f, 0x74, 0x78, 0x18, 0x03,
-	0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x6d, 0x69, 0x6e, 0x54, 0x78, 0x12, 0x17, 0x0a, 0x07, 0x70,
-	0x72, 0x65, 0x76, 0x5f, 0x74, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x70, 0x72,
-	0x65, 0x76, 0x54, 0x78, 0x22, 0x4f, 0x0a, 0x07, 0x47, 0x72, 0x61, 0x6e, 0x75, 0x6c, 0x65, 0x12,
-	0x44, 0x0a, 0x0d, 0x70, 0x61, 0x72, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
-	0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62,
+	0x61, 0x22, 0xdd, 0x02, 0x0a, 0x05, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e,
+	0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
+	0x3b, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
+	0x23, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e,
+	0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x6f,
+	0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4e, 0x0a, 0x0c,
+	0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01,
+	0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2e, 0x73, 0x6e, 0x61,
+	0x70, 0x73, 0x68, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x54,
+	0x61, 0x62, 0x6c, 0x65, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52,
+	0x0b, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x4d, 0x0a, 0x10,
+	0x67, 0x72, 0x61, 0x6e, 0x75, 0x6c, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+	0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62,
 	0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
-	0x61, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x74, 0x52, 0x0c, 0x70, 0x61, 0x72, 0x74, 0x4d, 0x65, 0x74,
-	0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x95, 0x02, 0x0a, 0x04, 0x50, 0x61, 0x72, 0x74, 0x12, 0x21,
-	0x0a, 0x0c, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x01,
-	0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x72, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65,
-	0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x6e, 0x64, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18,
-	0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x65, 0x6e, 0x64, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74,
-	0x12, 0x0e, 0x0a, 0x02, 0x74, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x74, 0x78,
-	0x12, 0x29, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6c,
-	0x65, 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x70,
-	0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x44, 0x0a, 0x08, 0x65,
-	0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e,
-	0x66, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74,
-	0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x74, 0x2e, 0x45,
-	0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e,
-	0x67, 0x22, 0x4a, 0x0a, 0x08, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x14, 0x0a,
-	0x10, 0x45, 0x4e, 0x43, 0x4f, 0x44, 0x49, 0x4e, 0x47, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57,
-	0x4e, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x45, 0x4e, 0x43, 0x4f, 0x44, 0x49, 0x4e, 0x47, 0x5f,
-	0x50, 0x41, 0x52, 0x51, 0x55, 0x45, 0x54, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x45, 0x4e, 0x43,
-	0x4f, 0x44, 0x49, 0x4e, 0x47, 0x5f, 0x41, 0x52, 0x52, 0x4f, 0x57, 0x10, 0x02, 0x42, 0x8d, 0x02,
-	0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2e, 0x73, 0x6e,
-	0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42,
-	0x0d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01,
-	0x5a, 0x57, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6f, 0x6c,
-	0x61, 0x72, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x73, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x64,
-	0x62, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x66,
-	0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2f, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x2f,
-	0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f,
-	0x74, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x46, 0x53, 0x58, 0xaa,
-	0x02, 0x19, 0x46, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2e, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68,
-	0x6f, 0x74, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x19, 0x46, 0x72,
-	0x6f, 0x73, 0x74, 0x64, 0x62, 0x5c, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5c, 0x56,
-	0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x25, 0x46, 0x72, 0x6f, 0x73, 0x74, 0x64,
-	0x62, 0x5c, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70,
-	0x68, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea,
-	0x02, 0x1b, 0x46, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x3a, 0x3a, 0x53, 0x6e, 0x61, 0x70, 0x73,
-	0x68, 0x6f, 0x74, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70,
-	0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x61, 0x31, 0x2e, 0x47, 0x72, 0x61, 0x6e, 0x75, 0x6c, 0x65, 0x52, 0x0f, 0x67, 0x72, 0x61, 0x6e,
+	0x75, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x1a, 0x64, 0x0a, 0x0a, 0x54,
+	0x61, 0x62, 0x6c, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x6c, 0x69,
+	0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x75, 0x6c, 0x69, 0x64, 0x12, 0x12, 0x0a,
+	0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a,
+	0x65, 0x12, 0x15, 0x0a, 0x06, 0x6d, 0x69, 0x6e, 0x5f, 0x74, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28,
+	0x04, 0x52, 0x05, 0x6d, 0x69, 0x6e, 0x54, 0x78, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x72, 0x65, 0x76,
+	0x5f, 0x74, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x70, 0x72, 0x65, 0x76, 0x54,
+	0x78, 0x22, 0x4f, 0x0a, 0x07, 0x47, 0x72, 0x61, 0x6e, 0x75, 0x6c, 0x65, 0x12, 0x44, 0x0a, 0x0d,
+	0x70, 0x61, 0x72, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20,
+	0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2e, 0x73, 0x6e,
+	0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e,
+	0x50, 0x61, 0x72, 0x74, 0x52, 0x0c, 0x70, 0x61, 0x72, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61,
+	0x74, 0x61, 0x22, 0x95, 0x02, 0x0a, 0x04, 0x50, 0x61, 0x72, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x73,
+	0x74, 0x61, 0x72, 0x74, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x03, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x72, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x1d,
+	0x0a, 0x0a, 0x65, 0x6e, 0x64, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x03, 0x52, 0x09, 0x65, 0x6e, 0x64, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x0e, 0x0a,
+	0x02, 0x74, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x74, 0x78, 0x12, 0x29, 0x0a,
+	0x10, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6c, 0x65, 0x76, 0x65,
+	0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74,
+	0x69, 0x6f, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x44, 0x0a, 0x08, 0x65, 0x6e, 0x63, 0x6f,
+	0x64, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x66, 0x72, 0x6f,
+	0x73, 0x74, 0x64, 0x62, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x2e, 0x76, 0x31,
+	0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x6f,
+	0x64, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x22, 0x4a,
+	0x0a, 0x08, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x14, 0x0a, 0x10, 0x45, 0x4e,
+	0x43, 0x4f, 0x44, 0x49, 0x4e, 0x47, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00,
+	0x12, 0x14, 0x0a, 0x10, 0x45, 0x4e, 0x43, 0x4f, 0x44, 0x49, 0x4e, 0x47, 0x5f, 0x50, 0x41, 0x52,
+	0x51, 0x55, 0x45, 0x54, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x45, 0x4e, 0x43, 0x4f, 0x44, 0x49,
+	0x4e, 0x47, 0x5f, 0x41, 0x52, 0x52, 0x4f, 0x57, 0x10, 0x02, 0x42, 0x8d, 0x02, 0x0a, 0x1d, 0x63,
+	0x6f, 0x6d, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73,
+	0x68, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x0d, 0x53, 0x6e,
+	0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x57, 0x67,
+	0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6f, 0x6c, 0x61, 0x72, 0x73,
+	0x69, 0x67, 0x6e, 0x61, 0x6c, 0x73, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2f, 0x67,
+	0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x66, 0x72, 0x6f, 0x73,
+	0x74, 0x64, 0x62, 0x2f, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x2f, 0x76, 0x31, 0x61,
+	0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x76, 0x31,
+	0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x46, 0x53, 0x58, 0xaa, 0x02, 0x19, 0x46,
+	0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2e, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x2e,
+	0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x19, 0x46, 0x72, 0x6f, 0x73, 0x74,
+	0x64, 0x62, 0x5c, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5c, 0x56, 0x31, 0x61, 0x6c,
+	0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x25, 0x46, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x5c, 0x53,
+	0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
+	0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x1b, 0x46,
+	0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x3a, 0x3a, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74,
+	0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x33,
 }
 
 var (
diff --git a/gen/proto/go/frostdb/snapshot/v1alpha1/snapshot_vtproto.pb.go b/gen/proto/go/frostdb/snapshot/v1alpha1/snapshot_vtproto.pb.go
index df64865..10fb8df 100644
--- a/gen/proto/go/frostdb/snapshot/v1alpha1/snapshot_vtproto.pb.go
+++ b/gen/proto/go/frostdb/snapshot/v1alpha1/snapshot_vtproto.pb.go
@@ -49,13 +49,6 @@ func (m *FooterData) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
 		i -= len(m.unknownFields)
 		copy(dAtA[i:], m.unknownFields)
 	}
-	if len(m.TxnMetadata) > 0 {
-		i -= len(m.TxnMetadata)
-		copy(dAtA[i:], m.TxnMetadata)
-		i = encodeVarint(dAtA, i, uint64(len(m.TxnMetadata)))
-		i--
-		dAtA[i] = 0x12
-	}
 	if len(m.TableMetadata) > 0 {
 		for iNdEx := len(m.TableMetadata) - 1; iNdEx >= 0; iNdEx-- {
 			size, err := m.TableMetadata[iNdEx].MarshalToSizedBufferVT(dAtA[:i])
@@ -324,10 +317,6 @@ func (m *FooterData) SizeVT() (n int) {
 			n += 1 + l + sov(uint64(l))
 		}
 	}
-	l = len(m.TxnMetadata)
-	if l > 0 {
-		n += 1 + l + sov(uint64(l))
-	}
 	n += len(m.unknownFields)
 	return n
 }
@@ -493,40 +482,6 @@ func (m *FooterData) UnmarshalVT(dAtA []byte) error {
 				return err
 			}
 			iNdEx = postIndex
-		case 2:
-			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field TxnMetadata", wireType)
-			}
-			var byteLen int
-			for shift := uint(0); ; shift += 7 {
-				if shift >= 64 {
-					return ErrIntOverflow
-				}
-				if iNdEx >= l {
-					return io.ErrUnexpectedEOF
-				}
-				b := dAtA[iNdEx]
-				iNdEx++
-				byteLen |= int(b&0x7F) << shift
-				if b < 0x80 {
-					break
-				}
-			}
-			if byteLen < 0 {
-				return ErrInvalidLength
-			}
-			postIndex := iNdEx + byteLen
-			if postIndex < 0 {
-				return ErrInvalidLength
-			}
-			if postIndex > l {
-				return io.ErrUnexpectedEOF
-			}
-			m.TxnMetadata = append(m.TxnMetadata[:0], dAtA[iNdEx:postIndex]...)
-			if m.TxnMetadata == nil {
-				m.TxnMetadata = []byte{}
-			}
-			iNdEx = postIndex
 		default:
 			iNdEx = preIndex
 			skippy, err := skip(dAtA[iNdEx:])
diff --git a/gen/proto/go/frostdb/wal/v1alpha1/wal.pb.go b/gen/proto/go/frostdb/wal/v1alpha1/wal.pb.go
index 85b4997..e6d0de6 100644
--- a/gen/proto/go/frostdb/wal/v1alpha1/wal.pb.go
+++ b/gen/proto/go/frostdb/wal/v1alpha1/wal.pb.go
@@ -30,9 +30,6 @@ type Record struct {
 	// Data of the record. This is intentionally nested so the only thing in
 	// the entry can be a protobuf `oneof` and have forward compatilibity.
 	Entry *Entry `protobuf:"bytes,1,opt,name=entry,proto3" json:"entry,omitempty"`
-	// TxnMetadata is the user-defined metadata associated with the txn at which
-	// this record was logged to the WAL.
-	TxnMetadata []byte `protobuf:"bytes,2,opt,name=txn_metadata,json=txnMetadata,proto3" json:"txn_metadata,omitempty"`
 }
 
 func (x *Record) Reset() {
@@ -74,13 +71,6 @@ func (x *Record) GetEntry() *Entry {
 	return nil
 }
 
-func (x *Record) GetTxnMetadata() []byte {
-	if x != nil {
-		return x.TxnMetadata
-	}
-	return nil
-}
-
 // The data of a WAL Record. This is intentionally separate to allow using the
 // `oneof` feature in a forward-compatible way.
 type Entry struct {
@@ -446,71 +436,68 @@ var file_frostdb_wal_v1alpha1_wal_proto_rawDesc = []byte{
 	0x12, 0x14, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2e, 0x77, 0x61, 0x6c, 0x2e, 0x76, 0x31,
 	0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x1a, 0x23, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2f,
 	0x74, 0x61, 0x62, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x63,
-	0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x5e, 0x0a, 0x06, 0x52,
+	0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x3b, 0x0a, 0x06, 0x52,
 	0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x31, 0x0a, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x01,
 	0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2e, 0x77,
 	0x61, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x72,
-	0x79, 0x52, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x78, 0x6e, 0x5f,
-	0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b,
-	0x74, 0x78, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0xa4, 0x05, 0x0a, 0x05,
-	0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x39, 0x0a, 0x05, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x01,
-	0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2e, 0x77,
-	0x61, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x72,
-	0x79, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x48, 0x00, 0x52, 0x05, 0x77, 0x72, 0x69, 0x74, 0x65,
-	0x12, 0x53, 0x0a, 0x0f, 0x6e, 0x65, 0x77, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x62, 0x6c,
-	0x6f, 0x63, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x66, 0x72, 0x6f, 0x73,
-	0x74, 0x64, 0x62, 0x2e, 0x77, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
-	0x2e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4e, 0x65, 0x77, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x42,
-	0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x0d, 0x6e, 0x65, 0x77, 0x54, 0x61, 0x62, 0x6c, 0x65,
-	0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x65, 0x0a, 0x15, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x62,
-	0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x64, 0x18, 0x03,
-	0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2e, 0x77,
-	0x61, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x72,
-	0x79, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x50, 0x65, 0x72, 0x73,
-	0x69, 0x73, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x13, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x6c,
-	0x6f, 0x63, 0x6b, 0x50, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x64, 0x12, 0x42, 0x0a, 0x08,
-	0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24,
-	0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2e, 0x77, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x61,
-	0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x6e, 0x61, 0x70,
-	0x73, 0x68, 0x6f, 0x74, 0x48, 0x00, 0x52, 0x08, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74,
-	0x1a, 0x50, 0x0a, 0x05, 0x57, 0x72, 0x69, 0x74, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x61, 0x62,
-	0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74,
-	0x61, 0x62, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61,
-	0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05,
-	0x61, 0x72, 0x72, 0x6f, 0x77, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x61, 0x72, 0x72,
-	0x6f, 0x77, 0x1a, 0x92, 0x01, 0x0a, 0x0d, 0x4e, 0x65, 0x77, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x42,
-	0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x61,
-	0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4e,
-	0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x18,
-	0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x64, 0x12, 0x3b,
-	0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23,
-	0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x76,
-	0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x6f, 0x6e,
-	0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4a, 0x04, 0x08, 0x03, 0x10,
-	0x04, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x1a, 0x4f, 0x0a, 0x13, 0x54, 0x61, 0x62, 0x6c, 0x65,
-	0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x50, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x64, 0x12, 0x1d,
-	0x0a, 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a,
-	0x08, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52,
-	0x07, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x64, 0x1a, 0x1a, 0x0a, 0x08, 0x53, 0x6e, 0x61, 0x70,
-	0x73, 0x68, 0x6f, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04,
-	0x52, 0x02, 0x74, 0x78, 0x42, 0x0c, 0x0a, 0x0a, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x74, 0x79,
-	0x70, 0x65, 0x42, 0xe5, 0x01, 0x0a, 0x18, 0x63, 0x6f, 0x6d, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74,
-	0x64, 0x62, 0x2e, 0x77, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42,
-	0x08, 0x57, 0x61, 0x6c, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x4d, 0x67, 0x69, 0x74,
-	0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6f, 0x6c, 0x61, 0x72, 0x73, 0x69, 0x67,
-	0x6e, 0x61, 0x6c, 0x73, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2f, 0x67, 0x65, 0x6e,
-	0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x64,
-	0x62, 0x2f, 0x77, 0x61, 0x6c, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x77,
-	0x61, 0x6c, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x46, 0x57, 0x58,
-	0xaa, 0x02, 0x14, 0x46, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2e, 0x57, 0x61, 0x6c, 0x2e, 0x56,
-	0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x14, 0x46, 0x72, 0x6f, 0x73, 0x74, 0x64,
-	0x62, 0x5c, 0x57, 0x61, 0x6c, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02,
-	0x20, 0x46, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x5c, 0x57, 0x61, 0x6c, 0x5c, 0x56, 0x31, 0x61,
-	0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
-	0x61, 0xea, 0x02, 0x16, 0x46, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x3a, 0x3a, 0x57, 0x61, 0x6c,
-	0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x33,
+	0x79, 0x52, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x22, 0xa4, 0x05, 0x0a, 0x05, 0x45, 0x6e, 0x74,
+	0x72, 0x79, 0x12, 0x39, 0x0a, 0x05, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x0b, 0x32, 0x21, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2e, 0x77, 0x61, 0x6c, 0x2e,
+	0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x57,
+	0x72, 0x69, 0x74, 0x65, 0x48, 0x00, 0x52, 0x05, 0x77, 0x72, 0x69, 0x74, 0x65, 0x12, 0x53, 0x0a,
+	0x0f, 0x6e, 0x65, 0x77, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62,
+	0x2e, 0x77, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x6e,
+	0x74, 0x72, 0x79, 0x2e, 0x4e, 0x65, 0x77, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x6c, 0x6f, 0x63,
+	0x6b, 0x48, 0x00, 0x52, 0x0d, 0x6e, 0x65, 0x77, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x6c, 0x6f,
+	0x63, 0x6b, 0x12, 0x65, 0x0a, 0x15, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x62, 0x6c, 0x6f, 0x63,
+	0x6b, 0x5f, 0x70, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
+	0x0b, 0x32, 0x2f, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2e, 0x77, 0x61, 0x6c, 0x2e,
+	0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x54,
+	0x61, 0x62, 0x6c, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x50, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74,
+	0x65, 0x64, 0x48, 0x00, 0x52, 0x13, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
+	0x50, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x64, 0x12, 0x42, 0x0a, 0x08, 0x73, 0x6e, 0x61,
+	0x70, 0x73, 0x68, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x66, 0x72,
+	0x6f, 0x73, 0x74, 0x64, 0x62, 0x2e, 0x77, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
+	0x61, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f,
+	0x74, 0x48, 0x00, 0x52, 0x08, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x1a, 0x50, 0x0a,
+	0x05, 0x57, 0x72, 0x69, 0x74, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f,
+	0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x61, 0x62, 0x6c,
+	0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x72, 0x72,
+	0x6f, 0x77, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x1a,
+	0x92, 0x01, 0x0a, 0x0d, 0x4e, 0x65, 0x77, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x6c, 0x6f, 0x63,
+	0x6b, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65,
+	0x12, 0x19, 0x0a, 0x08, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x0c, 0x52, 0x07, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x64, 0x12, 0x3b, 0x0a, 0x06, 0x63,
+	0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x66, 0x72,
+	0x6f, 0x73, 0x74, 0x64, 0x62, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c,
+	0x70, 0x68, 0x61, 0x31, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+	0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x4a, 0x04,
+	0x08, 0x04, 0x10, 0x05, 0x1a, 0x4f, 0x0a, 0x13, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x6c, 0x6f,
+	0x63, 0x6b, 0x50, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x74,
+	0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x6c,
+	0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x62, 0x6c,
+	0x6f, 0x63, 0x6b, 0x49, 0x64, 0x1a, 0x1a, 0x0a, 0x08, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f,
+	0x74, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x74,
+	0x78, 0x42, 0x0c, 0x0a, 0x0a, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x42,
+	0xe5, 0x01, 0x0a, 0x18, 0x63, 0x6f, 0x6d, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2e,
+	0x77, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x08, 0x57, 0x61,
+	0x6c, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x4d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
+	0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6f, 0x6c, 0x61, 0x72, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c,
+	0x73, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2f, 0x77,
+	0x61, 0x6c, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x77, 0x61, 0x6c, 0x76,
+	0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x46, 0x57, 0x58, 0xaa, 0x02, 0x14,
+	0x46, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x2e, 0x57, 0x61, 0x6c, 0x2e, 0x56, 0x31, 0x61, 0x6c,
+	0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x14, 0x46, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x5c, 0x57,
+	0x61, 0x6c, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x20, 0x46, 0x72,
+	0x6f, 0x73, 0x74, 0x64, 0x62, 0x5c, 0x57, 0x61, 0x6c, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68,
+	0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02,
+	0x16, 0x46, 0x72, 0x6f, 0x73, 0x74, 0x64, 0x62, 0x3a, 0x3a, 0x57, 0x61, 0x6c, 0x3a, 0x3a, 0x56,
+	0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
diff --git a/gen/proto/go/frostdb/wal/v1alpha1/wal_vtproto.pb.go b/gen/proto/go/frostdb/wal/v1alpha1/wal_vtproto.pb.go
index 6f06de6..d717348 100644
--- a/gen/proto/go/frostdb/wal/v1alpha1/wal_vtproto.pb.go
+++ b/gen/proto/go/frostdb/wal/v1alpha1/wal_vtproto.pb.go
@@ -49,13 +49,6 @@ func (m *Record) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
 		i -= len(m.unknownFields)
 		copy(dAtA[i:], m.unknownFields)
 	}
-	if len(m.TxnMetadata) > 0 {
-		i -= len(m.TxnMetadata)
-		copy(dAtA[i:], m.TxnMetadata)
-		i = encodeVarint(dAtA, i, uint64(len(m.TxnMetadata)))
-		i--
-		dAtA[i] = 0x12
-	}
 	if m.Entry != nil {
 		size, err := m.Entry.MarshalToSizedBufferVT(dAtA[:i])
 		if err != nil {
@@ -407,10 +400,6 @@ func (m *Record) SizeVT() (n int) {
 		l = m.Entry.SizeVT()
 		n += 1 + l + sov(uint64(l))
 	}
-	l = len(m.TxnMetadata)
-	if l > 0 {
-		n += 1 + l + sov(uint64(l))
-	}
 	n += len(m.unknownFields)
 	return n
 }
@@ -622,40 +611,6 @@ func (m *Record) UnmarshalVT(dAtA []byte) error {
 				return err
 			}
 			iNdEx = postIndex
-		case 2:
-			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field TxnMetadata", wireType)
-			}
-			var byteLen int
-			for shift := uint(0); ; shift += 7 {
-				if shift >= 64 {
-					return ErrIntOverflow
-				}
-				if iNdEx >= l {
-					return io.ErrUnexpectedEOF
-				}
-				b := dAtA[iNdEx]
-				iNdEx++
-				byteLen |= int(b&0x7F) << shift
-				if b < 0x80 {
-					break
-				}
-			}
-			if byteLen < 0 {
-				return ErrInvalidLength
-			}
-			postIndex := iNdEx + byteLen
-			if postIndex < 0 {
-				return ErrInvalidLength
-			}
-			if postIndex > l {
-				return io.ErrUnexpectedEOF
-			}
-			m.TxnMetadata = append(m.TxnMetadata[:0], dAtA[iNdEx:postIndex]...)
-			if m.TxnMetadata == nil {
-				m.TxnMetadata = []byte{}
-			}
-			iNdEx = postIndex
 		default:
 			iNdEx = preIndex
 			skippy, err := skip(dAtA[iNdEx:])
diff --git a/proto/frostdb/snapshot/v1alpha1/snapshot.proto b/proto/frostdb/snapshot/v1alpha1/snapshot.proto
index b20a216..d38585e 100644
--- a/proto/frostdb/snapshot/v1alpha1/snapshot.proto
+++ b/proto/frostdb/snapshot/v1alpha1/snapshot.proto
@@ -8,9 +8,6 @@ import "frostdb/table/v1alpha1/config.proto";
 // data about the rest of the file.
 message FooterData {
   repeated Table table_metadata = 1;
-  // TxnMetadata is the user-defined metadata associated with the txn at which
-  // this snapshot was performed.
-  bytes txn_metadata = 2;
 }
 
 message Table {
diff --git a/proto/frostdb/wal/v1alpha1/wal.proto b/proto/frostdb/wal/v1alpha1/wal.proto
index 6d6bcc2..a743aad 100644
--- a/proto/frostdb/wal/v1alpha1/wal.proto
+++ b/proto/frostdb/wal/v1alpha1/wal.proto
@@ -9,9 +9,6 @@ message Record {
   // Data of the record. This is intentionally nested so the only thing in
   // the entry can be a protobuf `oneof` and have forward compatilibity.
   Entry entry = 1;
-  // TxnMetadata is the user-defined metadata associated with the txn at which
-  // this record was logged to the WAL.
-  bytes txn_metadata = 2;
 }
 
 // The data of a WAL Record. This is intentionally separate to allow using the
diff --git a/snapshot.go b/snapshot.go
index a5ae91c..7be6270 100644
--- a/snapshot.go
+++ b/snapshot.go
@@ -129,7 +129,7 @@ func (db *DB) snapshot(ctx context.Context, async bool, onSuccess func()) {
 		return
 	}
 
-	tx, _, metadata, commit := db.begin()
+	tx, _, commit := db.begin()
 	level.Debug(db.logger).Log(
 		"msg", "starting a new snapshot",
 		"tx", tx,
@@ -150,7 +150,6 @@ func (db *DB) snapshot(ctx context.Context, async bool, onSuccess func()) {
 					Entry: &walpb.Entry{
 						EntryType: &walpb.Entry_Snapshot_{Snapshot: &walpb.Entry_Snapshot{Tx: tx}},
 					},
-					TxnMetadata: metadata,
 				},
 			); err != nil {
 				level.Error(db.logger).Log(
@@ -175,9 +174,9 @@ func (db *DB) snapshot(ctx context.Context, async bool, onSuccess func()) {
 	}
 
 	if async {
-		go doSnapshot(db.snapshotWriter(tx, metadata))
+		go doSnapshot(db.snapshotWriter(tx))
 	} else {
-		doSnapshot(db.offlineSnapshotWriter(tx, metadata))
+		doSnapshot(db.offlineSnapshotWriter(tx))
 	}
 }
 
@@ -239,14 +238,14 @@ func (db *DB) snapshotAtTX(ctx context.Context, tx uint64, writeSnapshot func(co
 
 // loadLatestSnapshot loads the latest snapshot (i.e. the snapshot with the
 // highest txn) from the snapshots dir into the database.
-func (db *DB) loadLatestSnapshot(ctx context.Context) (Txn, error) {
+func (db *DB) loadLatestSnapshot(ctx context.Context) (uint64, error) {
 	return db.loadLatestSnapshotFromDir(ctx, db.snapshotsDir())
 }
 
-func (db *DB) loadLatestSnapshotFromDir(ctx context.Context, dir string) (Txn, error) {
+func (db *DB) loadLatestSnapshotFromDir(ctx context.Context, dir string) (uint64, error) {
 	var (
 		lastErr   error
-		loadedTxn Txn
+		loadedTxn uint64
 	)
 	// No error should be returned from snapshotsDo.
 	_ = db.snapshotsDo(ctx, dir, func(parsedTx uint64, entry os.DirEntry) (bool, error) {
@@ -278,24 +277,23 @@ func (db *DB) loadLatestSnapshotFromDir(ctx context.Context, dir string) (Txn, e
 		}
 		return false, nil
 	})
-	if loadedTxn.TxnID != 0 {
+	if loadedTxn != 0 {
 		// Successfully loaded a snapshot.
 		return loadedTxn, nil
 	}
 
 	errString := "no valid snapshots found"
 	if lastErr != nil {
-		return Txn{}, fmt.Errorf("%s: lastErr: %w", errString, lastErr)
+		return 0, fmt.Errorf("%s: lastErr: %w", errString, lastErr)
 	}
-	return Txn{}, fmt.Errorf("%s", errString)
+	return 0, fmt.Errorf("%s", errString)
 }
 
-func LoadSnapshot(ctx context.Context, db *DB, tx uint64, r io.ReaderAt, size int64, truncateWAL bool) (Txn, error) {
-	txnMetadata, err := loadSnapshot(ctx, db, r, size)
-	if err != nil {
-		return Txn{}, err
+func LoadSnapshot(ctx context.Context, db *DB, tx uint64, r io.ReaderAt, size int64, truncateWAL bool) (uint64, error) {
+	if err := loadSnapshot(ctx, db, r, size); err != nil {
+		return 0, err
 	}
-	watermark := Txn{TxnID: tx, TxnMetadata: txnMetadata}
+	watermark := tx
 	var wal WAL
 	if truncateWAL {
 		wal = db.wal
@@ -369,20 +367,20 @@ func (w *offsetWriter) checksum() uint32 {
 	return w.runningChecksum.Sum32()
 }
 
-func (db *DB) snapshotWriter(tx uint64, txnMetadata []byte) func(context.Context, io.Writer) error {
+func (db *DB) snapshotWriter(tx uint64) func(context.Context, io.Writer) error {
 	return func(ctx context.Context, w io.Writer) error {
-		return WriteSnapshot(ctx, tx, txnMetadata, db, w, false)
+		return WriteSnapshot(ctx, tx, db, w, false)
 	}
 }
 
 // offlineSnapshotWriter is used when a database is closing after all the tables have closed.
-func (db *DB) offlineSnapshotWriter(tx uint64, txnMetadata []byte) func(context.Context, io.Writer) error {
+func (db *DB) offlineSnapshotWriter(tx uint64) func(context.Context, io.Writer) error {
 	return func(ctx context.Context, w io.Writer) error {
-		return WriteSnapshot(ctx, tx, txnMetadata, db, w, true)
+		return WriteSnapshot(ctx, tx, db, w, true)
 	}
 }
 
-func WriteSnapshot(ctx context.Context, _ uint64, txnMetadata []byte, db *DB, w io.Writer, offline bool) error {
+func WriteSnapshot(ctx context.Context, _ uint64, db *DB, w io.Writer, offline bool) error {
 	offW := newOffsetWriter(w)
 	w = offW
 	var tables []*Table
@@ -396,7 +394,7 @@ func WriteSnapshot(ctx context.Context, _ uint64, txnMetadata []byte, db *DB, w
 		return err
 	}
 
-	metadata := &snapshotpb.FooterData{TxnMetadata: txnMetadata}
+	metadata := &snapshotpb.FooterData{}
 	for _, t := range tables {
 		if err := func() error {
 			// Obtain a write block to prevent racing with
@@ -561,10 +559,10 @@ func readFooter(r io.ReaderAt, size int64) (*snapshotpb.FooterData, error) {
 // loadSnapshot loads a snapshot from the given io.ReaderAt and returns the
 // txnMetadata (if any) the snapshot was created with and an error if any
 // occurred.
-func loadSnapshot(ctx context.Context, db *DB, r io.ReaderAt, size int64) ([]byte, error) {
+func loadSnapshot(ctx context.Context, db *DB, r io.ReaderAt, size int64) error {
 	footer, err := readFooter(r, size)
 	if err != nil {
-		return nil, err
+		return err
 	}
 
 	for i, tableMeta := range footer.TableMetadata {
@@ -672,11 +670,11 @@ func loadSnapshot(ctx context.Context, db *DB, r io.ReaderAt, size int64) ([]byt
 				delete(db.tables, cleanupTable.Name)
 			}
 			db.mtx.Unlock()
-			return nil, err
+			return err
 		}
 	}
 
-	return footer.TxnMetadata, nil
+	return nil
 }
 
 // cleanupSnapshotDir should be called with a tx at which the caller is certain
diff --git a/table.go b/table.go
index 21b977e..49a8deb 100644
--- a/table.go
+++ b/table.go
@@ -174,7 +174,7 @@ type Table struct {
 type WAL interface {
 	Close() error
 	Log(tx uint64, record *walpb.Record) error
-	LogRecord(tx uint64, txnMetadata []byte, table string, record arrow.Record) error
+	LogRecord(tx uint64, table string, record arrow.Record) error
 	// Replay replays WAL records from the given first index. If firstIndex is
 	// 0, the first index read from the WAL is used (i.e. given a truncation,
 	// using 0 is still valid). If the given firstIndex is less than the WAL's
@@ -340,7 +340,7 @@ func newTable(
 	return t, nil
 }
 
-func (t *Table) newTableBlock(prevTx, tx uint64, txnMetadata []byte, id ulid.ULID) error {
+func (t *Table) newTableBlock(prevTx, tx uint64, id ulid.ULID) error {
 	b, err := id.MarshalBinary()
 	if err != nil {
 		return err
@@ -356,7 +356,6 @@ func (t *Table) newTableBlock(prevTx, tx uint64, txnMetadata []byte, id ulid.ULI
 				},
 			},
 		},
-		TxnMetadata: txnMetadata,
 	}); err != nil {
 		return err
 	}
@@ -401,7 +400,7 @@ func (t *Table) writeBlock(block *TableBlock, skipPersist, snapshotDB bool) {
 		return
 	}
 
-	tx, _, metadata, commit := t.db.begin()
+	tx, _, commit := t.db.begin()
 	defer commit()
 
 	buf, err := block.ulid.MarshalBinary()
@@ -419,7 +418,6 @@ func (t *Table) writeBlock(block *TableBlock, skipPersist, snapshotDB bool) {
 				},
 			},
 		},
-		TxnMetadata: metadata,
 	}); err != nil {
 		level.Error(t.logger).Log("msg", "failed to record block persistence in WAL", "err", err)
 		return
@@ -463,7 +461,7 @@ func (t *Table) writeBlock(block *TableBlock, skipPersist, snapshotDB bool) {
 			// TODO(asubiotto): Eventually we should register a cancel function
 			// that is called with a grace period on db.Close.
 			ctx := context.Background()
-			if err := t.db.snapshotAtTX(ctx, tx, t.db.snapshotWriter(tx, metadata)); err != nil {
+			if err := t.db.snapshotAtTX(ctx, tx, t.db.snapshotWriter(tx)); err != nil {
 				level.Error(t.logger).Log(
 					"msg", "failed to write snapshot on block rotation",
 					"err", err,
@@ -494,7 +492,7 @@ func (t *Table) RotateBlock(_ context.Context, block *TableBlock, skipPersist bo
 		level.Debug(t.logger).Log("msg", "done rotating block")
 	}()
 
-	tx, _, metadata, commit := t.db.begin()
+	tx, _, commit := t.db.begin()
 	defer commit()
 
 	id := generateULID()
@@ -502,7 +500,7 @@ func (t *Table) RotateBlock(_ context.Context, block *TableBlock, skipPersist bo
 		runtime.Gosched()
 		id = generateULID()
 	}
-	if err := t.newTableBlock(t.active.minTx, tx, metadata, id); err != nil {
+	if err := t.newTableBlock(t.active.minTx, tx, id); err != nil {
 		return err
 	}
 	t.metrics.blockRotated.Inc()
@@ -574,10 +572,10 @@ func (t *Table) InsertRecord(ctx context.Context, record arrow.Record) (uint64,
 	}
 	defer finish()
 
-	tx, _, metadata, commit := t.db.begin()
+	tx, _, commit := t.db.begin()
 	defer commit()
 
-	if err := t.wal.LogRecord(tx, metadata, t.name, record); err != nil {
+	if err := t.wal.LogRecord(tx, t.name, record); err != nil {
 		return tx, fmt.Errorf("append to log: %w", err)
 	}
 
diff --git a/tx_list.go b/tx_list.go
index 1947474..2590bee 100644
--- a/tx_list.go
+++ b/tx_list.go
@@ -8,7 +8,7 @@ import (
 type TxNode struct {
 	next     *atomic.Pointer[TxNode]
 	original *atomic.Pointer[TxNode]
-	tx       Txn
+	tx       uint64
 }
 
 type TxPool struct {
@@ -52,7 +52,7 @@ type TxPool struct {
 //
 // TxPool is a sorted lockless linked-list described in
 // https://timharris.uk/papers/2001-disc.pdf
-func NewTxPool(watermark *atomicTxn) *TxPool {
+func NewTxPool(watermark *atomic.Uint64) *TxPool {
 	tail := &TxNode{
 		next:     &atomic.Pointer[TxNode]{},
 		original: &atomic.Pointer[TxNode]{},
@@ -79,7 +79,7 @@ func NewTxPool(watermark *atomicTxn) *TxPool {
 }
 
 // Insert performs an insertion sort of the given tx.
-func (l *TxPool) Insert(tx Txn) {
+func (l *TxPool) Insert(tx uint64) {
 	n := &TxNode{
 		tx:       tx,
 		next:     &atomic.Pointer[TxNode]{},
@@ -89,7 +89,7 @@ func (l *TxPool) Insert(tx Txn) {
 	tryInsert := func() bool {
 		prev := l.head.Load()
 		for node := l.head.Load().next.Load(); node != nil; node = getUnmarked(node) {
-			if node.tx.TxnID == 0 { // end of list
+			if node.tx == 0 { // end of list
 				return l.insert(n, prev, node)
 			}
 
@@ -99,7 +99,7 @@ func (l *TxPool) Insert(tx Txn) {
 				return false
 			}
 
-			if node.tx.TxnID > tx.TxnID {
+			if node.tx > tx {
 				return l.insert(n, prev, node)
 			}
 			prev = node
@@ -125,8 +125,8 @@ func (l *TxPool) insert(node, prev, next *TxNode) bool {
 	return success
 }
 
-func (l *TxPool) Iterate(iterate func(txn Txn) bool) {
-	for node := l.head.Load().next.Load(); node.tx.TxnID != 0; node = getUnmarked(node) {
+func (l *TxPool) Iterate(iterate func(txn uint64) bool) {
+	for node := l.head.Load().next.Load(); node.tx != 0; node = getUnmarked(node) {
 		if isMarked(node) == nil && !iterate(node.tx) {
 			return
 		}
@@ -134,8 +134,8 @@ func (l *TxPool) Iterate(iterate func(txn Txn) bool) {
 }
 
 // delete iterates over the list and deletes until the delete function returns false.
-func (l *TxPool) delete(deleteFunc func(txn Txn) bool) {
-	for node := l.head.Load().next.Load(); node.tx.TxnID != 0; node = getUnmarked(node) {
+func (l *TxPool) delete(deleteFunc func(txn uint64) bool) {
+	for node := l.head.Load().next.Load(); node.tx != 0; node = getUnmarked(node) {
 		if !deleteFunc(node.tx) {
 			return
 		}
@@ -184,19 +184,19 @@ func getUnmarked(node *TxNode) *TxNode {
 
 // cleaner sweeps the pool periodically, and bubbles up the given watermark.
 // this function does not return.
-func (l *TxPool) cleaner(ctx context.Context, watermark *atomicTxn) {
+func (l *TxPool) cleaner(ctx context.Context, watermark *atomic.Uint64) {
 	for {
 		select {
 		case <-ctx.Done():
 			return
 		case <-l.drain:
-			l.delete(func(txn Txn) bool {
-				mark := watermark.Load().TxnID
+			l.delete(func(txn uint64) bool {
+				mark := watermark.Load()
 				switch {
-				case mark+1 == txn.TxnID:
+				case mark+1 == txn:
 					watermark.Store(txn)
 					return true // return true to indicate that this node should be removed from the tx list.
-				case mark >= txn.TxnID:
+				case mark >= txn:
 					return true
 				default:
 					return false
diff --git a/txn.go b/txn.go
deleted file mode 100644
index 87d8dfa..0000000
--- a/txn.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package frostdb
-
-import (
-	"sync/atomic"
-)
-
-type Txn struct {
-	TxnID       uint64
-	TxnMetadata []byte
-}
-
-type atomicTxn struct {
-	atomic.Pointer[Txn]
-}
-
-func (t *atomicTxn) Load() Txn {
-	txn := t.Pointer.Load()
-	if txn == nil {
-		return Txn{}
-	}
-	return *txn
-}
-
-func (t *atomicTxn) Store(txn Txn) {
-	t.Pointer.Store(&txn)
-}
diff --git a/wal/wal.go b/wal/wal.go
index f14f90f..0e46382 100644
--- a/wal/wal.go
+++ b/wal/wal.go
@@ -38,7 +38,7 @@ func (w *NopWAL) Replay(_ uint64, _ ReplayHandlerFunc) error {
 	return nil
 }
 
-func (w *NopWAL) LogRecord(_ uint64, _ []byte, _ string, _ arrow.Record) error {
+func (w *NopWAL) LogRecord(_ uint64, _ string, _ arrow.Record) error {
 	return nil
 }
 
@@ -461,7 +461,7 @@ func (w *FileWAL) writeRecord(buf *bytes.Buffer, record arrow.Record) error {
 	return writer.Write(record)
 }
 
-func (w *FileWAL) LogRecord(tx uint64, txnMetadata []byte, table string, record arrow.Record) error {
+func (w *FileWAL) LogRecord(tx uint64, table string, record arrow.Record) error {
 	w.protected.Lock()
 	nextTx := w.protected.nextTx
 	w.protected.Unlock()
@@ -491,7 +491,6 @@ func (w *FileWAL) LogRecord(tx uint64, txnMetadata []byte, table string, record
 				},
 			},
 		},
-		TxnMetadata: txnMetadata,
 	}
 
 	r := w.logRequestPool.Get().(*logRequest)


Test patch:
diff --git a/bench_test.go b/bench_test.go
index 77d1c48..a10f6c3 100644
--- a/bench_test.go
+++ b/bench_test.go
@@ -409,7 +409,7 @@ func BenchmarkSnapshot(b *testing.B) {
 	bytesWritten := 0
 	for i := 0; i < b.N; i++ {
 		wc := &writeCounter{Writer: io.Discard}
-		require.NoError(b, WriteSnapshot(ctx, db.HighWatermark().TxnID, nil, db, wc, false))
+		require.NoError(b, WriteSnapshot(ctx, db.HighWatermark(), db, wc, false))
 		bytesWritten += wc.count
 	}
 	b.ReportMetric(float64(bytesWritten)/float64(b.N), "size/op")
diff --git a/db_test.go b/db_test.go
index e0ceac1..2f3ebc4 100644
--- a/db_test.go
+++ b/db_test.go
@@ -1413,9 +1413,6 @@ func TestDBRecover(t *testing.T) {
 		dbAndTableName = "test"
 		numInserts     = 3
 	)
-	txnMetadataProvider := func(tx uint64) []byte {
-		return []byte(fmt.Sprintf("%d-metadata", tx))
-	}
 	setup := func(t *testing.T, blockRotation bool, options ...Option) string {
 		dir := t.TempDir()
 		c, err := New(
@@ -1435,7 +1432,7 @@ func TestDBRecover(t *testing.T) {
 		require.NoError(t, err)
 		defer c.Close()
 
-		db, err := c.DB(ctx, dbAndTableName, WithUserDefinedTxnMetadataProvider(txnMetadataProvider))
+		db, err := c.DB(ctx, dbAndTableName)
 		require.NoError(t, err)
 		schema := dynparquet.SampleDefinition()
 		table, err := db.Table(dbAndTableName, NewTableConfig(schema))
@@ -1501,10 +1498,6 @@ func TestDBRecover(t *testing.T) {
 		db, err := c.DB(ctx, dbAndTableName)
 		require.NoError(t, err)
 
-		// Verify metadata is stored.
-		watermark := db.highWatermark.Load()
-		require.Equal(t, txnMetadataProvider(watermark.TxnID), watermark.TxnMetadata)
-
 		engine := query.NewEngine(memory.DefaultAllocator, db.TableProvider())
 		nrows := 0
 		require.NoError(t, engine.ScanTable(dbAndTableName).
diff --git a/snapshot_test.go b/snapshot_test.go
index ff31475..2928182 100644
--- a/snapshot_test.go
+++ b/snapshot_test.go
@@ -2,7 +2,6 @@ package frostdb
 
 import (
 	"context"
-	"fmt"
 	"math"
 	"os"
 	"strconv"
@@ -66,16 +65,16 @@ func TestSnapshot(t *testing.T) {
 
 		// Complete a txn so that the snapshot is created at txn 1, snapshots at
 		// txn 0 are considered empty so ignored.
-		_, _, metadata, commit := db.begin()
+		_, _, commit := db.begin()
 		commit()
 
 		tx := db.highWatermark.Load()
-		require.NoError(t, db.snapshotAtTX(ctx, tx.TxnID, db.snapshotWriter(tx.TxnID, metadata)))
+		require.NoError(t, db.snapshotAtTX(ctx, tx, db.snapshotWriter(tx)))
 
-		txBefore := db.highWatermark.Load().TxnID
+		txBefore := db.highWatermark.Load()
 		tx, err = db.loadLatestSnapshot(ctx)
 		require.NoError(t, err)
-		require.Equal(t, txBefore, tx.TxnID)
+		require.Equal(t, txBefore, tx)
 	})
 
 	t.Run("WithData", func(t *testing.T) {
@@ -110,11 +109,11 @@ func TestSnapshot(t *testing.T) {
 		_, err = db.Table("empty", config)
 		require.NoError(t, err)
 
-		highWatermark := db.highWatermark.Load().TxnID
+		highWatermark := db.highWatermark.Load()
 
 		// Insert a sample that should not be snapshot.
 		insertSampleRecords(ctx, t, table, 10)
-		require.NoError(t, db.snapshotAtTX(ctx, highWatermark, db.snapshotWriter(highWatermark, nil)))
+		require.NoError(t, db.snapshotAtTX(ctx, highWatermark, db.snapshotWriter(highWatermark)))
 
 		// Create another db and verify.
 		snapshotDB, err := c.DB(ctx, "testsnapshot")
@@ -123,8 +122,8 @@ func TestSnapshot(t *testing.T) {
 		// Load the other db's latest snapshot.
 		tx, err := snapshotDB.loadLatestSnapshotFromDir(ctx, db.snapshotsDir())
 		require.NoError(t, err)
-		require.Equal(t, highWatermark, tx.TxnID)
-		require.Equal(t, highWatermark, snapshotDB.highWatermark.Load().TxnID)
+		require.Equal(t, highWatermark, tx)
+		require.Equal(t, highWatermark, snapshotDB.highWatermark.Load())
 
 		require.Equal(t, len(db.tables), len(snapshotDB.tables))
 
@@ -189,7 +188,7 @@ func TestSnapshot(t *testing.T) {
 		table, err := db.Table(tableName, config)
 		require.NoError(t, err)
 
-		highWatermarkAtStart := db.highWatermark.Load().TxnID
+		highWatermarkAtStart := db.highWatermark.Load()
 		shouldStartSnapshotChan := make(chan struct{})
 		var errg errgroup.Group
 		errg.Go(func() error {
@@ -214,7 +213,7 @@ func TestSnapshot(t *testing.T) {
 		snapshotDB, err := c.DB(ctx, "testsnapshot")
 		require.NoError(t, err)
 		tx := db.highWatermark.Load()
-		require.NoError(t, db.snapshotAtTX(ctx, tx.TxnID, db.snapshotWriter(tx.TxnID, nil)))
+		require.NoError(t, db.snapshotAtTX(ctx, tx, db.snapshotWriter(tx)))
 		snapshotTx, err := snapshotDB.loadLatestSnapshotFromDir(ctx, db.snapshotsDir())
 		require.NoError(t, err)
 		require.NoError(
@@ -225,7 +224,7 @@ func TestSnapshot(t *testing.T) {
 				[]logicalplan.Expr{logicalplan.Max(logicalplan.Col("timestamp"))}, nil,
 			).Execute(ctx, func(ctx context.Context, r arrow.Record) error {
 				require.Equal(
-					t, int(snapshotTx.TxnID-highWatermarkAtStart), int(r.Column(0).(*array.Int64).Int64Values()[0]),
+					t, int(snapshotTx-highWatermarkAtStart), int(r.Column(0).(*array.Int64).Int64Values()[0]),
 				)
 				return nil
 			}),
@@ -246,9 +245,6 @@ func TestSnapshotWithWAL(t *testing.T) {
 		snapshotTx          uint64
 		firstWriteTimestamp int64
 	)
-	txnMetadataProvider := func(tx uint64) []byte {
-		return []byte(fmt.Sprintf("%d-metadata", tx))
-	}
 	func() {
 		c, err := New(
 			WithWAL(),
@@ -258,7 +254,7 @@ func TestSnapshotWithWAL(t *testing.T) {
 		require.NoError(t, err)
 		defer c.Close()
 
-		db, err := c.DB(ctx, dbAndTableName, WithUserDefinedTxnMetadataProvider(txnMetadataProvider))
+		db, err := c.DB(ctx, dbAndTableName)
 		require.NoError(t, err)
 
 		schema := dynparquet.SampleDefinition()
@@ -314,10 +310,6 @@ func TestSnapshotWithWAL(t *testing.T) {
 	verifyDB, err := verifyC.DB(ctx, dbAndTableName)
 	require.NoError(t, err)
 
-	// Verify txn metadata is persisted.
-	watermark := verifyDB.highWatermark.Load()
-	require.Equal(t, txnMetadataProvider(watermark.TxnID), watermark.TxnMetadata)
-
 	// Truncate all entries from the WAL up to but not including the second
 	// insert.
 	require.NoError(t, verifyDB.wal.Truncate(snapshotTx+1))
diff --git a/table_test.go b/table_test.go
index dc1e9c5..2e43ca0 100644
--- a/table_test.go
+++ b/table_test.go
@@ -354,7 +354,7 @@ func Test_Table_ReadIsolation(t *testing.T) {
 
 	// Now we cheat and reset our tx and watermark
 	table.db.tx.Store(2)
-	table.db.highWatermark.Store(Txn{TxnID: 2})
+	table.db.highWatermark.Store(2)
 
 	pool := memory.NewGoAllocator()
 
@@ -378,13 +378,13 @@ func Test_Table_ReadIsolation(t *testing.T) {
 
 	// Now set the tx back to what it was, and perform the same read, we should return all 4 rows
 	table.db.tx.Store(3)
-	table.db.highWatermark.Store(Txn{TxnID: 3})
+	table.db.highWatermark.Store(3)
 
 	err = table.View(ctx, func(ctx context.Context, tx uint64) error {
 		rows := int64(0)
 		err = table.Iterator(
 			ctx,
-			table.db.highWatermark.Load().TxnID,
+			table.db.highWatermark.Load(),
 			pool,
 			[]logicalplan.Callback{func(ctx context.Context, ar arrow.Record) error {
 				rows += ar.NumRows()
diff --git a/tx_list_test.go b/tx_list_test.go
index 0a31961..8fc44d6 100644
--- a/tx_list_test.go
+++ b/tx_list_test.go
@@ -34,17 +34,17 @@ func Test_TXList_Mark(t *testing.T) {
 }
 
 func Test_TXList_Basic(t *testing.T) {
-	wm := atomicTxn{}
-	wm.Store(Txn{TxnID: 1}) // set the watermark so that the sweeper won't remove any of our txs
+	wm := atomic.Uint64{}
+	wm.Store(1) // set the watermark so that the sweeper won't remove any of our txs
 	p := NewTxPool(&wm)
 	txs := []uint64{9, 8, 7, 6, 4, 5, 3, 10}
 	for _, tx := range txs {
-		p.Insert(Txn{TxnID: tx})
+		p.Insert(tx)
 	}
 
 	found := make(Uint64Slice, 0, len(txs))
-	p.Iterate(func(tx Txn) bool {
-		found = append(found, tx.TxnID)
+	p.Iterate(func(tx uint64) bool {
+		found = append(found, tx)
 		return true
 	})
 
@@ -54,7 +54,7 @@ func Test_TXList_Basic(t *testing.T) {
 }
 
 func Test_TXList_Async(t *testing.T) {
-	wm := atomicTxn{}
+	wm := atomic.Uint64{}
 	p := NewTxPool(&wm)
 
 	tx := &atomic.Uint64{}
@@ -69,7 +69,7 @@ func Test_TXList_Async(t *testing.T) {
 		go func() {
 			defer wg.Done()
 			for j := 0; j < n; j++ {
-				p.Insert(Txn{TxnID: tx.Add(1)})
+				p.Insert(tx.Add(1))
 			}
 		}()
 	}
@@ -77,24 +77,24 @@ func Test_TXList_Async(t *testing.T) {
 	wg.Wait()
 
 	found := make(Uint64Slice, 0, writers*n)
-	p.Iterate(func(tx Txn) bool {
-		found = append(found, tx.TxnID)
+	p.Iterate(func(tx uint64) bool {
+		found = append(found, tx)
 		return true
 	})
 	require.True(t, sort.IsSorted(found))
 	require.Equal(t, n*writers, len(found))
 
-	p.Insert(Txn{TxnID: 1}) // insert the missing tx to drain the pool
+	p.Insert(1) // insert the missing tx to drain the pool
 
-	for v := wm.Load().TxnID; v < tx.Load(); v = wm.Load().TxnID {
+	for v := wm.Load(); v < tx.Load(); v = wm.Load() {
 		// Satisfy linter with statement.
 		continue
 	}
-	require.Equal(t, tx.Load(), wm.Load().TxnID)
+	require.Equal(t, tx.Load(), wm.Load())
 
 	// Verify the pool is empty
 	foundtx := false
-	p.Iterate(func(tx Txn) bool {
+	p.Iterate(func(tx uint64) bool {
 		foundtx = true
 		return true
 	})
@@ -128,7 +128,7 @@ func Benchmark_TXList_InsertAndDrain(b *testing.B) {
 
 	for name, benchmark := range benchmarks {
 		b.Run(name, func(b *testing.B) {
-			wm := atomicTxn{}
+			wm := atomic.Uint64{}
 			p := NewTxPool(&wm)
 			tx := &atomic.Uint64{}
 			wg := &sync.WaitGroup{}
@@ -138,7 +138,7 @@ func Benchmark_TXList_InsertAndDrain(b *testing.B) {
 					go func() {
 						defer wg.Done()
 						for j := 0; j < benchmark.values; j++ {
-							p.Insert(Txn{TxnID: tx.Add(1)})
+							p.Insert(tx.Add(1))
 						}
 					}()
 				}
@@ -146,11 +146,11 @@ func Benchmark_TXList_InsertAndDrain(b *testing.B) {
 				wg.Wait()
 
 				// Wait for the sweeper to drain
-				for v := wm.Load().TxnID; v < tx.Load(); v = wm.Load().TxnID {
+				for v := wm.Load(); v < tx.Load(); v = wm.Load() {
 					// Satisfy linter with statement.
 					continue
 				}
-				require.Equal(b, tx.Load(), wm.Load().TxnID)
+				require.Equal(b, tx.Load(), wm.Load())
 			}
 			p.Stop()
 		})