diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go
index a8e89a03408ec2501f12449637cfee6a094f6915..cc856603e3b95d70edb66dabcdf8901107101181 100644
--- a/cmd/geth/chaincmd.go
+++ b/cmd/geth/chaincmd.go
@@ -413,7 +413,7 @@ func copyDb(ctx *cli.Context) error {
 	if syncMode == downloader.FastSync {
 		//syncBloom = trie.NewSyncBloom(uint64(ctx.GlobalInt(utils.CacheFlag.Name)/2), chainDb)
 	}
-	dl := downloader.New(0, chainDb, syncBloom, new(event.TypeMux), chain, nil, nil, true)
+	dl := downloader.New(0, chainDb, syncBloom, new(event.TypeMux), chain, nil, nil, ethdb.DefaultStorageMode)
 
 	// Create a source peer to satisfy downloader requests from
 	db, err := ethdb.NewBoltDatabase(ctx.Args().First())
diff --git a/cmd/hack/hack.go b/cmd/hack/hack.go
index dc8c5dc5c8732f73138ac1d250cafe5a7eb873b8..59dd11fff63adbe8c359514ab7a86bce51aa86f3 100644
--- a/cmd/hack/hack.go
+++ b/cmd/hack/hack.go
@@ -2431,7 +2431,7 @@ func testStage4(chaindata string, block uint64) error {
 	ch := make(chan struct{})
 	stageState := &stagedsync.StageState{Stage: stages.Execution, BlockNumber: stage4progress}
 	blockchain, _ := core.NewBlockChain(db, nil, params.MainnetChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
-	if err = stagedsync.SpawnExecuteBlocksStage(stageState, db, blockchain, block, ch, nil); err != nil {
+	if err = stagedsync.SpawnExecuteBlocksStage(stageState, db, blockchain, block, ch, nil, false); err != nil {
 		return err
 	}
 	return nil
diff --git a/cmd/restapi/apis/retrace_tx_api.go b/cmd/restapi/apis/retrace_tx_api.go
index d27a6cc4cc1d971807f8851fba1334a57af17a45..5be72d94d429e737f0581e19594deab941bb624d 100644
--- a/cmd/restapi/apis/retrace_tx_api.go
+++ b/cmd/restapi/apis/retrace_tx_api.go
@@ -127,7 +127,7 @@ func runBlock(ibs *state.IntraBlockState, txnWriter state.StateWriter, blockWrit
 
 	ctx := chainConfig.WithEIPsFlags(context.Background(), header.Number)
 	if err := ibs.CommitBlock(ctx, blockWriter); err != nil {
-		return fmt.Errorf("commiting block %d failed: %v", block.NumberU64(), err)
+		return fmt.Errorf("committing block %d failed: %v", block.NumberU64(), err)
 	}
 	return nil
 }
diff --git a/cmd/state/stateless/stateless.go b/cmd/state/stateless/stateless.go
index 5c5cd292eea9a949156c645c68a3630d4f47b6ef..03e0ddf6c6a533b07352f8c585698dc97d2e7569 100644
--- a/cmd/state/stateless/stateless.go
+++ b/cmd/state/stateless/stateless.go
@@ -460,7 +460,7 @@ func Stateless(
 		blockWriter := tds.DbStateWriter()
 		err = statedb.CommitBlock(ctx, blockWriter)
 		if err != nil {
-			fmt.Printf("Commiting block %d failed: %v", blockNum, err)
+			fmt.Printf("Committing block %d failed: %v", blockNum, err)
 			return
 		}
 		if writeHistory {
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index a60b09bf16903f1bed648a30bf6e1bfd07e87283..9fb73b096c714b51345dcc0f17e2b3f19c1b426f 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -439,7 +439,7 @@ var (
 * p - write preimages to the DB
 * r - write receipts to the DB
 * t - write tx lookup index to the DB`,
-		Value: eth.DefaultStorageMode.ToString(),
+		Value: ethdb.DefaultStorageMode.ToString(),
 	}
 	ArchiveSyncInterval = cli.IntFlag{
 		Name:  "archive-sync-interval",
@@ -1554,7 +1554,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
 
 	cfg.EnableDebugProtocol = ctx.GlobalBool(DebugProtocolFlag.Name)
 
-	mode, err := eth.StorageModeFromString(ctx.GlobalString(StorageModeFlag.Name))
+	mode, err := ethdb.StorageModeFromString(ctx.GlobalString(StorageModeFlag.Name))
 	if err != nil {
 		Fatalf(fmt.Sprintf("error while parsing mode: %v", err))
 	}
diff --git a/common/dbutils/bucket.go b/common/dbutils/bucket.go
index 1501089e753a130bb9d0f7123627aaac41d669a1..7af73b231027fbadf289bd59c1323653ceee6a36 100644
--- a/common/dbutils/bucket.go
+++ b/common/dbutils/bucket.go
@@ -142,8 +142,6 @@ var (
 	StorageModeTxIndex = []byte("smTxIndex")
 	//StorageModePreImages - does node save hash to value mapping
 	StorageModePreImages = []byte("smPreImages")
-	//StorageModeThinHistory - does thin history mode enabled
-	StorageModeThinHistory = []byte("smThinHistory")
 	//StorageModeIntermediateTrieHash - does IntermediateTrieHash feature enabled
 	StorageModeIntermediateTrieHash = []byte("smIntermediateTrieHash")
 
@@ -192,7 +190,6 @@ var Buckets = [][]byte{
 	StorageModeReceipts,
 	StorageModeTxIndex,
 	StorageModePreImages,
-	StorageModeThinHistory,
 	CliqueBucket,
 	SyncStageProgress,
 	SyncStageUnwind,
diff --git a/core/blockchain.go b/core/blockchain.go
index 60b35e191cdb801fc51ce0c7c29458854a6615ae..1caebae78c5256afe4bc2cc182fed0bfa4303b33 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -2474,9 +2474,9 @@ func (bc *BlockChain) waitJobs() {
 	bc.quitMu.Unlock()
 }
 
-// ExecuteBlockEuphemerally runs a block from provided stateReader and
+// ExecuteBlockEphemerally runs a block from provided stateReader and
 // writes the result to the provided stateWriter
-func ExecuteBlockEuphemerally(
+func ExecuteBlockEphemerally(
 	chainConfig *params.ChainConfig,
 	vmConfig *vm.Config,
 	chainContext ChainContext,
@@ -2485,7 +2485,7 @@ func ExecuteBlockEuphemerally(
 	stateReader state.StateReader,
 	stateWriter state.WriterWithChangeSets,
 	dests vm.Cache,
-) error {
+) (types.Receipts, error) {
 	ibs := state.New(stateReader)
 	header := block.Header()
 	var receipts types.Receipts
@@ -2500,7 +2500,7 @@ func ExecuteBlockEuphemerally(
 		ibs.Prepare(tx.Hash(), block.Hash(), i)
 		receipt, err := ApplyTransaction(chainConfig, chainContext, nil, gp, ibs, noop, header, tx, usedGas, *vmConfig, dests)
 		if err != nil {
-			return fmt.Errorf("tx %x failed: %v", tx.Hash(), err)
+			return nil, fmt.Errorf("tx %x failed: %v", tx.Hash(), err)
 		}
 		receipts = append(receipts, receipt)
 	}
@@ -2508,23 +2508,23 @@ func ExecuteBlockEuphemerally(
 	if chainConfig.IsByzantium(header.Number) {
 		receiptSha := types.DeriveSha(receipts)
 		if receiptSha != block.Header().ReceiptHash {
-			return fmt.Errorf("mismatched receipt headers for block %d", block.NumberU64())
+			return nil, fmt.Errorf("mismatched receipt headers for block %d", block.NumberU64())
 		}
 	}
 
 	// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
 	if _, err := engine.FinalizeAndAssemble(chainConfig, header, ibs, block.Transactions(), block.Uncles(), receipts); err != nil {
-		return fmt.Errorf("finalize of block %d failed: %v", block.NumberU64(), err)
+		return nil, fmt.Errorf("finalize of block %d failed: %v", block.NumberU64(), err)
 	}
 
 	ctx := chainConfig.WithEIPsFlags(context.Background(), header.Number)
 	if err := ibs.CommitBlock(ctx, stateWriter); err != nil {
-		return fmt.Errorf("commiting block %d failed: %v", block.NumberU64(), err)
+		return nil, fmt.Errorf("committing block %d failed: %v", block.NumberU64(), err)
 	}
 
 	if err := stateWriter.WriteChangeSets(); err != nil {
-		return fmt.Errorf("writing changesets for block %d failed: %v", block.NumberU64(), err)
+		return nil, fmt.Errorf("writing changesets for block %d failed: %v", block.NumberU64(), err)
 	}
 
-	return nil
+	return receipts, nil
 }
diff --git a/core/state/database.go b/core/state/database.go
index 2c223db69730a60e70b67c661f5109bfc2ce4869..323713abbf2c6484b7173afde712cef59064bbe6 100644
--- a/core/state/database.go
+++ b/core/state/database.go
@@ -1292,12 +1292,12 @@ func (tds *TrieDbState) TrieStateWriter() *TrieStateWriter {
 
 // DbStateWriter creates a writer that is designed to write changes into the database batch
 func (tds *TrieDbState) DbStateWriter() *DbStateWriter {
-	return &DbStateWriter{blockNr: tds.blockNr, stateDb: tds.db, changeDb: tds.db, pw: tds.pw, csw: NewChangeSetWriter()}
+	return &DbStateWriter{blockNr: tds.blockNr, db: tds.db, pw: tds.pw, csw: NewChangeSetWriter()}
 }
 
 // DbStateWriter creates a writer that is designed to write changes into the database batch
 func (tds *TrieDbState) PlainStateWriter() *PlainStateWriter {
-	return NewPlainStateWriter(tds.db, tds.db, tds.blockNr)
+	return NewPlainStateWriter(tds.db, tds.blockNr)
 }
 
 func (tsw *TrieStateWriter) UpdateAccountData(_ context.Context, address common.Address, original, account *accounts.Account) error {
diff --git a/core/state/db_state_writer.go b/core/state/db_state_writer.go
index c32fa6279493a5d604b3854d1d2629c74fc15b50..3e393b0f5c8d97c318e7472c0b4a0ee5fbc2d754 100644
--- a/core/state/db_state_writer.go
+++ b/core/state/db_state_writer.go
@@ -19,26 +19,24 @@ import (
 
 var _ WriterWithChangeSets = (*DbStateWriter)(nil)
 
-func NewDbStateWriter(stateDb, changeDb ethdb.Database, blockNr uint64) *DbStateWriter {
+func NewDbStateWriter(db ethdb.Database, blockNr uint64) *DbStateWriter {
 	return &DbStateWriter{
-		stateDb:        stateDb,
-		changeDb:       changeDb,
-		blockNr:        blockNr,
-		pw:             &PreimageWriter{db: stateDb, savePreimages: false},
-		csw:            NewChangeSetWriter(),
+		db:      db,
+		blockNr: blockNr,
+		pw:      &PreimageWriter{db: db, savePreimages: false},
+		csw:     NewChangeSetWriter(),
 	}
 }
 
 type DbStateWriter struct {
-	stateDb        ethdb.Database
-	changeDb       ethdb.Database
-	pw             *PreimageWriter
-	blockNr        uint64
-	csw            *ChangeSetWriter
-	accountCache   *fastcache.Cache
-	storageCache   *fastcache.Cache
-	codeCache      *fastcache.Cache
-	codeSizeCache  *fastcache.Cache
+	db            ethdb.Database
+	pw            *PreimageWriter
+	blockNr       uint64
+	csw           *ChangeSetWriter
+	accountCache  *fastcache.Cache
+	storageCache  *fastcache.Cache
+	codeCache     *fastcache.Cache
+	codeSizeCache *fastcache.Cache
 }
 
 func (dsw *DbStateWriter) SetAccountCache(accountCache *fastcache.Cache) {
@@ -86,7 +84,7 @@ func (dsw *DbStateWriter) UpdateAccountData(ctx context.Context, address common.
 	}
 	value := make([]byte, account.EncodingLengthForStorage())
 	account.EncodeForStorage(value)
-	if err := dsw.stateDb.Put(dbutils.CurrentStateBucket, addrHash[:], value); err != nil {
+	if err := dsw.db.Put(dbutils.CurrentStateBucket, addrHash[:], value); err != nil {
 		return err
 	}
 	if dsw.accountCache != nil {
@@ -103,13 +101,13 @@ func (dsw *DbStateWriter) DeleteAccount(ctx context.Context, address common.Addr
 	if err != nil {
 		return err
 	}
-	if err := rawdb.DeleteAccount(dsw.stateDb, addrHash); err != nil {
+	if err := rawdb.DeleteAccount(dsw.db, addrHash); err != nil {
 		return err
 	}
 	if original.Incarnation > 0 {
 		var b [8]byte
 		binary.BigEndian.PutUint64(b[:], original.Incarnation)
-		if err := dsw.stateDb.Put(dbutils.IncarnationMapBucket, address[:], b[:]); err != nil {
+		if err := dsw.db.Put(dbutils.IncarnationMapBucket, address[:], b[:]); err != nil {
 			return err
 		}
 	}
@@ -132,7 +130,7 @@ func (dsw *DbStateWriter) UpdateAccountCode(address common.Address, incarnation
 		return err
 	}
 	//save contract code mapping
-	if err := dsw.stateDb.Put(dbutils.CodeBucket, codeHash[:], code); err != nil {
+	if err := dsw.db.Put(dbutils.CodeBucket, codeHash[:], code); err != nil {
 		return err
 	}
 	addrHash, err := common.HashData(address.Bytes())
@@ -140,7 +138,7 @@ func (dsw *DbStateWriter) UpdateAccountCode(address common.Address, incarnation
 		return err
 	}
 	//save contract to codeHash mapping
-	if err := dsw.stateDb.Put(dbutils.ContractCodeBucket, dbutils.GenerateStoragePrefix(addrHash[:], incarnation), codeHash[:]); err != nil {
+	if err := dsw.db.Put(dbutils.ContractCodeBucket, dbutils.GenerateStoragePrefix(addrHash[:], incarnation), codeHash[:]); err != nil {
 		return err
 	}
 	if dsw.codeCache != nil {
@@ -181,16 +179,16 @@ func (dsw *DbStateWriter) WriteAccountStorage(ctx context.Context, address commo
 		dsw.storageCache.Set(compositeKey, v)
 	}
 	if len(v) == 0 {
-		return dsw.stateDb.Delete(dbutils.CurrentStateBucket, compositeKey)
+		return dsw.db.Delete(dbutils.CurrentStateBucket, compositeKey)
 	}
-	return dsw.stateDb.Put(dbutils.CurrentStateBucket, compositeKey, v)
+	return dsw.db.Put(dbutils.CurrentStateBucket, compositeKey, v)
 }
 
 func (dsw *DbStateWriter) CreateContract(address common.Address) error {
 	if err := dsw.csw.CreateContract(address); err != nil {
 		return err
 	}
-	if err := dsw.stateDb.Delete(dbutils.IncarnationMapBucket, address[:]); err != nil {
+	if err := dsw.db.Delete(dbutils.IncarnationMapBucket, address[:]); err != nil {
 		return err
 	}
 	return nil
@@ -209,7 +207,7 @@ func (dsw *DbStateWriter) WriteChangeSets() error {
 		return err
 	}
 	key := dbutils.EncodeTimestamp(dsw.blockNr)
-	if err = dsw.changeDb.Put(dbutils.AccountChangeSetBucket, key, accountSerialised); err != nil {
+	if err = dsw.db.Put(dbutils.AccountChangeSetBucket, key, accountSerialised); err != nil {
 		return err
 	}
 	storageChanges, err := dsw.csw.GetStorageChanges()
@@ -222,7 +220,7 @@ func (dsw *DbStateWriter) WriteChangeSets() error {
 		if err != nil {
 			return err
 		}
-		if err = dsw.changeDb.Put(dbutils.StorageChangeSetBucket, key, storageSerialized); err != nil {
+		if err = dsw.db.Put(dbutils.StorageChangeSetBucket, key, storageSerialized); err != nil {
 			return err
 		}
 	}
@@ -234,7 +232,7 @@ func (dsw *DbStateWriter) WriteHistory() error {
 	if err != nil {
 		return err
 	}
-	err = writeIndex(dsw.blockNr, accountChanges, dbutils.AccountsHistoryBucket, dsw.changeDb)
+	err = writeIndex(dsw.blockNr, accountChanges, dbutils.AccountsHistoryBucket, dsw.db)
 	if err != nil {
 		return err
 	}
@@ -243,7 +241,7 @@ func (dsw *DbStateWriter) WriteHistory() error {
 	if err != nil {
 		return err
 	}
-	err = writeIndex(dsw.blockNr, storageChanges, dbutils.StorageHistoryBucket, dsw.changeDb)
+	err = writeIndex(dsw.blockNr, storageChanges, dbutils.StorageHistoryBucket, dsw.db)
 	if err != nil {
 		return err
 	}
diff --git a/core/state/plain_state_writer.go b/core/state/plain_state_writer.go
index 4ca0e317ac19007e63088ff6092c58e36b474e59..17d774f10e50370a79739f6f4a7c1f69d68fae3a 100644
--- a/core/state/plain_state_writer.go
+++ b/core/state/plain_state_writer.go
@@ -17,22 +17,20 @@ import (
 var _ WriterWithChangeSets = (*PlainStateWriter)(nil)
 
 type PlainStateWriter struct {
-	stateDb                ethdb.Database
-	changeDb               ethdb.Database
-	csw                    *ChangeSetWriter
-	blockNumber            uint64
-	accountCache           *fastcache.Cache
-	storageCache           *fastcache.Cache
-	codeCache              *fastcache.Cache
-	codeSizeCache          *fastcache.Cache
+	db            ethdb.Database
+	csw           *ChangeSetWriter
+	blockNumber   uint64
+	accountCache  *fastcache.Cache
+	storageCache  *fastcache.Cache
+	codeCache     *fastcache.Cache
+	codeSizeCache *fastcache.Cache
 }
 
-func NewPlainStateWriter(stateDb, changeDb ethdb.Database, blockNumber uint64) *PlainStateWriter {
+func NewPlainStateWriter(db ethdb.Database, blockNumber uint64) *PlainStateWriter {
 	return &PlainStateWriter{
-		stateDb:                stateDb,
-		changeDb:               changeDb,
-		csw:                    NewChangeSetWriterPlain(),
-		blockNumber:            blockNumber,
+		db:          db,
+		csw:         NewChangeSetWriterPlain(),
+		blockNumber: blockNumber,
 	}
 }
 
@@ -61,7 +59,7 @@ func (w *PlainStateWriter) UpdateAccountData(ctx context.Context, address common
 	if w.accountCache != nil {
 		w.accountCache.Set(address[:], value)
 	}
-	return w.stateDb.Put(dbutils.PlainStateBucket, address[:], value)
+	return w.db.Put(dbutils.PlainStateBucket, address[:], value)
 }
 
 func (w *PlainStateWriter) UpdateAccountCode(address common.Address, incarnation uint64, codeHash common.Hash, code []byte) error {
@@ -80,10 +78,10 @@ func (w *PlainStateWriter) UpdateAccountCode(address common.Address, incarnation
 		binary.BigEndian.PutUint32(b[:], uint32(len(code)))
 		w.codeSizeCache.Set(address[:], b[:])
 	}
-	if err := w.stateDb.Put(dbutils.CodeBucket, codeHash[:], code); err != nil {
+	if err := w.db.Put(dbutils.CodeBucket, codeHash[:], code); err != nil {
 		return err
 	}
-	return w.stateDb.Put(dbutils.PlainContractCodeBucket, dbutils.PlainGenerateStoragePrefix(address[:], incarnation), codeHash[:])
+	return w.db.Put(dbutils.PlainContractCodeBucket, dbutils.PlainGenerateStoragePrefix(address[:], incarnation), codeHash[:])
 }
 
 func (w *PlainStateWriter) DeleteAccount(ctx context.Context, address common.Address, original *accounts.Account) error {
@@ -101,13 +99,13 @@ func (w *PlainStateWriter) DeleteAccount(ctx context.Context, address common.Add
 		binary.BigEndian.PutUint32(b[:], 0)
 		w.codeSizeCache.Set(address[:], b[:])
 	}
-	if err := w.stateDb.Delete(dbutils.PlainStateBucket, address[:]); err != nil {
+	if err := w.db.Delete(dbutils.PlainStateBucket, address[:]); err != nil {
 		return err
 	}
 	if original.Incarnation > 0 {
 		var b [8]byte
 		binary.BigEndian.PutUint64(b[:], original.Incarnation)
-		if err := w.stateDb.Put(dbutils.IncarnationMapBucket, address[:], b[:]); err != nil {
+		if err := w.db.Put(dbutils.IncarnationMapBucket, address[:], b[:]); err != nil {
 			return err
 		}
 	}
@@ -128,16 +126,16 @@ func (w *PlainStateWriter) WriteAccountStorage(ctx context.Context, address comm
 		w.storageCache.Set(compositeKey, v)
 	}
 	if len(v) == 0 {
-		return w.stateDb.Delete(dbutils.PlainStateBucket, compositeKey)
+		return w.db.Delete(dbutils.PlainStateBucket, compositeKey)
 	}
-	return w.stateDb.Put(dbutils.PlainStateBucket, compositeKey, v)
+	return w.db.Put(dbutils.PlainStateBucket, compositeKey, v)
 }
 
 func (w *PlainStateWriter) CreateContract(address common.Address) error {
 	if err := w.csw.CreateContract(address); err != nil {
 		return err
 	}
-	if err := w.stateDb.Delete(dbutils.IncarnationMapBucket, address[:]); err != nil {
+	if err := w.db.Delete(dbutils.IncarnationMapBucket, address[:]); err != nil {
 		return err
 	}
 	return nil
@@ -154,7 +152,7 @@ func (w *PlainStateWriter) WriteChangeSets() error {
 		return err
 	}
 	key := dbutils.EncodeTimestamp(w.blockNumber)
-	if err = w.changeDb.Put(dbutils.PlainAccountChangeSetBucket, key, accountSerialised); err != nil {
+	if err = w.db.Put(dbutils.PlainAccountChangeSetBucket, key, accountSerialised); err != nil {
 		return err
 	}
 	storageChanges, err := w.csw.GetStorageChanges()
@@ -167,7 +165,7 @@ func (w *PlainStateWriter) WriteChangeSets() error {
 		if err != nil {
 			return err
 		}
-		if err = w.changeDb.Put(dbutils.PlainStorageChangeSetBucket, key, storageSerialized); err != nil {
+		if err = w.db.Put(dbutils.PlainStorageChangeSetBucket, key, storageSerialized); err != nil {
 			return err
 		}
 	}
@@ -179,7 +177,7 @@ func (w *PlainStateWriter) WriteHistory() error {
 	if err != nil {
 		return err
 	}
-	err = writeIndex(w.blockNumber, accountChanges, dbutils.AccountsHistoryBucket, w.changeDb)
+	err = writeIndex(w.blockNumber, accountChanges, dbutils.AccountsHistoryBucket, w.db)
 	if err != nil {
 		return err
 	}
@@ -188,7 +186,7 @@ func (w *PlainStateWriter) WriteHistory() error {
 	if err != nil {
 		return err
 	}
-	err = writeIndex(w.blockNumber, storageChanges, dbutils.StorageHistoryBucket, w.changeDb)
+	err = writeIndex(w.blockNumber, storageChanges, dbutils.StorageHistoryBucket, w.db)
 	if err != nil {
 		return err
 	}
diff --git a/eth/backend.go b/eth/backend.go
index 1ca9742ec261b2771134763cf82fa91cebd185cf..5c0c1e0962728283880b73935557707fb22834ab 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -29,7 +29,6 @@ import (
 	"github.com/ledgerwatch/turbo-geth/accounts"
 	"github.com/ledgerwatch/turbo-geth/accounts/abi/bind"
 	"github.com/ledgerwatch/turbo-geth/common"
-	"github.com/ledgerwatch/turbo-geth/common/dbutils"
 	"github.com/ledgerwatch/turbo-geth/common/hexutil"
 	"github.com/ledgerwatch/turbo-geth/consensus"
 	"github.com/ledgerwatch/turbo-geth/consensus/clique"
@@ -194,12 +193,12 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
 		}
 	}
 
-	err = setStorageModeIfNotExist(chainDb, config.StorageMode)
+	err = ethdb.SetStorageModeIfNotExist(chainDb, config.StorageMode)
 	if err != nil {
 		return nil, err
 	}
 
-	sm, err := GetStorageModeFromDB(chainDb)
+	sm, err := ethdb.GetStorageModeFromDB(chainDb)
 	if err != nil {
 		return nil, err
 	}
@@ -662,86 +661,3 @@ func (s *Ethereum) Stop() error {
 	s.eventMux.Stop()
 	return nil
 }
-
-func setStorageModeIfNotExist(db ethdb.Database, sm StorageMode) error {
-	var (
-		err error
-	)
-	err = setModeOnEmpty(db, dbutils.StorageModeHistory, sm.History)
-	if err != nil {
-		return err
-	}
-
-	err = setModeOnEmpty(db, dbutils.StorageModePreImages, sm.Preimages)
-	if err != nil {
-		return err
-	}
-
-	err = setModeOnEmpty(db, dbutils.StorageModeReceipts, sm.Receipts)
-	if err != nil {
-		return err
-	}
-
-	err = setModeOnEmpty(db, dbutils.StorageModeTxIndex, sm.TxIndex)
-	if err != nil {
-		return err
-	}
-
-	return nil
-}
-
-func setModeOnEmpty(db ethdb.Database, key []byte, currentValue bool) error {
-	_, err := db.Get(dbutils.DatabaseInfoBucket, key)
-	if err != nil && err != ethdb.ErrKeyNotFound {
-		return err
-	}
-	if err == ethdb.ErrKeyNotFound {
-		val := []byte{}
-		if currentValue {
-			val = []byte{1}
-		}
-		if err = db.Put(dbutils.DatabaseInfoBucket, key, val); err != nil {
-			return err
-		}
-	}
-
-	return nil
-}
-
-func GetStorageModeFromDB(db ethdb.Database) (StorageMode, error) {
-	var (
-		sm  StorageMode
-		v   []byte
-		err error
-	)
-	v, err = db.Get(dbutils.DatabaseInfoBucket, dbutils.StorageModeHistory)
-	if err != nil && err != ethdb.ErrKeyNotFound {
-		return StorageMode{}, err
-	}
-	sm.History = len(v) > 0
-
-	v, err = db.Get(dbutils.DatabaseInfoBucket, dbutils.StorageModePreImages)
-	if err != nil && err != ethdb.ErrKeyNotFound {
-		return StorageMode{}, err
-	}
-	sm.Preimages = len(v) > 0
-
-	v, err = db.Get(dbutils.DatabaseInfoBucket, dbutils.StorageModeReceipts)
-	if err != nil && err != ethdb.ErrKeyNotFound {
-		return StorageMode{}, err
-	}
-	sm.Receipts = len(v) > 0
-
-	v, err = db.Get(dbutils.DatabaseInfoBucket, dbutils.StorageModeTxIndex)
-	if err != nil && err != ethdb.ErrKeyNotFound {
-		return StorageMode{}, err
-	}
-	sm.TxIndex = len(v) > 0
-
-	v, err = db.Get(dbutils.DatabaseInfoBucket, dbutils.StorageModeThinHistory)
-	if err != nil && err != ethdb.ErrKeyNotFound {
-		return StorageMode{}, err
-	}
-
-	return sm, nil
-}
diff --git a/eth/config.go b/eth/config.go
index b77e8a12516c56f8689c1e0bb631f3d56fca4b13..2853885868559557a8c8f96be78b89ab3ee896aa 100644
--- a/eth/config.go
+++ b/eth/config.go
@@ -17,7 +17,6 @@
 package eth
 
 import (
-	"fmt"
 	"math/big"
 	"os"
 	"os/user"
@@ -30,6 +29,7 @@ import (
 	"github.com/ledgerwatch/turbo-geth/core"
 	"github.com/ledgerwatch/turbo-geth/eth/downloader"
 	"github.com/ledgerwatch/turbo-geth/eth/gasprice"
+	"github.com/ledgerwatch/turbo-geth/ethdb"
 	"github.com/ledgerwatch/turbo-geth/miner"
 	"github.com/ledgerwatch/turbo-geth/params"
 )
@@ -53,7 +53,7 @@ var DefaultConfig = Config{
 	TrieCleanCache:     256,
 	TrieDirtyCache:     256,
 	TrieTimeout:        60 * time.Minute,
-	StorageMode:        DefaultStorageMode,
+	StorageMode:        ethdb.DefaultStorageMode,
 	Miner: miner.Config{
 		GasFloor: 8000000,
 		GasCeil:  8000000,
@@ -88,52 +88,6 @@ func init() {
 	}
 }
 
-type StorageMode struct {
-	History   bool
-	Receipts  bool
-	TxIndex   bool
-	Preimages bool
-}
-
-var DefaultStorageMode = StorageMode{History: true, Receipts: false, TxIndex: true, Preimages: true}
-
-func (m StorageMode) ToString() string {
-	modeString := ""
-	if m.History {
-		modeString += "h"
-	}
-	if m.Preimages {
-		modeString += "p"
-	}
-	if m.Receipts {
-		modeString += "r"
-	}
-	if m.TxIndex {
-		modeString += "t"
-	}
-	return modeString
-}
-
-func StorageModeFromString(flags string) (StorageMode, error) {
-	mode := StorageMode{}
-	for _, flag := range flags {
-		switch flag {
-		case 'h':
-			mode.History = true
-		case 'r':
-			mode.Receipts = true
-		case 't':
-			mode.TxIndex = true
-		case 'p':
-			mode.Preimages = true
-		default:
-			return mode, fmt.Errorf("unexpected flag found: %c", flag)
-		}
-	}
-
-	return mode, nil
-}
-
 //go:generate gencodec -type Config -formats toml -out gen_config.go
 
 type Config struct {
@@ -153,7 +107,7 @@ type Config struct {
 	NoPrefetch    bool   // Whether to disable prefetching and only load state on demand
 	TxLookupLimit uint64 `toml:",omitempty"` // The maximum number of blocks from head whose tx indices are reserved.
 
-	StorageMode StorageMode
+	StorageMode ethdb.StorageMode
 
 	// DownloadOnly is set when the node does not need to process the blocks, but simply
 	// download them
diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go
index 3af8f56a1fae656c53b97e8103cc741a4f015071..5b5d5632bb015e7f0709f412cf02dbab04ba7b99 100644
--- a/eth/downloader/downloader.go
+++ b/eth/downloader/downloader.go
@@ -156,9 +156,9 @@ type Downloader struct {
 	bodyFetchHook    func([]*types.Header) // Method to call upon starting a block body fetch
 	receiptFetchHook func([]*types.Header) // Method to call upon starting a receipt fetch
 	chainInsertHook  func([]*fetchResult)  // Method to call upon inserting a chain of blocks (possibly in multiple invocations)
-	// generate history index, disable/enable pruning
-	history bool
-	datadir string
+
+	storageMode ethdb.StorageMode
+	datadir     string
 
 	headersState    *stagedsync.StageState
 	headersUnwinder stagedsync.Unwinder
@@ -246,13 +246,13 @@ type BlockChain interface {
 }
 
 // New creates a new downloader to fetch hashes and blocks from remote peers.
-func New(checkpoint uint64, stateDb ethdb.Database, stateBloom *trie.SyncBloom, mux *event.TypeMux, chain BlockChain, lightchain LightChain, dropPeer peerDropFn, history bool) *Downloader {
+func New(checkpoint uint64, stateDB ethdb.Database, stateBloom *trie.SyncBloom, mux *event.TypeMux, chain BlockChain, lightchain LightChain, dropPeer peerDropFn, sm ethdb.StorageMode) *Downloader {
 	if lightchain == nil {
 		lightchain = chain
 	}
 	dl := &Downloader{
 		mode:          FullSync,
-		stateDB:       stateDb,
+		stateDB:       stateDB,
 		mux:           mux,
 		queue:         newQueue(),
 		peers:         newPeerSet(),
@@ -268,8 +268,7 @@ func New(checkpoint uint64, stateDb ethdb.Database, stateBloom *trie.SyncBloom,
 		receiptWakeCh: make(chan bool, 1),
 		headerProcCh:  make(chan []*types.Header, 1),
 		quitCh:        make(chan struct{}),
-		//generate index, disable/enable pruning
-		history: history,
+		storageMode:   sm,
 	}
 	go dl.qosTuner()
 	return dl
@@ -557,7 +556,7 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td *big.I
 			d.blockchain,
 			d.stateDB,
 			p.id,
-			d.history,
+			d.storageMode,
 			d.datadir,
 			d.quitCh,
 			fetchers,
diff --git a/eth/downloader/downloader_stagedsync_test.go b/eth/downloader/downloader_stagedsync_test.go
index ad1e24aa7d0049e83fd4a5374efedd78534f6d91..e62ae5a15a510b8d553a8b0ac4f678f2f7ea49e0 100644
--- a/eth/downloader/downloader_stagedsync_test.go
+++ b/eth/downloader/downloader_stagedsync_test.go
@@ -31,7 +31,7 @@ type stagedSyncTester struct {
 	lock          sync.RWMutex
 }
 
-func newStagedSyncTester(history bool) *stagedSyncTester {
+func newStagedSyncTester() *stagedSyncTester {
 	tester := &stagedSyncTester{
 		peers:   make(map[string]*stagedSyncTesterPeer),
 		genesis: testGenesis,
@@ -42,7 +42,7 @@ func newStagedSyncTester(history bool) *stagedSyncTester {
 	rawdb.WriteTd(tester.db, tester.genesis.Hash(), tester.genesis.NumberU64(), tester.genesis.Difficulty())
 	rawdb.WriteBlock(context.Background(), tester.db, testGenesis)
 	tester.currentHeader = tester.genesis.Header()
-	tester.downloader = New(uint64(StagedSync), tester.db, trie.NewSyncBloom(1, tester.db), new(event.TypeMux), tester, nil, tester.dropPeer, history)
+	tester.downloader = New(uint64(StagedSync), tester.db, trie.NewSyncBloom(1, tester.db), new(event.TypeMux), tester, nil, tester.dropPeer, ethdb.DefaultStorageMode)
 	return tester
 }
 
@@ -90,8 +90,8 @@ func (st *stagedSyncTester) CurrentHeader() *types.Header {
 	return st.currentHeader
 }
 
-// ExecuteBlockEuphemerally is part of the implementation of BlockChain interface defined in downloader.go
-func (st *stagedSyncTester) ExecuteBlockEuphemerally(_ *types.Block, _ state.StateReader, _ *state.DbStateWriter) error {
+// ExecuteBlockEphemerally is part of the implementation of BlockChain interface defined in downloader.go
+func (st *stagedSyncTester) ExecuteBlockEphemerally(_ *types.Block, _ state.StateReader, _ *state.DbStateWriter) error {
 	panic("")
 }
 
@@ -323,7 +323,7 @@ func (stp *stagedSyncTesterPeer) RequestReceipts(hashes []common.Hash) error {
 }
 
 func TestUnwind(t *testing.T) {
-	tester := newStagedSyncTester(false)
+	tester := newStagedSyncTester()
 	if err := tester.newPeer("peer", 65, testChainForkLightA); err != nil {
 		t.Fatal(err)
 	}
diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go
index b30597a0348454314e4148267f397fc30a65b810..24658092342c285ad8d0f60dde337b1bedef8745 100644
--- a/eth/downloader/downloader_test.go
+++ b/eth/downloader/downloader_test.go
@@ -92,7 +92,7 @@ func newTester() *downloadTester {
 	if err != nil {
 		panic(err)
 	}
-	tester.downloader = New(uint64(FullSync), tester.stateDb, trie.NewSyncBloom(1, tester.stateDb), new(event.TypeMux), tester, nil, tester.dropPeer, false)
+	tester.downloader = New(uint64(FullSync), tester.stateDb, trie.NewSyncBloom(1, tester.stateDb), new(event.TypeMux), tester, nil, tester.dropPeer, ethdb.DefaultStorageMode)
 	return tester
 }
 
diff --git a/eth/gen_config.go b/eth/gen_config.go
index 6d61f6e73a97eecc9269c2af3535d11e297401b7..45a92847ce5e69105d60e3bd88ec09ecd570f821 100644
--- a/eth/gen_config.go
+++ b/eth/gen_config.go
@@ -11,6 +11,7 @@ import (
 	"github.com/ledgerwatch/turbo-geth/core"
 	"github.com/ledgerwatch/turbo-geth/eth/downloader"
 	"github.com/ledgerwatch/turbo-geth/eth/gasprice"
+	"github.com/ledgerwatch/turbo-geth/ethdb"
 	"github.com/ledgerwatch/turbo-geth/miner"
 	"github.com/ledgerwatch/turbo-geth/params"
 )
@@ -22,7 +23,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
 		NetworkID               uint64
 		SyncMode                downloader.SyncMode
 		DiscoveryURLs           []string
-		Pruning               bool
+		Pruning                 bool
 		NoPrefetch              bool
 		TxLookupLimit           uint64                 `toml:",omitempty"`
 		Whitelist               map[uint64]common.Hash `toml:"-"`
@@ -97,7 +98,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
 		NetworkID               *uint64
 		SyncMode                *downloader.SyncMode
 		DiscoveryURLs           []string
-		Pruning               *bool
+		Pruning                 *bool
 		NoPrefetch              *bool
 		TxLookupLimit           *uint64                `toml:",omitempty"`
 		Whitelist               map[uint64]common.Hash `toml:"-"`
@@ -158,7 +159,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
 		c.Whitelist = dec.Whitelist
 	}
 	if dec.Mode != nil {
-		mode, err := StorageModeFromString(*dec.Mode)
+		mode, err := ethdb.StorageModeFromString(*dec.Mode)
 		if err != nil {
 			return err
 		}
diff --git a/eth/handler.go b/eth/handler.go
index 96366269c3adfc2c0a432a462ce8a355c4edef58..6f8da55e29e65397d826d3c1585175c308446473 100644
--- a/eth/handler.go
+++ b/eth/handler.go
@@ -176,12 +176,12 @@ func (pm *ProtocolManager) SetDataDir(datadir string) {
 }
 
 func initPm(manager *ProtocolManager, txpool txPool, engine consensus.Engine, blockchain *core.BlockChain, tds *state.TrieDbState, chaindb ethdb.Database) {
-	sm, err := GetStorageModeFromDB(chaindb)
+	sm, err := ethdb.GetStorageModeFromDB(chaindb)
 	if err != nil {
 		log.Error("Get storage mode", "err", err)
 	}
 	// Construct the different synchronisation mechanisms
-	manager.downloader = downloader.New(manager.checkpointNumber, chaindb, nil /*stateBloom */, manager.eventMux, blockchain, nil, manager.removePeer, sm.History)
+	manager.downloader = downloader.New(manager.checkpointNumber, chaindb, nil /*stateBloom */, manager.eventMux, blockchain, nil, manager.removePeer, sm)
 	manager.downloader.SetDataDir(manager.datadir)
 
 	// Construct the fetcher (short sync)
diff --git a/eth/stagedsync/stage_execute.go b/eth/stagedsync/stage_execute.go
index 78e5d49bfd7914664505046fa6c937551ae7e665..6b7a9c2fbd1e09b4e0aa977a28b32327aa049ea8 100644
--- a/eth/stagedsync/stage_execute.go
+++ b/eth/stagedsync/stage_execute.go
@@ -22,7 +22,8 @@ import (
 )
 
 const (
-	logInterval = 30 // seconds
+	logInterval = 30    // seconds
+	prof        = false // whether to profile
 )
 
 type progressLogger struct {
@@ -76,11 +77,7 @@ func (l *progressLogger) Stop() {
 	close(l.quit)
 }
 
-const StateBatchSize = 50 * 1024 * 1024 // 50 Mb
-const ChangeBatchSize = 1024 * 2014     // 1 Mb
-const prof = false
-
-func SpawnExecuteBlocksStage(s *StageState, stateDB ethdb.Database, blockchain BlockChain, limit uint64, quit chan struct{}, dests vm.Cache) error {
+func SpawnExecuteBlocksStage(s *StageState, stateDB ethdb.Database, blockchain BlockChain, limit uint64, quit chan struct{}, dests vm.Cache, writeReceipts bool) error {
 	lastProcessedBlockNumber := s.BlockNumber
 
 	nextBlockNumber := uint64(0)
@@ -99,10 +96,9 @@ func SpawnExecuteBlocksStage(s *StageState, stateDB ethdb.Database, blockchain B
 		}
 	}
 
-	stateBatch := stateDB.NewBatch()
-	changeBatch := stateDB.NewBatch()
+	batch := stateDB.NewBatch()
 
-	progressLogger := NewProgressLogger(logInterval, stateBatch)
+	progressLogger := NewProgressLogger(logInterval, batch)
 	progressLogger.Start(&nextBlockNumber)
 	defer progressLogger.Stop()
 
@@ -145,11 +141,11 @@ func SpawnExecuteBlocksStage(s *StageState, stateDB ethdb.Database, blockchain B
 			cacheSetter
 		}
 		if core.UsePlainStateExecution {
-			stateReader = state.NewPlainStateReader(stateBatch)
-			stateWriter = state.NewPlainStateWriter(stateBatch, changeBatch, blockNum)
+			stateReader = state.NewPlainStateReader(batch)
+			stateWriter = state.NewPlainStateWriter(batch, blockNum)
 		} else {
-			stateReader = state.NewDbStateReader(stateBatch)
-			stateWriter = state.NewDbStateWriter(stateBatch, changeBatch, blockNum)
+			stateReader = state.NewDbStateReader(batch)
+			stateWriter = state.NewDbStateWriter(batch, blockNum)
 		}
 		stateReader.SetAccountCache(accountCache)
 		stateReader.SetStorageCache(storageCache)
@@ -162,45 +158,48 @@ func SpawnExecuteBlocksStage(s *StageState, stateDB ethdb.Database, blockchain B
 		stateWriter.SetCodeSizeCache(codeSizeCache)
 
 		// where the magic happens
-		err := core.ExecuteBlockEuphemerally(chainConfig, vmConfig, blockchain, engine, block, stateReader, stateWriter, dests)
+		receipts, err := core.ExecuteBlockEphemerally(chainConfig, vmConfig, blockchain, engine, block, stateReader, stateWriter, dests)
 		if err != nil {
 			return err
 		}
 
-		if err = s.Update(stateBatch, blockNum); err != nil {
+		if writeReceipts {
+			rawdb.WriteReceipts(batch, block.Hash(), block.NumberU64(), receipts)
+		}
+
+		if err = s.Update(batch, blockNum); err != nil {
 			return err
 		}
 
 		atomic.AddUint64(&nextBlockNumber, 1)
 
-		if stateBatch.BatchSize() >= StateBatchSize {
+		if batch.BatchSize() >= stateDB.IdealBatchSize() {
 			start := time.Now()
-			if _, err = stateBatch.Commit(); err != nil {
-				return err
-			}
-			log.Info("State batch committed", "in", time.Since(start))
-		}
-		if changeBatch.BatchSize() >= ChangeBatchSize {
-			if _, err = changeBatch.Commit(); err != nil {
+			if _, err = batch.Commit(); err != nil {
 				return err
 			}
+			log.Info("Batch committed", "in", time.Since(start))
 		}
 
 		if prof {
 			if blockNum-profileNumber == 100000 {
-				// Flush the profiler
+				// Flush the CPU profiler
 				pprof.StopCPUProfile()
+
+				// And the memory profiler
+				f, _ := os.Create(fmt.Sprintf("mem-%d.prof", profileNumber))
+				defer f.Close()
+				runtime.GC()
+				if err = pprof.WriteHeapProfile(f); err != nil {
+					log.Error("could not save memory profile", "error", err)
+				}
 			}
 		}
 	}
 
-	_, err := stateBatch.Commit()
-	if err != nil {
-		return fmt.Errorf("sync Execute: failed to write state batch commit: %v", err)
-	}
-	_, err = changeBatch.Commit()
+	_, err := batch.Commit()
 	if err != nil {
-		return fmt.Errorf("sync Execute: failed to write change batch commit: %v", err)
+		return fmt.Errorf("sync Execute: failed to write batch commit: %v", err)
 	}
 	s.Done()
 	return nil
diff --git a/eth/stagedsync/stage_hashstate_test.go b/eth/stagedsync/stage_hashstate_test.go
index f09f8ef86a66016dc7db12f547b685cb10b3ec5e..217ab73d3247400d7016d979b5f4a9d82ecff0e9 100644
--- a/eth/stagedsync/stage_hashstate_test.go
+++ b/eth/stagedsync/stage_hashstate_test.go
@@ -33,7 +33,7 @@ func TestPromoteHashedStateClearState(t *testing.T) {
 	}
 	_, err = m2.Commit()
 	if err != nil {
-		t.Errorf("error while commiting state: %v", err)
+		t.Errorf("error while committing state: %v", err)
 	}
 
 	compareCurrentState(t, db1, db2, dbutils.CurrentStateBucket, dbutils.ContractCodeBucket)
@@ -55,7 +55,7 @@ func TestPromoteHashedStateIncremental(t *testing.T) {
 	}
 	_, err = m2.Commit()
 	if err != nil {
-		t.Errorf("error while commiting state: %v", err)
+		t.Errorf("error while committing state: %v", err)
 	}
 
 	generateBlocks(t, 51, 50, hashedWriterGen(db1), changeCodeWithIncarnations)
@@ -68,7 +68,7 @@ func TestPromoteHashedStateIncremental(t *testing.T) {
 	}
 	_, err = m2.Commit()
 	if err != nil {
-		t.Errorf("error while commiting state: %v", err)
+		t.Errorf("error while committing state: %v", err)
 	}
 
 	compareCurrentState(t, db1, db2, dbutils.CurrentStateBucket)
@@ -92,7 +92,7 @@ func TestPromoteHashedStateIncrementalMixed(t *testing.T) {
 
 	_, err = m2.Commit()
 	if err != nil {
-		t.Errorf("error while commiting state: %v", err)
+		t.Errorf("error while committing state: %v", err)
 	}
 	compareCurrentState(t, db1, db2, dbutils.CurrentStateBucket)
 }
diff --git a/eth/stagedsync/stagedsync.go b/eth/stagedsync/stagedsync.go
index 43153622286bca886d6430f8a4fbc01acc07f889..2f68a51bf61acb5f3a67e6391a6314fcd9221e16 100644
--- a/eth/stagedsync/stagedsync.go
+++ b/eth/stagedsync/stagedsync.go
@@ -13,7 +13,7 @@ func PrepareStagedSync(
 	blockchain BlockChain,
 	stateDB ethdb.Database,
 	pid string,
-	history bool,
+	storageMode ethdb.StorageMode,
 	datadir string,
 	quitCh chan struct{},
 	headersFetchers []func() error,
@@ -56,7 +56,7 @@ func PrepareStagedSync(
 			ID:          stages.Execution,
 			Description: "Executing blocks w/o hash checks",
 			ExecFunc: func(s *StageState, u Unwinder) error {
-				return SpawnExecuteBlocksStage(s, stateDB, blockchain, 0 /* limit (meaning no limit) */, quitCh, dests)
+				return SpawnExecuteBlocksStage(s, stateDB, blockchain, 0 /* limit (meaning no limit) */, quitCh, dests, storageMode.Receipts)
 			},
 			UnwindFunc: func(u *UnwindState, s *StageState) error {
 				return unwindExecutionStage(u, s, stateDB)
@@ -85,7 +85,7 @@ func PrepareStagedSync(
 		{
 			ID:                  stages.AccountHistoryIndex,
 			Description:         "Generating account history index",
-			Disabled:            !history,
+			Disabled:            !storageMode.History,
 			DisabledDescription: "Enable by adding `h` to --storage-mode",
 			ExecFunc: func(s *StageState, u Unwinder) error {
 				return spawnAccountHistoryIndex(s, stateDB, datadir, core.UsePlainStateExecution, quitCh)
@@ -97,7 +97,7 @@ func PrepareStagedSync(
 		{
 			ID:                  stages.StorageHistoryIndex,
 			Description:         "Generating storage history index",
-			Disabled:            !history,
+			Disabled:            !storageMode.History,
 			DisabledDescription: "Enable by adding `h` to --storage-mode",
 			ExecFunc: func(s *StageState, u Unwinder) error {
 				return spawnStorageHistoryIndex(s, stateDB, datadir, core.UsePlainStateExecution, quitCh)
diff --git a/eth/stagedsync/testutil.go b/eth/stagedsync/testutil.go
index f08546de4408bf6cd5b21c2410069149fe462c37..d77e0edf016924f116decd76f33ce4790567be20 100644
--- a/eth/stagedsync/testutil.go
+++ b/eth/stagedsync/testutil.go
@@ -55,13 +55,13 @@ type stateWriterGen func(uint64) state.WriterWithChangeSets
 
 func hashedWriterGen(db ethdb.Database) stateWriterGen {
 	return func(blockNum uint64) state.WriterWithChangeSets {
-		return state.NewDbStateWriter(db, db, blockNum)
+		return state.NewDbStateWriter(db, blockNum)
 	}
 }
 
 func plainWriterGen(db ethdb.Database) stateWriterGen {
 	return func(blockNum uint64) state.WriterWithChangeSets {
-		return state.NewPlainStateWriter(db, db, blockNum)
+		return state.NewPlainStateWriter(db, blockNum)
 	}
 }
 func generateBlocks(t *testing.T, from uint64, numberOfBlocks uint64, stateWriterGen stateWriterGen, difficulty int) {
diff --git a/ethdb/storage_mode.go b/ethdb/storage_mode.go
new file mode 100644
index 0000000000000000000000000000000000000000..53c14cbe8b34a6349bf3f1c57dde546d32d589f3
--- /dev/null
+++ b/ethdb/storage_mode.go
@@ -0,0 +1,132 @@
+package ethdb
+
+import (
+	"errors"
+	"fmt"
+
+	"github.com/ledgerwatch/turbo-geth/common/dbutils"
+)
+
+type StorageMode struct {
+	History   bool
+	Receipts  bool
+	TxIndex   bool
+	Preimages bool
+}
+
+var DefaultStorageMode = StorageMode{History: true, Receipts: false, TxIndex: true, Preimages: true}
+
+func (m StorageMode) ToString() string {
+	modeString := ""
+	if m.History {
+		modeString += "h"
+	}
+	if m.Preimages {
+		modeString += "p"
+	}
+	if m.Receipts {
+		modeString += "r"
+	}
+	if m.TxIndex {
+		modeString += "t"
+	}
+	return modeString
+}
+
+func StorageModeFromString(flags string) (StorageMode, error) {
+	mode := StorageMode{}
+	for _, flag := range flags {
+		switch flag {
+		case 'h':
+			mode.History = true
+		case 'r':
+			mode.Receipts = true
+		case 't':
+			mode.TxIndex = true
+		case 'p':
+			mode.Preimages = true
+		default:
+			return mode, fmt.Errorf("unexpected flag found: %c", flag)
+		}
+	}
+
+	return mode, nil
+}
+
+func GetStorageModeFromDB(db Database) (StorageMode, error) {
+	var (
+		sm  StorageMode
+		v   []byte
+		err error
+	)
+	v, err = db.Get(dbutils.DatabaseInfoBucket, dbutils.StorageModeHistory)
+	if err != nil && !errors.Is(err, ErrKeyNotFound) {
+		return StorageMode{}, err
+	}
+	sm.History = len(v) > 0
+
+	v, err = db.Get(dbutils.DatabaseInfoBucket, dbutils.StorageModePreImages)
+	if err != nil && !errors.Is(err, ErrKeyNotFound) {
+		return StorageMode{}, err
+	}
+	sm.Preimages = len(v) > 0
+
+	v, err = db.Get(dbutils.DatabaseInfoBucket, dbutils.StorageModeReceipts)
+	if err != nil && !errors.Is(err, ErrKeyNotFound) {
+		return StorageMode{}, err
+	}
+	sm.Receipts = len(v) > 0
+
+	v, err = db.Get(dbutils.DatabaseInfoBucket, dbutils.StorageModeTxIndex)
+	if err != nil && !errors.Is(err, ErrKeyNotFound) {
+		return StorageMode{}, err
+	}
+	sm.TxIndex = len(v) > 0
+
+	return sm, nil
+}
+
+func SetStorageModeIfNotExist(db Database, sm StorageMode) error {
+	var (
+		err error
+	)
+	err = setModeOnEmpty(db, dbutils.StorageModeHistory, sm.History)
+	if err != nil {
+		return err
+	}
+
+	err = setModeOnEmpty(db, dbutils.StorageModePreImages, sm.Preimages)
+	if err != nil {
+		return err
+	}
+
+	err = setModeOnEmpty(db, dbutils.StorageModeReceipts, sm.Receipts)
+	if err != nil {
+		return err
+	}
+
+	err = setModeOnEmpty(db, dbutils.StorageModeTxIndex, sm.TxIndex)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func setModeOnEmpty(db Database, key []byte, currentValue bool) error {
+	_, err := db.Get(dbutils.DatabaseInfoBucket, key)
+	if err != nil && !errors.Is(err, ErrKeyNotFound) {
+		return err
+	}
+	if errors.Is(err, ErrKeyNotFound) {
+		val := []byte{}
+		if currentValue {
+			val = []byte{1}
+		}
+		if err = db.Put(dbutils.DatabaseInfoBucket, key, val); err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
diff --git a/eth/backend_test.go b/ethdb/storage_mode_test.go
similarity index 79%
rename from eth/backend_test.go
rename to ethdb/storage_mode_test.go
index c8c80190734b98cfd1debca30cfb9ef4d6fa9b5d..96e76ac4a8e464d359cbf899a3cf27abdaf68207 100644
--- a/eth/backend_test.go
+++ b/ethdb/storage_mode_test.go
@@ -1,15 +1,14 @@
-package eth
+package ethdb
 
 import (
 	"reflect"
 	"testing"
 
 	"github.com/davecgh/go-spew/spew"
-	"github.com/ledgerwatch/turbo-geth/ethdb"
 )
 
 func TestSetStorageModeIfNotExist(t *testing.T) {
-	db := ethdb.NewMemDatabase()
+	db := NewMemDatabase()
 	sm, err := GetStorageModeFromDB(db)
 	if err != nil {
 		t.Fatal(err)
@@ -19,7 +18,7 @@ func TestSetStorageModeIfNotExist(t *testing.T) {
 		t.Fatal()
 	}
 
-	err = setStorageModeIfNotExist(db, StorageMode{
+	err = SetStorageModeIfNotExist(db, StorageMode{
 		true,
 		true,
 		true,
@@ -43,5 +42,4 @@ func TestSetStorageModeIfNotExist(t *testing.T) {
 		spew.Dump(sm)
 		t.Fatal("not equal")
 	}
-
 }