diff --git a/cmd/hack/hack.go b/cmd/hack/hack.go
index 8baa96d2e948a3e1c21a570b495a6a7062fa71e8..687b2bbe9870e45f604f5d8e2a015223a1f354cf 100644
--- a/cmd/hack/hack.go
+++ b/cmd/hack/hack.go
@@ -1231,6 +1231,22 @@ func printBranches(block uint64) {
 	}
 }
 
+func readPlainAccount(chaindata string, address common.Address) {
+	ethDb, err := ethdb.NewBoltDatabase(chaindata)
+	check(err)
+	var acc accounts.Account
+	enc, err := ethDb.Get(dbutils.PlainStateBucket, address[:])
+	if err != nil {
+		panic(err)
+	} else if enc == nil {
+		panic("acc not found")
+	}
+	if err = acc.DecodeForStorage(enc); err != nil {
+		panic(err)
+	}
+	fmt.Printf("%x\n%x\n%x\n%d\n", address, acc.Root, acc.CodeHash, acc.Incarnation)
+}
+
 func readAccount(chaindata string, account common.Address, block uint64, rewind uint64) {
 	ethDb, err := ethdb.NewBoltDatabase(chaindata)
 	check(err)
@@ -2300,6 +2316,9 @@ func main() {
 	if *action == "readAccount" {
 		readAccount(*chaindata, common.HexToAddress(*account), uint64(*block), uint64(*rewind))
 	}
+	if *action == "readPlainAccount" {
+		readPlainAccount(*chaindata, common.HexToAddress(*account))
+	}
 	if *action == "fixAccount" {
 		fixAccount(*chaindata, common.HexToHash(*account), common.HexToHash(*hash))
 	}
diff --git a/core/state/db_state_reader.go b/core/state/db_state_reader.go
index 3e0c9e6189f6153e50ad32cbb30c7d39a6221c95..d4160d23c19d7a5b84a95b6317c4d14cc9a4741f 100644
--- a/core/state/db_state_reader.go
+++ b/core/state/db_state_reader.go
@@ -2,12 +2,12 @@ package state
 
 import (
 	"bytes"
+	"encoding/binary"
 
-	lru "github.com/hashicorp/golang-lru"
+	"github.com/VictoriaMetrics/fastcache"
 
 	"github.com/ledgerwatch/turbo-geth/common"
 	"github.com/ledgerwatch/turbo-geth/common/dbutils"
-	"github.com/ledgerwatch/turbo-geth/core/rawdb"
 	"github.com/ledgerwatch/turbo-geth/core/types/accounts"
 	"github.com/ledgerwatch/turbo-geth/ethdb"
 )
@@ -16,10 +16,10 @@ import (
 type DbStateReader struct {
 	db             ethdb.Getter
 	incarnationMap map[common.Address]uint64
-	accountCache   *lru.Cache
-	storageCache   *lru.Cache
-	codeCache      *lru.Cache
-	codeSizeCache  *lru.Cache
+	accountCache   *fastcache.Cache
+	storageCache   *fastcache.Cache
+	codeCache      *fastcache.Cache
+	codeSizeCache  *fastcache.Cache
 }
 
 func NewDbStateReader(db ethdb.Getter, incarnationMap map[common.Address]uint64) *DbStateReader {
@@ -29,64 +29,53 @@ func NewDbStateReader(db ethdb.Getter, incarnationMap map[common.Address]uint64)
 	}
 }
 
-func (dbr *DbStateReader) SetAccountCache(accountCache *lru.Cache) {
+func (dbr *DbStateReader) SetAccountCache(accountCache *fastcache.Cache) {
 	dbr.accountCache = accountCache
 }
 
-func (dbr *DbStateReader) SetStorageCache(storageCache *lru.Cache) {
+func (dbr *DbStateReader) SetStorageCache(storageCache *fastcache.Cache) {
 	dbr.storageCache = storageCache
 }
 
-func (dbr *DbStateReader) SetCodeCache(codeCache *lru.Cache) {
+func (dbr *DbStateReader) SetCodeCache(codeCache *fastcache.Cache) {
 	dbr.codeCache = codeCache
 }
 
-func (dbr *DbStateReader) SetCodeSizeCache(codeSizeCache *lru.Cache) {
+func (dbr *DbStateReader) SetCodeSizeCache(codeSizeCache *fastcache.Cache) {
 	dbr.codeSizeCache = codeSizeCache
 }
 
 func (dbr *DbStateReader) ReadAccountData(address common.Address) (*accounts.Account, error) {
+	var enc []byte
+	var ok bool
 	if dbr.accountCache != nil {
-		if cached, ok := dbr.accountCache.Get(address); ok {
-			if cached == nil {
-				return nil, nil
-			}
-			return cached.(*accounts.Account), nil
+		enc, ok = dbr.accountCache.HasGet(nil, address[:])
+	}
+	if !ok {
+		var err error
+		if addrHash, err1 := common.HashData(address[:]); err1 == nil {
+			enc, err = dbr.db.Get(dbutils.CurrentStateBucket, addrHash[:])
+		} else {
+			return nil, err1
+		}
+		if err != nil && !entryNotFound(err) {
+			return nil, err
 		}
 	}
-	addrHash, err := common.HashData(address[:])
-	if err != nil {
-		return nil, err
+	if !ok && dbr.accountCache != nil {
+		dbr.accountCache.Set(address[:], enc)
 	}
-	var a accounts.Account
-	if ok, err := rawdb.ReadAccount(dbr.db, addrHash, &a); err != nil {
-		return nil, err
-	} else if !ok {
-		if dbr.accountCache != nil {
-			dbr.accountCache.Add(address, nil)
-		}
+	if enc == nil {
 		return nil, nil
 	}
-	if dbr.accountCache != nil {
-		dbr.accountCache.Add(address, a.SelfCopy())
+	acc := &accounts.Account{}
+	if err := acc.DecodeForStorage(enc); err != nil {
+		return nil, err
 	}
-	return &a, nil
+	return acc, nil
 }
 
 func (dbr *DbStateReader) ReadAccountStorage(address common.Address, incarnation uint64, key *common.Hash) ([]byte, error) {
-	var storageKeyP *[20 + 32]byte
-	if dbr.storageCache != nil {
-		var storageKey [20 + 32]byte
-		copy(storageKey[:], address[:])
-		copy(storageKey[20:], key[:])
-		if cached, ok := dbr.storageCache.Get(storageKey); ok {
-			if cached == nil {
-				return nil, nil
-			}
-			return cached.([]byte), nil
-		}
-		storageKeyP = &storageKey
-	}
 	addrHash, err := common.HashData(address[:])
 	if err != nil {
 		return nil, err
@@ -95,34 +84,39 @@ func (dbr *DbStateReader) ReadAccountStorage(address common.Address, incarnation
 	if err1 != nil {
 		return nil, err1
 	}
-	enc, err2 := dbr.db.Get(dbutils.CurrentStateBucket, dbutils.GenerateCompositeStorageKey(addrHash, incarnation, seckey))
-	if err2 != nil && err2 != ethdb.ErrKeyNotFound {
+	compositeKey := dbutils.GenerateCompositeStorageKey(addrHash, incarnation, seckey)
+	if dbr.storageCache != nil {
+		if enc, ok := dbr.storageCache.HasGet(nil, compositeKey); ok {
+			return enc, nil
+		}
+	}
+	enc, err2 := dbr.db.Get(dbutils.CurrentStateBucket, compositeKey)
+	if err2 != nil && !entryNotFound(err2) {
 		return nil, err2
 	}
 	if dbr.storageCache != nil {
-		dbr.storageCache.Add(*storageKeyP, enc)
+		dbr.storageCache.Set(compositeKey, enc)
 	}
 	return enc, nil
 }
 
-func (dbr *DbStateReader) ReadAccountCode(address common.Address, codeHash common.Hash) (code []byte, err error) {
+func (dbr *DbStateReader) ReadAccountCode(address common.Address, codeHash common.Hash) ([]byte, error) {
 	if bytes.Equal(codeHash[:], emptyCodeHash) {
 		return nil, nil
 	}
 	if dbr.codeCache != nil {
-		if cached, ok := dbr.codeCache.Get(address); ok {
-			if cached == nil {
-				return nil, nil
-			}
-			return cached.([]byte), nil
+		if code, ok := dbr.codeCache.HasGet(nil, address[:]); ok {
+			return code, nil
 		}
 	}
-	code, err = dbr.db.Get(dbutils.CodeBucket, codeHash[:])
+	code, err := dbr.db.Get(dbutils.CodeBucket, codeHash[:])
 	if dbr.codeCache != nil && len(code) <= 1024 {
-		dbr.codeCache.Add(address, code)
+		dbr.codeCache.Set(address[:], code)
 	}
 	if dbr.codeSizeCache != nil {
-		dbr.codeSizeCache.Add(address, len(code))
+		var b [4]byte
+		binary.BigEndian.PutUint32(b[:], uint32(len(code)))
+		dbr.codeSizeCache.Set(address[:], b[:])
 	}
 	return code, err
 }
@@ -132,8 +126,8 @@ func (dbr *DbStateReader) ReadAccountCodeSize(address common.Address, codeHash c
 		return 0, nil
 	}
 	if dbr.codeSizeCache != nil {
-		if cached, ok := dbr.codeSizeCache.Get(address); ok {
-			return cached.(int), nil
+		if b, ok := dbr.codeSizeCache.HasGet(nil, address[:]); ok {
+			return int(binary.BigEndian.Uint32(b)), nil
 		}
 	}
 	var code []byte
@@ -142,7 +136,9 @@ func (dbr *DbStateReader) ReadAccountCodeSize(address common.Address, codeHash c
 		return 0, err
 	}
 	if dbr.codeSizeCache != nil {
-		dbr.codeSizeCache.Add(address, len(code))
+		var b [4]byte
+		binary.BigEndian.PutUint32(b[:], uint32(len(code)))
+		dbr.codeSizeCache.Set(address[:], b[:])
 	}
 	return len(code), nil
 }
diff --git a/core/state/db_state_writer.go b/core/state/db_state_writer.go
index 0050698e28ab9e3995a70b13bf27fd0651eda1a2..1387936b130ca50032abaf8d6fc1993f1decaaf1 100644
--- a/core/state/db_state_writer.go
+++ b/core/state/db_state_writer.go
@@ -2,9 +2,10 @@ package state
 
 import (
 	"context"
+	"encoding/binary"
 	"fmt"
 
-	lru "github.com/hashicorp/golang-lru"
+	"github.com/VictoriaMetrics/fastcache"
 
 	"github.com/ledgerwatch/turbo-geth/common"
 	"github.com/ledgerwatch/turbo-geth/common/changeset"
@@ -35,25 +36,25 @@ type DbStateWriter struct {
 	blockNr        uint64
 	csw            *ChangeSetWriter
 	incarnationMap map[common.Address]uint64
-	accountCache   *lru.Cache
-	storageCache   *lru.Cache
-	codeCache      *lru.Cache
-	codeSizeCache  *lru.Cache
+	accountCache   *fastcache.Cache
+	storageCache   *fastcache.Cache
+	codeCache      *fastcache.Cache
+	codeSizeCache  *fastcache.Cache
 }
 
-func (dsw *DbStateWriter) SetAccountCache(accountCache *lru.Cache) {
+func (dsw *DbStateWriter) SetAccountCache(accountCache *fastcache.Cache) {
 	dsw.accountCache = accountCache
 }
 
-func (dsw *DbStateWriter) SetStorageCache(storageCache *lru.Cache) {
+func (dsw *DbStateWriter) SetStorageCache(storageCache *fastcache.Cache) {
 	dsw.storageCache = storageCache
 }
 
-func (dsw *DbStateWriter) SetCodeCache(codeCache *lru.Cache) {
+func (dsw *DbStateWriter) SetCodeCache(codeCache *fastcache.Cache) {
 	dsw.codeCache = codeCache
 }
 
-func (dsw *DbStateWriter) SetCodeSizeCache(codeSizeCache *lru.Cache) {
+func (dsw *DbStateWriter) SetCodeSizeCache(codeSizeCache *fastcache.Cache) {
 	dsw.codeSizeCache = codeSizeCache
 }
 
@@ -84,11 +85,13 @@ func (dsw *DbStateWriter) UpdateAccountData(ctx context.Context, address common.
 	if err != nil {
 		return err
 	}
-	if err := rawdb.WriteAccount(dsw.stateDb, addrHash, *account); err != nil {
+	value := make([]byte, account.EncodingLengthForStorage())
+	account.EncodeForStorage(value)
+	if err := dsw.stateDb.Put(dbutils.CurrentStateBucket, addrHash[:], value); err != nil {
 		return err
 	}
 	if dsw.accountCache != nil {
-		dsw.accountCache.Add(address, account.SelfCopy())
+		dsw.accountCache.Set(address[:], value)
 	}
 	return nil
 }
@@ -108,7 +111,15 @@ func (dsw *DbStateWriter) DeleteAccount(ctx context.Context, address common.Addr
 		dsw.incarnationMap[address] = original.Incarnation
 	}
 	if dsw.accountCache != nil {
-		dsw.accountCache.Add(address, nil)
+		dsw.accountCache.Set(address[:], nil)
+	}
+	if dsw.codeCache != nil {
+		dsw.codeCache.Set(address[:], nil)
+	}
+	if dsw.codeSizeCache != nil {
+		var b [4]byte
+		binary.BigEndian.PutUint32(b[:], 0)
+		dsw.codeSizeCache.Set(address[:], b[:])
 	}
 	return nil
 }
@@ -129,11 +140,17 @@ func (dsw *DbStateWriter) UpdateAccountCode(address common.Address, incarnation
 	if err := dsw.stateDb.Put(dbutils.ContractCodeBucket, dbutils.GenerateStoragePrefix(addrHash[:], incarnation), codeHash[:]); err != nil {
 		return err
 	}
-	if dsw.codeCache != nil && len(code) <= 1024 {
-		dsw.codeCache.Add(address, code)
+	if dsw.codeCache != nil {
+		if len(code) <= 1024 {
+			dsw.codeCache.Set(address[:], code)
+		} else {
+			dsw.codeCache.Del(address[:])
+		}
 	}
 	if dsw.codeSizeCache != nil {
-		dsw.codeSizeCache.Add(address, len(code))
+		var b [4]byte
+		binary.BigEndian.PutUint32(b[:], uint32(len(code)))
+		dsw.codeSizeCache.Set(address[:], b[:])
 	}
 	return nil
 }
@@ -156,18 +173,14 @@ func (dsw *DbStateWriter) WriteAccountStorage(ctx context.Context, address commo
 	}
 	compositeKey := dbutils.GenerateCompositeStorageKey(addrHash, incarnation, seckey)
 
-	v := common.CopyBytes(cleanUpTrailingZeroes(value[:]))
+	v := cleanUpTrailingZeroes(value[:])
 	if dsw.storageCache != nil {
-		var storageKey [20 + 32]byte
-		copy(storageKey[:], address[:])
-		copy(storageKey[20:], key[:])
-		dsw.storageCache.Add(storageKey, v)
+		dsw.storageCache.Set(compositeKey, v)
 	}
 	if len(v) == 0 {
 		return dsw.stateDb.Delete(dbutils.CurrentStateBucket, compositeKey)
-	} else {
-		return dsw.stateDb.Put(dbutils.CurrentStateBucket, compositeKey, v)
 	}
+	return dsw.stateDb.Put(dbutils.CurrentStateBucket, compositeKey, common.CopyBytes(v))
 }
 
 func (dsw *DbStateWriter) CreateContract(address common.Address) error {
diff --git a/core/state/plain_state_reader.go b/core/state/plain_state_reader.go
index 496db821949b19d594463171f89c83b59527819c..cbd0a56132621a0d509dd3ad31be8717b26d5d9d 100644
--- a/core/state/plain_state_reader.go
+++ b/core/state/plain_state_reader.go
@@ -2,7 +2,8 @@ package state
 
 import (
 	"bytes"
-	lru "github.com/hashicorp/golang-lru"
+	"encoding/binary"
+	"github.com/VictoriaMetrics/fastcache"
 
 	"github.com/ledgerwatch/turbo-geth/common"
 	"github.com/ledgerwatch/turbo-geth/common/dbutils"
@@ -18,104 +19,92 @@ var _ StateReader = (*PlainStateReader)(nil)
 type PlainStateReader struct {
 	db                     ethdb.Getter
 	uncommitedIncarnations map[common.Address]uint64
-	accountCache           *lru.Cache
-	storageCache           *lru.Cache
-	codeCache              *lru.Cache
-	codeSizeCache          *lru.Cache
+	accountCache           *fastcache.Cache
+	storageCache           *fastcache.Cache
+	codeCache              *fastcache.Cache
+	codeSizeCache          *fastcache.Cache
 }
 
-func NewPlainStateReaderWithFallback(db ethdb.Getter, incarnations map[common.Address]uint64) *PlainStateReader {
+func NewPlainStateReader(db ethdb.Getter, incarnations map[common.Address]uint64) *PlainStateReader {
 	return &PlainStateReader{
 		db:                     db,
 		uncommitedIncarnations: incarnations,
 	}
 }
 
-func (r *PlainStateReader) SetAccountCache(accountCache *lru.Cache) {
+func (r *PlainStateReader) SetAccountCache(accountCache *fastcache.Cache) {
 	r.accountCache = accountCache
 }
 
-func (r *PlainStateReader) SetStorageCache(storageCache *lru.Cache) {
+func (r *PlainStateReader) SetStorageCache(storageCache *fastcache.Cache) {
 	r.storageCache = storageCache
 }
 
-func (r *PlainStateReader) SetCodeCache(codeCache *lru.Cache) {
+func (r *PlainStateReader) SetCodeCache(codeCache *fastcache.Cache) {
 	r.codeCache = codeCache
 }
 
-func (r *PlainStateReader) SetCodeSizeCache(codeSizeCache *lru.Cache) {
+func (r *PlainStateReader) SetCodeSizeCache(codeSizeCache *fastcache.Cache) {
 	r.codeSizeCache = codeSizeCache
 }
 
 func (r *PlainStateReader) ReadAccountData(address common.Address) (*accounts.Account, error) {
+	var enc []byte
+	var ok bool
 	if r.accountCache != nil {
-		if cached, ok := r.accountCache.Get(address); ok {
-			if cached == nil {
-				return nil, nil
-			}
-			return cached.(*accounts.Account), nil
-		}
+		enc, ok = r.accountCache.HasGet(nil, address[:])
 	}
-	enc, err := r.db.Get(dbutils.PlainStateBucket, address[:])
-	if err == nil {
-		acc := &accounts.Account{}
-		if err = acc.DecodeForStorage(enc); err != nil {
+	if !ok {
+		var err error
+		enc, err = r.db.Get(dbutils.PlainStateBucket, address[:])
+		if err != nil && !entryNotFound(err) {
 			return nil, err
 		}
-		if r.accountCache != nil {
-			r.accountCache.Add(address, acc)
-		}
-		return acc, nil
-	} else if !entryNotFound(err) {
-		return nil, err
 	}
-	if r.accountCache != nil {
-		r.accountCache.Add(address, nil)
+	if !ok && r.accountCache != nil {
+		r.accountCache.Set(address[:], enc)
+	}
+	if enc == nil {
+		return nil, nil
+	}
+	acc := &accounts.Account{}
+	if err := acc.DecodeForStorage(enc); err != nil {
+		return nil, err
 	}
-	return nil, nil
+	return acc, nil
 }
 
 func (r *PlainStateReader) ReadAccountStorage(address common.Address, incarnation uint64, key *common.Hash) ([]byte, error) {
-	var storageKeyP *[20 + 32]byte
+	compositeKey := dbutils.PlainGenerateCompositeStorageKey(address, incarnation, *key)
 	if r.storageCache != nil {
-		var storageKey [20 + 32]byte
-		copy(storageKey[:], address[:])
-		copy(storageKey[20:], key[:])
-		if cached, ok := r.storageCache.Get(storageKey); ok {
-			if cached == nil {
-				return nil, nil
-			}
-			return cached.([]byte), nil
+		if enc, ok := r.storageCache.HasGet(nil, compositeKey); ok {
+			return enc, nil
 		}
-		storageKeyP = &storageKey
 	}
-	enc, err := r.db.Get(dbutils.PlainStateBucket, dbutils.PlainGenerateCompositeStorageKey(address, incarnation, *key))
-	if err == nil {
-		if r.storageCache != nil {
-			r.storageCache.Add(*storageKeyP, enc)
-		}
-		return enc, nil
-	} else if !entryNotFound(err) {
+	enc, err := r.db.Get(dbutils.PlainStateBucket, compositeKey)
+	if err != nil && !entryNotFound(err) {
 		return nil, err
 	}
 	if r.storageCache != nil {
-		r.storageCache.Add(*storageKeyP, nil)
+		r.storageCache.Set(compositeKey, enc)
 	}
-	return nil, nil
+	return enc, nil
 }
 
 func (r *PlainStateReader) ReadAccountCode(address common.Address, codeHash common.Hash) ([]byte, error) {
-	if bytes.Equal(codeHash[:], emptyCodeHash) {
-		return nil, nil
-	}
 	if r.codeCache != nil {
-		if cached, ok := r.codeCache.Get(address); ok {
-			return cached.([]byte), nil
+		if code, ok := r.codeCache.HasGet(nil, address[:]); ok {
+			return code, nil
 		}
 	}
 	code, err := r.db.Get(dbutils.CodeBucket, codeHash[:])
-	if r.codeCache != nil {
-		r.codeCache.Add(address, code)
+	if r.codeCache != nil && len(code) <= 1024 {
+		r.codeCache.Set(address[:], code)
+	}
+	if r.codeSizeCache != nil {
+		var b [4]byte
+		binary.BigEndian.PutUint32(b[:], uint32(len(code)))
+		r.codeSizeCache.Set(address[:], b[:])
 	}
 	return code, err
 }
@@ -125,8 +114,8 @@ func (r *PlainStateReader) ReadAccountCodeSize(address common.Address, codeHash
 		return 0, nil
 	}
 	if r.codeSizeCache != nil {
-		if cached, ok := r.codeSizeCache.Get(address); ok {
-			return cached.(int), nil
+		if b, ok := r.codeSizeCache.HasGet(nil, address[:]); ok {
+			return int(binary.BigEndian.Uint32(b)), nil
 		}
 	}
 	code, err := r.db.Get(dbutils.CodeBucket, codeHash[:])
@@ -134,7 +123,9 @@ func (r *PlainStateReader) ReadAccountCodeSize(address common.Address, codeHash
 		return 0, err
 	}
 	if r.codeSizeCache != nil {
-		r.codeSizeCache.Add(address, len(code))
+		var b [4]byte
+		binary.BigEndian.PutUint32(b[:], uint32(len(code)))
+		r.codeSizeCache.Set(address[:], b[:])
 	}
 	return len(code), nil
 }
diff --git a/core/state/plain_state_writer.go b/core/state/plain_state_writer.go
index 6c9969c064af59ef65f2649936a4a63be3d35503..00e48f8cbede3ac7777f075e2f4c11384c1ce257 100644
--- a/core/state/plain_state_writer.go
+++ b/core/state/plain_state_writer.go
@@ -2,8 +2,9 @@ package state
 
 import (
 	"context"
+	"encoding/binary"
 
-	lru "github.com/hashicorp/golang-lru"
+	"github.com/VictoriaMetrics/fastcache"
 
 	"github.com/ledgerwatch/turbo-geth/common"
 	"github.com/ledgerwatch/turbo-geth/common/changeset"
@@ -20,10 +21,10 @@ type PlainStateWriter struct {
 	uncommitedIncarnations map[common.Address]uint64
 	csw                    *ChangeSetWriter
 	blockNumber            uint64
-	accountCache           *lru.Cache
-	storageCache           *lru.Cache
-	codeCache              *lru.Cache
-	codeSizeCache          *lru.Cache
+	accountCache           *fastcache.Cache
+	storageCache           *fastcache.Cache
+	codeCache              *fastcache.Cache
+	codeSizeCache          *fastcache.Cache
 }
 
 func NewPlainStateWriter(stateDb, changeDb ethdb.Database, blockNumber uint64, uncommitedIncarnations map[common.Address]uint64) *PlainStateWriter {
@@ -36,19 +37,19 @@ func NewPlainStateWriter(stateDb, changeDb ethdb.Database, blockNumber uint64, u
 	}
 }
 
-func (w *PlainStateWriter) SetAccountCache(accountCache *lru.Cache) {
+func (w *PlainStateWriter) SetAccountCache(accountCache *fastcache.Cache) {
 	w.accountCache = accountCache
 }
 
-func (w *PlainStateWriter) SetStorageCache(storageCache *lru.Cache) {
+func (w *PlainStateWriter) SetStorageCache(storageCache *fastcache.Cache) {
 	w.storageCache = storageCache
 }
 
-func (w *PlainStateWriter) SetCodeCache(codeCache *lru.Cache) {
+func (w *PlainStateWriter) SetCodeCache(codeCache *fastcache.Cache) {
 	w.codeCache = codeCache
 }
 
-func (w *PlainStateWriter) SetCodeSizeCache(codeSizeCache *lru.Cache) {
+func (w *PlainStateWriter) SetCodeSizeCache(codeSizeCache *fastcache.Cache) {
 	w.codeSizeCache = codeSizeCache
 }
 
@@ -56,11 +57,11 @@ func (w *PlainStateWriter) UpdateAccountData(ctx context.Context, address common
 	if err := w.csw.UpdateAccountData(ctx, address, original, account); err != nil {
 		return err
 	}
-	if w.accountCache != nil {
-		w.accountCache.Add(address, account)
-	}
 	value := make([]byte, account.EncodingLengthForStorage())
 	account.EncodeForStorage(value)
+	if w.accountCache != nil {
+		w.accountCache.Set(address[:], value)
+	}
 	return w.stateDb.Put(dbutils.PlainStateBucket, address[:], value)
 }
 
@@ -69,10 +70,16 @@ func (w *PlainStateWriter) UpdateAccountCode(address common.Address, incarnation
 		return err
 	}
 	if w.codeCache != nil {
-		w.codeCache.Add(address, code)
+		if len(code) <= 1024 {
+			w.codeCache.Set(address[:], code)
+		} else {
+			w.codeCache.Del(address[:])
+		}
 	}
 	if w.codeSizeCache != nil {
-		w.codeSizeCache.Add(address, len(code))
+		var b [4]byte
+		binary.BigEndian.PutUint32(b[:], uint32(len(code)))
+		w.codeSizeCache.Set(address[:], b[:])
 	}
 	if err := w.stateDb.Put(dbutils.CodeBucket, codeHash[:], code); err != nil {
 		return err
@@ -88,14 +95,17 @@ func (w *PlainStateWriter) DeleteAccount(ctx context.Context, address common.Add
 		w.uncommitedIncarnations[address] = original.Incarnation
 	}
 	if w.accountCache != nil {
-		w.accountCache.Add(address, nil)
+		w.accountCache.Set(address[:], nil)
 	}
-	if err := w.stateDb.Delete(dbutils.PlainStateBucket, address[:]); err != nil {
-		if err != ethdb.ErrKeyNotFound {
-			return err
-		}
+	if w.codeCache != nil {
+		w.codeCache.Set(address[:], nil)
 	}
-	return nil
+	if w.codeSizeCache != nil {
+		var b [4]byte
+		binary.BigEndian.PutUint32(b[:], 0)
+		w.codeSizeCache.Set(address[:], b[:])
+	}
+	return w.stateDb.Delete(dbutils.PlainStateBucket, address[:])
 }
 
 func (w *PlainStateWriter) WriteAccountStorage(ctx context.Context, address common.Address, incarnation uint64, key, original, value *common.Hash) error {
@@ -105,25 +115,16 @@ func (w *PlainStateWriter) WriteAccountStorage(ctx context.Context, address comm
 	if *original == *value {
 		return nil
 	}
-
 	compositeKey := dbutils.PlainGenerateCompositeStorageKey(address, incarnation, *key)
 
-	v := common.CopyBytes(cleanUpTrailingZeroes(value[:]))
+	v := cleanUpTrailingZeroes(value[:])
 	if w.storageCache != nil {
-		var storageKey [20 + 32]byte
-		copy(storageKey[:], address[:])
-		copy(storageKey[20:], key[:])
-		w.storageCache.Add(storageKey, v)
+		w.storageCache.Set(compositeKey, v)
 	}
 	if len(v) == 0 {
-		if err := w.stateDb.Delete(dbutils.PlainStateBucket, compositeKey); err != nil {
-			if err != ethdb.ErrKeyNotFound {
-				return err
-			}
-		}
-		return nil
+		return w.stateDb.Delete(dbutils.PlainStateBucket, compositeKey)
 	}
-	return w.stateDb.Put(dbutils.PlainStateBucket, compositeKey, v)
+	return w.stateDb.Put(dbutils.PlainStateBucket, compositeKey, common.CopyBytes(v))
 }
 
 func (w *PlainStateWriter) CreateContract(address common.Address) error {
diff --git a/eth/downloader/stagedsync_stage_execute.go b/eth/downloader/stagedsync_stage_execute.go
index 6961077fb8b0919fae7f93eca86e321232cd5cff..d3999a04f9157572b573158e064803c4fad2317c 100644
--- a/eth/downloader/stagedsync_stage_execute.go
+++ b/eth/downloader/stagedsync_stage_execute.go
@@ -8,7 +8,7 @@ import (
 	"sync/atomic"
 	"time"
 
-	lru "github.com/hashicorp/golang-lru"
+	"github.com/VictoriaMetrics/fastcache"
 
 	"github.com/ledgerwatch/turbo-geth/common"
 	"github.com/ledgerwatch/turbo-geth/common/dbutils"
@@ -100,10 +100,10 @@ func spawnExecuteBlocksStage(stateDB ethdb.Database, blockchain BlockChain) (uin
 	progressLogger.Start(&nextBlockNumber)
 	defer progressLogger.Stop()
 
-	accountCache, _ := lru.New(400000)
-	storageCache, _ := lru.New(400000)
-	codeCache, _ := lru.New(1000)
-	codeSizeCache, _ := lru.New(400000)
+	accountCache := fastcache.New(128 * 1024 * 1024) // 128 Mb
+	storageCache := fastcache.New(128 * 1024 * 1024) // 128 Mb
+	codeCache := fastcache.New(32 * 1024 * 1024)     // 32 Mb (the minimum)
+	codeSizeCache := fastcache.New(32 * 1024 * 1024) // 32 Mb (the minimum)
 	// uncommitedIncarnations map holds incarnations for accounts that were deleted,
 	// but their storage is not yet committed
 	var uncommitedIncarnations = make(map[common.Address]uint64)
@@ -123,7 +123,7 @@ func spawnExecuteBlocksStage(stateDB ethdb.Database, blockchain BlockChain) (uin
 		var stateWriter state.WriterWithChangeSets
 
 		if core.UsePlainStateExecution {
-			plainReader := state.NewPlainStateReaderWithFallback(stateBatch, uncommitedIncarnations)
+			plainReader := state.NewPlainStateReader(stateBatch, uncommitedIncarnations)
 			plainReader.SetAccountCache(accountCache)
 			plainReader.SetStorageCache(storageCache)
 			plainReader.SetCodeCache(codeCache)