diff --git a/pkg/local_object_storage/blobovnicza/blobovnicza.go b/pkg/local_object_storage/blobovnicza/blobovnicza.go
index fc7795d35..dd8dbbba5 100644
--- a/pkg/local_object_storage/blobovnicza/blobovnicza.go
+++ b/pkg/local_object_storage/blobovnicza/blobovnicza.go
@@ -106,3 +106,10 @@ func WithLogger(l *logger.Logger) Option {
 		c.log = l.With(zap.String("component", "Blobovnicza"))
 	}
 }
+
+// ReadOnly returns option to open Blobovnicza in read-only mode.
+func ReadOnly() Option {
+	return func(c *cfg) {
+		c.boltOptions.ReadOnly = true
+	}
+}
diff --git a/pkg/local_object_storage/blobovnicza/control.go b/pkg/local_object_storage/blobovnicza/control.go
index 7c39717cb..5c2141310 100644
--- a/pkg/local_object_storage/blobovnicza/control.go
+++ b/pkg/local_object_storage/blobovnicza/control.go
@@ -16,24 +16,33 @@ import (
 func (b *Blobovnicza) Open() error {
 	b.log.Debug("creating directory for BoltDB",
 		zap.String("path", b.path),
+		zap.Bool("ro", b.boltOptions.ReadOnly),
 	)
 
-	err := util.MkdirAllX(path.Dir(b.path), b.perm)
-	if err == nil {
-		b.log.Debug("opening BoltDB",
-			zap.String("path", b.path),
-			zap.Stringer("permissions", b.perm),
-		)
+	var err error
 
-		b.boltDB, err = bbolt.Open(b.path, b.perm, b.boltOptions)
+	if !b.boltOptions.ReadOnly {
+		err = util.MkdirAllX(path.Dir(b.path), b.perm)
+		if err != nil {
+			return err
+		}
 	}
 
+	b.log.Debug("opening BoltDB",
+		zap.String("path", b.path),
+		zap.Stringer("permissions", b.perm),
+	)
+
+	b.boltDB, err = bbolt.Open(b.path, b.perm, b.boltOptions)
+
 	return err
 }
 
 // Init initializes internal database structure.
 //
 // If Blobovnicza is already initialized, then no action is taken.
+//
+// Should not be called in read-only configuration.
 func (b *Blobovnicza) Init() error {
 	b.log.Debug("initializing...",
 		zap.Uint64("object size limit", b.objSizeLimit),
diff --git a/pkg/local_object_storage/blobovnicza/delete.go b/pkg/local_object_storage/blobovnicza/delete.go
index a7974d635..0100e6517 100644
--- a/pkg/local_object_storage/blobovnicza/delete.go
+++ b/pkg/local_object_storage/blobovnicza/delete.go
@@ -27,6 +27,8 @@ func (p *DeletePrm) SetAddress(addr *objectSDK.Address) {
 // did not allow to completely delete the object.
 //
 // Returns ErrNotFound if the object to be deleted is not in blobovnicza.
+//
+// Should not be called in read-only configuration.
 func (b *Blobovnicza) Delete(prm *DeletePrm) (*DeleteRes, error) {
 	addrKey := addressKey(prm.addr)
 
diff --git a/pkg/local_object_storage/blobovnicza/put.go b/pkg/local_object_storage/blobovnicza/put.go
index 0160f3087..5075697f3 100644
--- a/pkg/local_object_storage/blobovnicza/put.go
+++ b/pkg/local_object_storage/blobovnicza/put.go
@@ -47,6 +47,8 @@ func (p *PutPrm) SetMarshaledObject(data []byte) {
 // did not allow to completely save the object.
 //
 // Returns ErrFull if blobovnicza is filled.
+//
+// Should not be called in read-only configuration.
 func (b *Blobovnicza) Put(prm *PutPrm) (*PutRes, error) {
 	addr := prm.addr
 	if addr == nil {