Repository: TBD54566975/ssi-service
Pull request #220 (2022-12-15 09:39:14)

Make storage more friendly.
# Overview
this basically same with #188 

# Description
merge changes by myself;

# How Has This Been Tested?
modified test code with setupTestDB, but still have some internet issue.

# Checklist

Before submitting this PR, please make sure:

- [x] I have read the CONTRIBUTING document.
- [x] My code is consistent with the rest of the project 
- [x] I have tagged the relevant reviewers and/or interested parties
- [x] I have updated the READMEs and other documentation of affected packages





Patch:
diff --git a/.gitignore b/.gitignore
index 7be95b4..86749ed 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,4 +25,7 @@ vendor/
 *.db
 
 # Log files
-log/*.log
\ No newline at end of file
+log/*.log
+
+# VSCode
+.vscode
\ No newline at end of file
diff --git a/cmd/main.go b/cmd/main.go
index a36f23e..9340999 100644
--- a/cmd/main.go
+++ b/cmd/main.go
@@ -9,6 +9,7 @@ import (
 	"syscall"
 	"time"
 
+	"github.com/TBD54566975/ssi-sdk/schema"
 	"github.com/ardanlabs/conf"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
@@ -80,6 +81,20 @@ func run() error {
 		defer file.Close()
 	}
 
+	// set up schema caching based on config
+	if cfg.Server.EnableSchemaCaching {
+		localSchemas, err := schema.GetAllLocalSchemas()
+		if err != nil {
+			logrus.WithError(err).Error("could not load local schemas")
+		} else {
+			cl, err := schema.NewCachingLoader(localSchemas)
+			if err != nil {
+				logrus.WithError(err).Error("could not create caching loader")
+			}
+			cl.EnableHTTPCache()
+		}
+	}
+
 	expvar.NewString("build").Set(cfg.Version.SVN)
 
 	logrus.Infof("main: Started : Service initializing : version %q", cfg.Version.SVN)
@@ -125,7 +140,7 @@ func run() error {
 	}()
 
 	select {
-	case err := <-serverErrors:
+	case err = <-serverErrors:
 		return errors.Wrap(err, "server error")
 	case sig := <-shutdown:
 		logrus.Infof("main: shutdown signal received -> %v", sig)
@@ -138,8 +153,10 @@ func run() error {
 			logrus.Errorf("main: failed to shutdown tracer: %s", err)
 		}
 
-		if err := api.Shutdown(ctx); err != nil {
-			api.Close()
+		if err = api.Shutdown(ctx); err != nil {
+			if err = api.Close(); err != nil {
+				return err
+			}
 			return errors.Wrap(err, "main: failed to stop server gracefully")
 		}
 	}
diff --git a/config/compose.toml b/config/compose.toml
index 799a0d0..3899b38 100644
--- a/config/compose.toml
+++ b/config/compose.toml
@@ -19,6 +19,8 @@ log_location = "logs"
 # options: trace, debug, info, warning, error, fatal, panic
 log_level = "info"
 
+enable_schema_caching = true
+
 [services]
 storage = "bolt"
 service_endpoint = "http://localhost:8080"
diff --git a/config/config.go b/config/config.go
index f4f4dff..6188a22 100644
--- a/config/config.go
+++ b/config/config.go
@@ -30,15 +30,16 @@ type SSIServiceConfig struct {
 
 // ServerConfig represents configurable properties for the HTTP server
 type ServerConfig struct {
-	APIHost         string        `toml:"api_host" conf:"default:0.0.0.0:3000"`
-	DebugHost       string        `toml:"debug_host" conf:"default:0.0.0.0:4000"`
-	JagerHost       string        `toml:"jager_host" conf:"http://jaeger:14268/api/traces"`
-	JagerEnabled    bool          `toml:"jager_enabled" conf:"default:false"`
-	ReadTimeout     time.Duration `toml:"read_timeout" conf:"default:5s"`
-	WriteTimeout    time.Duration `toml:"write_timeout" conf:"default:5s"`
-	ShutdownTimeout time.Duration `toml:"shutdown_timeout" conf:"default:5s"`
-	LogLocation     string        `toml:"log_location" conf:"default:log"`
-	LogLevel        string        `toml:"log_level" conf:"default:debug"`
+	APIHost             string        `toml:"api_host" conf:"default:0.0.0.0:3000"`
+	DebugHost           string        `toml:"debug_host" conf:"default:0.0.0.0:4000"`
+	JagerHost           string        `toml:"jager_host" conf:"http://jaeger:14268/api/traces"`
+	JagerEnabled        bool          `toml:"jager_enabled" conf:"default:false"`
+	ReadTimeout         time.Duration `toml:"read_timeout" conf:"default:5s"`
+	WriteTimeout        time.Duration `toml:"write_timeout" conf:"default:5s"`
+	ShutdownTimeout     time.Duration `toml:"shutdown_timeout" conf:"default:5s"`
+	LogLocation         string        `toml:"log_location" conf:"default:log"`
+	LogLevel            string        `toml:"log_level" conf:"default:debug"`
+	EnableSchemaCaching bool          `toml:"enable_schema_caching" conf:"default:true"`
 }
 
 // ServicesConfig represents configurable properties for the components of the SSI Service
@@ -46,8 +47,9 @@ type ServicesConfig struct {
 	// at present, it is assumed that a single storage provider works for all services
 	// in the future it may make sense to have per-service storage providers (e.g. mysql for one service,
 	// mongo for another)
-	StorageProvider string `toml:"storage"`
-	ServiceEndpoint string `toml:"service_endpoint"`
+	StorageProvider string      `toml:"storage"`
+	StorageOption   interface{} `toml:"storage_option"`
+	ServiceEndpoint string      `toml:"service_endpoint"`
 
 	// Embed all service-specific configs here. The order matters: from which should be instantiated first, to last
 	KeyStoreConfig     KeyStoreServiceConfig     `toml:"keystore,omitempty"`
diff --git a/config/config.toml b/config/config.toml
index a1a8b56..d0c0bff 100644
--- a/config/config.toml
+++ b/config/config.toml
@@ -17,6 +17,8 @@ log_location = "logs"
 # options: trace, debug, info, warning, error, fatal, panic
 log_level = "debug"
 
+enable_schema_caching = true
+
 [services]
 storage = "bolt"
 service_endpoint = "http://localhost:8080"
diff --git a/doc/swagger.yaml b/doc/swagger.yaml
index a5d9f93..3833160 100644
--- a/doc/swagger.yaml
+++ b/doc/swagger.yaml
@@ -479,7 +479,7 @@ definitions:
           context values.
         type: string
       data:
-        additionalProperties: true
+        additionalProperties: {}
         type: object
       expiry:
         type: string
@@ -770,7 +770,7 @@ definitions:
         description: The reason why the submission was approved or denied.
         type: string
       status:
-        description: One of {`pending`, `approved`, `denied`}.
+        description: One of {`pending`, `approved`, `denied`, `cancelled`}.
         type: string
     required:
     - definition_id
@@ -790,7 +790,7 @@ definitions:
     properties:
       submissions:
         items:
-          $ref: '#/definitions/presentation.Submission'
+          $ref: '#/definitions/model.Submission'
         type: array
     type: object
   github.com_tbd54566975_ssi-service_pkg_server_router.Operation:
@@ -846,7 +846,7 @@ definitions:
         description: The reason why the submission was approved or denied.
         type: string
       status:
-        description: One of {`pending`, `approved`, `denied`}.
+        description: One of {`pending`, `approved`, `denied`, `cancelled`}.
         type: string
     required:
     - definition_id
@@ -1044,6 +1044,28 @@ definitions:
     - id
     - schema
     type: object
+  model.Submission:
+    properties:
+      definition_id:
+        type: string
+      descriptor_map:
+        items:
+          $ref: '#/definitions/exchange.SubmissionDescriptor'
+        type: array
+      id:
+        type: string
+      reason:
+        description: The reason why the submission was approved or denied.
+        type: string
+      status:
+        description: One of {`pending`, `approved`, `denied`, `cancelled`}.
+        type: string
+    required:
+    - definition_id
+    - descriptor_map
+    - id
+    - status
+    type: object
   pkg_server_router.CreateCredentialRequest:
     properties:
       '@context':
@@ -1051,7 +1073,7 @@ definitions:
           context values.
         type: string
       data:
-        additionalProperties: true
+        additionalProperties: {}
         type: object
       expiry:
         type: string
@@ -1342,7 +1364,7 @@ definitions:
         description: The reason why the submission was approved or denied.
         type: string
       status:
-        description: One of {`pending`, `approved`, `denied`}.
+        description: One of {`pending`, `approved`, `denied`, `cancelled`}.
         type: string
     required:
     - definition_id
@@ -1362,7 +1384,7 @@ definitions:
     properties:
       submissions:
         items:
-          $ref: '#/definitions/presentation.Submission'
+          $ref: '#/definitions/model.Submission'
         type: array
     type: object
   pkg_server_router.Operation:
@@ -1418,7 +1440,7 @@ definitions:
         description: The reason why the submission was approved or denied.
         type: string
       status:
-        description: One of {`pending`, `approved`, `denied`}.
+        description: One of {`pending`, `approved`, `denied`, `cancelled`}.
         type: string
     required:
     - definition_id
@@ -1501,28 +1523,6 @@ definitions:
       verified:
         type: boolean
     type: object
-  presentation.Submission:
-    properties:
-      definition_id:
-        type: string
-      descriptor_map:
-        items:
-          $ref: '#/definitions/exchange.SubmissionDescriptor'
-        type: array
-      id:
-        type: string
-      reason:
-        description: The reason why the submission was approved or denied.
-        type: string
-      status:
-        description: One of {`pending`, `approved`, `denied`}.
-        type: string
-    required:
-    - definition_id
-    - descriptor_map
-    - id
-    - status
-    type: object
   rendering.ColorResource:
     properties:
       color:
@@ -2411,7 +2411,7 @@ paths:
         "200":
           description: OK
           schema:
-            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.GetOperationsResponse'
+            $ref: '#/definitions/pkg_server_router.Operation'
         "400":
           description: Bad request
           schema:
@@ -2440,7 +2440,7 @@ paths:
         "200":
           description: OK
           schema:
-            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.Operation'
+            $ref: '#/definitions/pkg_server_router.Operation'
         "400":
           description: Bad request
           schema:
diff --git a/go.mod b/go.mod
index 60d23fe..99d75be 100644
--- a/go.mod
+++ b/go.mod
@@ -4,7 +4,7 @@ go 1.19
 
 require (
 	github.com/BurntSushi/toml v1.2.1
-	github.com/TBD54566975/ssi-sdk v0.0.2-alpha.0.20221209214116-fb01f46e7429
+	github.com/TBD54566975/ssi-sdk v0.0.2-alpha.0.20221214220628-e2badfb960fa
 	github.com/ardanlabs/conf v1.5.0
 	github.com/dimfeld/httptreemux/v5 v5.5.0
 	github.com/go-playground/locales v0.14.0
diff --git a/go.sum b/go.sum
index 6d0359f..78f9f23 100644
--- a/go.sum
+++ b/go.sum
@@ -2,6 +2,8 @@ github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak
 github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
 github.com/TBD54566975/ssi-sdk v0.0.2-alpha.0.20221209214116-fb01f46e7429 h1:YPGYl5SdnVF+b+7ccut1IuQ1xC4rEHuBqIXoy+379DE=
 github.com/TBD54566975/ssi-sdk v0.0.2-alpha.0.20221209214116-fb01f46e7429/go.mod h1:h5Oa7RbqAzeGBlK3UR5qyCqU42+SMn0hb8hxjjAMkGs=
+github.com/TBD54566975/ssi-sdk v0.0.2-alpha.0.20221214220628-e2badfb960fa h1:d1O2F8c/AwCHmOOeQQFPySEz+Jou0EayyjM/66m6Vck=
+github.com/TBD54566975/ssi-sdk v0.0.2-alpha.0.20221214220628-e2badfb960fa/go.mod h1:GIfJZUiXKxnyFJs3H0SLoFL5tVezav6p5Zcs8TddKJE=
 github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 h1:yL7+Jz0jTC6yykIK/Wh74gnTJnrGr5AyrNMXuA0gves=
 github.com/antlr/antlr4/runtime/Go/antlr v1.4.10/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
 github.com/ardanlabs/conf v1.5.0 h1:5TwP6Wu9Xi07eLFEpiCUF3oQXh9UzHMDVnD3u/I5d5c=
diff --git a/pkg/server/router/manifest.go b/pkg/server/router/manifest.go
index ad7fa54..c9678d9 100644
--- a/pkg/server/router/manifest.go
+++ b/pkg/server/router/manifest.go
@@ -164,7 +164,7 @@ func (mr ManifestRouter) GetManifests(ctx context.Context, w http.ResponseWriter
 	gotManifests, err := mr.service.GetManifests()
 
 	if err != nil {
-		errMsg := fmt.Sprintf("could not get manifests")
+		errMsg := "could not get manifests"
 		logrus.WithError(err).Error(errMsg)
 		return framework.NewRequestError(errors.Wrap(err, errMsg), http.StatusBadRequest)
 	}
@@ -384,7 +384,7 @@ func (mr ManifestRouter) GetApplications(ctx context.Context, w http.ResponseWri
 	gotApplications, err := mr.service.GetApplications()
 
 	if err != nil {
-		errMsg := fmt.Sprintf("could not get applications")
+		errMsg := "could not get applications"
 		logrus.WithError(err).Error(errMsg)
 		return framework.NewRequestError(errors.Wrap(err, errMsg), http.StatusBadRequest)
 	}
@@ -479,7 +479,7 @@ func (mr ManifestRouter) GetResponses(ctx context.Context, w http.ResponseWriter
 	gotResponses, err := mr.service.GetResponses()
 
 	if err != nil {
-		errMsg := fmt.Sprintf("could not get responses")
+		errMsg := "could not get responses"
 		logrus.WithError(err).Error(errMsg)
 		return framework.NewRequestError(errors.Wrap(err, errMsg), http.StatusBadRequest)
 	}
diff --git a/pkg/server/router/operation.go b/pkg/server/router/operation.go
index f0e1e64..596d0b7 100644
--- a/pkg/server/router/operation.go
+++ b/pkg/server/router/operation.go
@@ -53,7 +53,7 @@ func (o OperationRouter) GetOperation(ctx context.Context, w http.ResponseWriter
 		return framework.NewRequestError(
 			util.LoggingErrorMsg(err, "failed getting operation"), http.StatusInternalServerError)
 	}
-	return framework.Respond(ctx, w, routerModel(op), http.StatusOK)
+	return framework.Respond(ctx, w, routerModel(*op), http.StatusOK)
 }
 
 type GetOperationsRequest struct {
@@ -169,10 +169,22 @@ func routerModel(op operation.Operation) Operation {
 // @Accept       json
 // @Produce      json
 // @Param        id   path      string  true  "ID"
-// @Success      200  {object}  GetOperationsResponse  "OK"
+// @Success      200  {object}  Operation  "OK"
 // @Failure      400  {string}  string  "Bad request"
 // @Failure      500  {string}  string  "Internal server error"
 // @Router       /v1/operations [get]
 func (o OperationRouter) CancelOperation(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
-	return nil
+	id := framework.GetParam(ctx, IDParam)
+	if id == nil {
+		return framework.NewRequestError(
+			util.LoggingNewError("get operation request requires id"), http.StatusBadRequest)
+	}
+
+	op, err := o.service.CancelOperation(operation.CancelOperationRequest{ID: *id})
+
+	if err != nil {
+		return framework.NewRequestError(
+			util.LoggingErrorMsg(err, "failed cancelling operation"), http.StatusInternalServerError)
+	}
+	return framework.Respond(ctx, w, routerModel(*op), http.StatusOK)
 }
diff --git a/pkg/server/router/presentation.go b/pkg/server/router/presentation.go
index f67ec79..89eb989 100644
--- a/pkg/server/router/presentation.go
+++ b/pkg/server/router/presentation.go
@@ -133,7 +133,7 @@ type GetPresentationDefinitionResponse struct {
 // @Success      200  {object}  GetPresentationDefinitionResponse
 // @Failure      400  {string}  string  "Bad request"
 // @Router       /v1/presentation/definition/{id} [get]
-func (pr PresentationRouter) GetPresentationDefinition(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
+func (pr PresentationRouter) GetPresentationDefinition(ctx context.Context, w http.ResponseWriter, _ *http.Request) error {
 	id := framework.GetParam(ctx, IDParam)
 	if id == nil {
 		errMsg := "cannot get presentation without ID parameter"
@@ -289,7 +289,7 @@ type GetSubmissionResponse struct {
 // @Success      200  {object}  GetSubmissionResponse
 // @Failure      400  {string}  string  "Bad request"
 // @Router       /v1/presentations/submissions/{id} [get]
-func (pr PresentationRouter) GetSubmission(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
+func (pr PresentationRouter) GetSubmission(ctx context.Context, w http.ResponseWriter, _ *http.Request) error {
 	id := framework.GetParam(ctx, IDParam)
 	if id == nil {
 		return framework.NewRequestError(
diff --git a/pkg/service/credential/service.go b/pkg/service/credential/service.go
index 09b5235..f0fc111 100644
--- a/pkg/service/credential/service.go
+++ b/pkg/service/credential/service.go
@@ -19,7 +19,6 @@ import (
 	credint "github.com/tbd54566975/ssi-service/internal/credential"
 	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 	"github.com/tbd54566975/ssi-service/internal/util"
-	credstorage "github.com/tbd54566975/ssi-service/pkg/service/credential/storage"
 	"github.com/tbd54566975/ssi-service/pkg/service/framework"
 	"github.com/tbd54566975/ssi-service/pkg/service/keystore"
 	"github.com/tbd54566975/ssi-service/pkg/service/schema"
@@ -27,7 +26,7 @@ import (
 )
 
 type Service struct {
-	storage  credstorage.Storage
+	storage  *Storage
 	config   config.CredentialServiceConfig
 	verifier *credint.Verifier
 
@@ -68,7 +67,7 @@ func (s Service) Config() config.CredentialServiceConfig {
 }
 
 func NewCredentialService(config config.CredentialServiceConfig, s storage.ServiceStorage, keyStore *keystore.Service, didResolver *didsdk.Resolver, schema *schema.Service) (*Service, error) {
-	credentialStorage, err := credstorage.NewCredentialStorage(s)
+	credentialStorage, err := NewCredentialStorage(s)
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not instantiate storage for the credential service")
 	}
@@ -205,7 +204,7 @@ func (s Service) CreateCredential(request CreateCredentialRequest) (*CreateCrede
 		Revoked:       false,
 	}
 
-	storageRequest := credstorage.StoreCredentialRequest{
+	storageRequest := StoreCredentialRequest{
 		Container: container,
 	}
 
@@ -251,7 +250,7 @@ func getStatusListCredential(s Service, issuerID string, schemaID string) (*cred
 			CredentialJWT: statusListCredJWT,
 		}
 
-		storageRequest := credstorage.StoreCredentialRequest{
+		storageRequest := StoreCredentialRequest{
 			Container: statusListContainer,
 		}
 
@@ -486,7 +485,7 @@ func (s Service) UpdateCredentialStatus(request UpdateCredentialStatusRequest) (
 	return &response, nil
 }
 
-func updateCredentialStatus(s Service, gotCred *credstorage.StoredCredential, request UpdateCredentialStatusRequest) (*credint.Container, error) {
+func updateCredentialStatus(s Service, gotCred *StoredCredential, request UpdateCredentialStatusRequest) (*credint.Container, error) {
 	// store the credential with updated status
 	container := credint.Container{
 		ID:            gotCred.ID,
@@ -495,7 +494,7 @@ func updateCredentialStatus(s Service, gotCred *credstorage.StoredCredential, re
 		Revoked:       request.Revoked,
 	}
 
-	storageRequest := credstorage.StoreCredentialRequest{
+	storageRequest := StoreCredentialRequest{
 		Container: container,
 	}
 
@@ -538,7 +537,7 @@ func updateCredentialStatus(s Service, gotCred *credstorage.StoredCredential, re
 		CredentialJWT: statusListCredJWT,
 	}
 
-	storageRequest = credstorage.StoreCredentialRequest{
+	storageRequest = StoreCredentialRequest{
 		Container: statusListContainer,
 	}
 
diff --git a/pkg/service/credential/storage/bolt.go b/pkg/service/credential/storage.go
similarity index 76%
rename from pkg/service/credential/storage/bolt.go
rename to pkg/service/credential/storage.go
index 2ec4d8e..7a7715f 100644
--- a/pkg/service/credential/storage/bolt.go
+++ b/pkg/service/credential/storage.go
@@ -1,4 +1,4 @@
-package storage
+package credential
 
 import (
 	"fmt"
@@ -10,10 +10,46 @@ import (
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 
+	"github.com/TBD54566975/ssi-sdk/credential"
+	credint "github.com/tbd54566975/ssi-service/internal/credential"
+	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 	"github.com/tbd54566975/ssi-service/internal/util"
 	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
 
+type StoreCredentialRequest struct {
+	credint.Container
+}
+
+type StoredCredential struct {
+	// This ID is generated by the storage module upon first write
+	ID string `json:"id"`
+
+	CredentialID string `json:"credentialId"`
+
+	// only one of these fields should be present
+	Credential    *credential.VerifiableCredential `json:"credential,omitempty"`
+	CredentialJWT *keyaccess.JWT                   `json:"token,omitempty"`
+
+	Issuer       string `json:"issuer"`
+	Subject      string `json:"subject"`
+	Schema       string `json:"schema"`
+	IssuanceDate string `json:"issuanceDate"`
+	Revoked      bool   `json:"revoked"`
+}
+
+func (sc StoredCredential) IsValid() bool {
+	return sc.ID != "" && (sc.HasDataIntegrityCredential() || sc.HasJWTCredential())
+}
+
+func (sc StoredCredential) HasDataIntegrityCredential() bool {
+	return sc.Credential != nil && sc.Credential.Proof != nil
+}
+
+func (sc StoredCredential) HasJWTCredential() bool {
+	return sc.CredentialJWT != nil
+}
+
 const (
 	credentialNamespace           = "credential"
 	statusListCredentialNamespace = "status-list-credential"
@@ -29,15 +65,15 @@ const (
 	credentialNotFoundErrMsg = "credential not found"
 )
 
-type BoltCredentialStorage struct {
-	db *storage.BoltDB
+type Storage struct {
+	db storage.ServiceStorage
 }
 
 type StatusListIndex struct {
 	Index int `json:"index"`
 }
 
-func NewBoltCredentialStorage(db *storage.BoltDB) (*BoltCredentialStorage, error) {
+func NewCredentialStorage(db storage.ServiceStorage) (*Storage, error) {
 	if db == nil {
 		return nil, errors.New("bolt db reference is nil")
 	}
@@ -80,12 +116,12 @@ func NewBoltCredentialStorage(db *storage.BoltDB) (*BoltCredentialStorage, error
 		return nil, util.LoggingErrorMsg(err, "problem writing current list index to db")
 	}
 
-	return &BoltCredentialStorage{db: db}, nil
+	return &Storage{db: db}, nil
 }
 
-func (b BoltCredentialStorage) GetNextStatusListRandomIndex() (int, error) {
+func (cs *Storage) GetNextStatusListRandomIndex() (int, error) {
 
-	gotUniqueNumBytes, err := b.db.Read(statusListIndexNamespace, statusListIndexesKey)
+	gotUniqueNumBytes, err := cs.db.Read(statusListIndexNamespace, statusListIndexesKey)
 	if err != nil {
 		return -1, util.LoggingErrorMsgf(err, "reading status list")
 	}
@@ -99,7 +135,7 @@ func (b BoltCredentialStorage) GetNextStatusListRandomIndex() (int, error) {
 		return -1, util.LoggingErrorMsgf(err, "could not unmarshal unique numbers")
 	}
 
-	gotCurrentListIndexBytes, err := b.db.Read(statusListIndexNamespace, currentListIndexKey)
+	gotCurrentListIndexBytes, err := cs.db.Read(statusListIndexNamespace, currentListIndexKey)
 	if err != nil {
 		return -1, util.LoggingErrorMsgf(err, "could not get list index")
 	}
@@ -114,22 +150,22 @@ func (b BoltCredentialStorage) GetNextStatusListRandomIndex() (int, error) {
 		return -1, util.LoggingErrorMsg(err, "could not marshal status list index bytes")
 	}
 
-	if err := b.db.Write(statusListIndexNamespace, currentListIndexKey, statusListIndexBytes); err != nil {
+	if err := cs.db.Write(statusListIndexNamespace, currentListIndexKey, statusListIndexBytes); err != nil {
 		return -1, util.LoggingErrorMsg(err, "problem writing current list index to db")
 	}
 
 	return uniqueNums[statusListIndex.Index], nil
 }
 
-func (b BoltCredentialStorage) StoreCredential(request StoreCredentialRequest) error {
-	return b.storeCredential(request, credentialNamespace)
+func (cs *Storage) StoreCredential(request StoreCredentialRequest) error {
+	return cs.storeCredential(request, credentialNamespace)
 }
 
-func (b BoltCredentialStorage) StoreStatusListCredential(request StoreCredentialRequest) error {
-	return b.storeCredential(request, statusListCredentialNamespace)
+func (cs *Storage) StoreStatusListCredential(request StoreCredentialRequest) error {
+	return cs.storeCredential(request, statusListCredentialNamespace)
 }
 
-func (b BoltCredentialStorage) storeCredential(request StoreCredentialRequest, namespace string) error {
+func (cs *Storage) storeCredential(request StoreCredentialRequest, namespace string) error {
 	if !request.IsValid() {
 		return util.LoggingNewError("store request request is not valid")
 	}
@@ -145,7 +181,7 @@ func (b BoltCredentialStorage) storeCredential(request StoreCredentialRequest, n
 		return util.LoggingErrorMsgf(err, "could not store request: %s", storedCredential.CredentialID)
 	}
 	// TODO(gabe) conflict checking?
-	return b.db.Write(namespace, storedCredential.ID, storedCredBytes)
+	return cs.db.Write(namespace, storedCredential.ID, storedCredBytes)
 }
 
 // buildStoredCredential generically parses a store credential request and returns the object to be stored
@@ -185,16 +221,16 @@ func buildStoredCredential(request StoreCredentialRequest) (*StoredCredential, e
 	}, nil
 }
 
-func (b BoltCredentialStorage) GetCredential(id string) (*StoredCredential, error) {
-	return b.getCredential(id, credentialNamespace)
+func (cs *Storage) GetCredential(id string) (*StoredCredential, error) {
+	return cs.getCredential(id, credentialNamespace)
 }
 
-func (b BoltCredentialStorage) GetStatusListCredential(id string) (*StoredCredential, error) {
-	return b.getCredential(id, statusListCredentialNamespace)
+func (cs *Storage) GetStatusListCredential(id string) (*StoredCredential, error) {
+	return cs.getCredential(id, statusListCredentialNamespace)
 }
 
-func (b BoltCredentialStorage) getCredential(id string, namespace string) (*StoredCredential, error) {
-	prefixValues, err := b.db.ReadPrefix(namespace, id)
+func (cs *Storage) getCredential(id string, namespace string) (*StoredCredential, error) {
+	prefixValues, err := cs.db.ReadPrefix(namespace, id)
 	if err != nil {
 		return nil, util.LoggingErrorMsgf(err, "could not get credential from storage: %s", id)
 	}
@@ -226,8 +262,8 @@ func (b BoltCredentialStorage) getCredential(id string, namespace string) (*Stor
 // GetCredentialsByIssuer gets all credentials stored with a prefix key containing the issuer value
 // The method is greedy, meaning if multiple values are found and some fail during processing, we will
 // return only the successful values and log an error for the failures.
-func (b BoltCredentialStorage) GetCredentialsByIssuer(issuer string) ([]StoredCredential, error) {
-	keys, err := b.db.ReadAllKeys(credentialNamespace)
+func (cs *Storage) GetCredentialsByIssuer(issuer string) ([]StoredCredential, error) {
+	keys, err := cs.db.ReadAllKeys(credentialNamespace)
 	if err != nil {
 		return nil, util.LoggingErrorMsgf(err, "could not read credential storage while searching for creds for issuer: %s", issuer)
 	}
@@ -246,7 +282,7 @@ func (b BoltCredentialStorage) GetCredentialsByIssuer(issuer string) ([]StoredCr
 	// now get each credential by key
 	var storedCreds []StoredCredential
 	for _, key := range issuerKeys {
-		credBytes, err := b.db.Read(credentialNamespace, key)
+		credBytes, err := cs.db.Read(credentialNamespace, key)
 		if err != nil {
 			logrus.WithError(err).Errorf("could not read credential with key: %s", key)
 		} else {
@@ -268,8 +304,8 @@ func (b BoltCredentialStorage) GetCredentialsByIssuer(issuer string) ([]StoredCr
 // GetCredentialsBySubject gets all credentials stored with a prefix key containing the subject value
 // The method is greedy, meaning if multiple values are found...and some fail during processing, we will
 // return only the successful values and log an error for the failures.
-func (b BoltCredentialStorage) GetCredentialsBySubject(subject string) ([]StoredCredential, error) {
-	keys, err := b.db.ReadAllKeys(credentialNamespace)
+func (cs *Storage) GetCredentialsBySubject(subject string) ([]StoredCredential, error) {
+	keys, err := cs.db.ReadAllKeys(credentialNamespace)
 	if err != nil {
 		return nil, util.LoggingErrorMsgf(err, "could not read credential storage while searching for creds for subject: %s", subject)
 	}
@@ -289,7 +325,7 @@ func (b BoltCredentialStorage) GetCredentialsBySubject(subject string) ([]Stored
 	// now get each credential by key
 	var storedCreds []StoredCredential
 	for _, key := range subjectKeys {
-		credBytes, err := b.db.Read(credentialNamespace, key)
+		credBytes, err := cs.db.Read(credentialNamespace, key)
 		if err != nil {
 			logrus.WithError(err).Errorf("could not read credential with key: %s", key)
 		} else {
@@ -311,8 +347,8 @@ func (b BoltCredentialStorage) GetCredentialsBySubject(subject string) ([]Stored
 // GetCredentialsBySchema gets all credentials stored with a prefix key containing the schema value
 // The method is greedy, meaning if multiple values are found...and some fail during processing, we will
 // return only the successful values and log an error for the failures.
-func (b BoltCredentialStorage) GetCredentialsBySchema(schema string) ([]StoredCredential, error) {
-	keys, err := b.db.ReadAllKeys(credentialNamespace)
+func (cs *Storage) GetCredentialsBySchema(schema string) ([]StoredCredential, error) {
+	keys, err := cs.db.ReadAllKeys(credentialNamespace)
 	if err != nil {
 		return nil, util.LoggingErrorMsgf(err, "could not read credential storage while searching for creds for schema: %s", schema)
 	}
@@ -333,7 +369,7 @@ func (b BoltCredentialStorage) GetCredentialsBySchema(schema string) ([]StoredCr
 	// now get each credential by key
 	var storedCreds []StoredCredential
 	for _, key := range schemaKeys {
-		credBytes, err := b.db.Read(credentialNamespace, key)
+		credBytes, err := cs.db.Read(credentialNamespace, key)
 		if err != nil {
 			logrus.WithError(err).Errorf("could not read credential with key: %s", key)
 		} else {
@@ -355,16 +391,16 @@ func (b BoltCredentialStorage) GetCredentialsBySchema(schema string) ([]StoredCr
 // GetCredentialsByIssuerAndSchema gets all credentials stored with a prefix key containing the issuer value
 // The method is greedy, meaning if multiple values are found...and some fail during processing, we will
 // return only the successful values and log an error for the failures.
-func (b BoltCredentialStorage) GetCredentialsByIssuerAndSchema(issuer string, schema string) ([]StoredCredential, error) {
-	return b.getCredentialsByIssuerAndSchema(issuer, schema, credentialNamespace)
+func (cs *Storage) GetCredentialsByIssuerAndSchema(issuer string, schema string) ([]StoredCredential, error) {
+	return cs.getCredentialsByIssuerAndSchema(issuer, schema, credentialNamespace)
 }
 
-func (b BoltCredentialStorage) GetStatusListCredentialsByIssuerAndSchema(issuer string, schema string) ([]StoredCredential, error) {
-	return b.getCredentialsByIssuerAndSchema(issuer, schema, statusListCredentialNamespace)
+func (cs *Storage) GetStatusListCredentialsByIssuerAndSchema(issuer string, schema string) ([]StoredCredential, error) {
+	return cs.getCredentialsByIssuerAndSchema(issuer, schema, statusListCredentialNamespace)
 }
 
-func (b BoltCredentialStorage) getCredentialsByIssuerAndSchema(issuer string, schema string, namespace string) ([]StoredCredential, error) {
-	keys, err := b.db.ReadAllKeys(namespace)
+func (cs *Storage) getCredentialsByIssuerAndSchema(issuer string, schema string, namespace string) ([]StoredCredential, error) {
+	keys, err := cs.db.ReadAllKeys(namespace)
 	if err != nil {
 		return nil, util.LoggingErrorMsgf(err, "could not read credential storage while searching for creds for issuer: %s", issuer)
 	}
@@ -385,7 +421,7 @@ func (b BoltCredentialStorage) getCredentialsByIssuerAndSchema(issuer string, sc
 	// now get each credential by key
 	var storedCreds []StoredCredential
 	for _, key := range issuerSchemaKeys {
-		credBytes, err := b.db.Read(namespace, key)
+		credBytes, err := cs.db.Read(namespace, key)
 		if err != nil {
 			logrus.WithError(err).Errorf("could not read credential with key: %s", key)
 		} else {
@@ -404,19 +440,19 @@ func (b BoltCredentialStorage) getCredentialsByIssuerAndSchema(issuer string, sc
 	return storedCreds, nil
 }
 
-func (b BoltCredentialStorage) DeleteCredential(id string) error {
-	return b.deleteCredential(id, credentialNamespace)
+func (cs *Storage) DeleteCredential(id string) error {
+	return cs.deleteCredential(id, credentialNamespace)
 }
 
-func (b BoltCredentialStorage) DeleteStatusListCredential(id string) error {
-	return b.deleteCredential(id, statusListCredentialNamespace)
+func (cs *Storage) DeleteStatusListCredential(id string) error {
+	return cs.deleteCredential(id, statusListCredentialNamespace)
 }
 
-func (b BoltCredentialStorage) deleteCredential(id string, namespace string) error {
+func (cs *Storage) deleteCredential(id string, namespace string) error {
 	credDoesNotExistMsg := fmt.Sprintf("credential does not exist, cannot delete: %s", id)
 
 	// first get the credential to regenerate the prefix key
-	gotCred, err := b.GetCredential(id)
+	gotCred, err := cs.GetCredential(id)
 	if err != nil {
 		// no error on deletion for a non-existent credential
 		if strings.Contains(err.Error(), credentialNotFoundErrMsg) {
@@ -435,7 +471,7 @@ func (b BoltCredentialStorage) deleteCredential(id string, namespace string) err
 
 	// re-create the prefix key to delete
 	prefix := createPrefixKey(id, gotCred.Issuer, gotCred.Subject, gotCred.Schema)
-	if err = b.db.Delete(namespace, prefix); err != nil {
+	if err = cs.db.Delete(namespace, prefix); err != nil {
 		return util.LoggingErrorMsgf(err, "could not delete credential: %s", id)
 	}
 	return nil
diff --git a/pkg/service/credential/storage/storage.go b/pkg/service/credential/storage/storage.go
deleted file mode 100644
index 4b4b30b..0000000
--- a/pkg/service/credential/storage/storage.go
+++ /dev/null
@@ -1,77 +0,0 @@
-package storage
-
-import (
-	"github.com/TBD54566975/ssi-sdk/credential"
-
-	cred "github.com/tbd54566975/ssi-service/internal/credential"
-	"github.com/tbd54566975/ssi-service/internal/keyaccess"
-	"github.com/tbd54566975/ssi-service/internal/util"
-	"github.com/tbd54566975/ssi-service/pkg/storage"
-)
-
-type StoreCredentialRequest struct {
-	cred.Container
-}
-
-type StoredCredential struct {
-	// This ID is generated by the storage module upon first write
-	ID string `json:"id"`
-
-	CredentialID string `json:"credentialId"`
-
-	// only one of these fields should be present
-	Credential    *credential.VerifiableCredential `json:"credential,omitempty"`
-	CredentialJWT *keyaccess.JWT                   `json:"token,omitempty"`
-
-	Issuer       string `json:"issuer"`
-	Subject      string `json:"subject"`
-	Schema       string `json:"schema"`
-	IssuanceDate string `json:"issuanceDate"`
-	Revoked      bool   `json:"revoked"`
-}
-
-func (sc StoredCredential) IsValid() bool {
-	return sc.ID != "" && (sc.HasDataIntegrityCredential() || sc.HasJWTCredential())
-}
-
-func (sc StoredCredential) HasDataIntegrityCredential() bool {
-	return sc.Credential != nil && sc.Credential.Proof != nil
-}
-
-func (sc StoredCredential) HasJWTCredential() bool {
-	return sc.CredentialJWT != nil
-}
-
-type Storage interface {
-	StoreCredential(request StoreCredentialRequest) error
-	GetCredential(id string) (*StoredCredential, error)
-	GetCredentialsByIssuer(issuer string) ([]StoredCredential, error)
-	GetCredentialsBySubject(subject string) ([]StoredCredential, error)
-	GetCredentialsBySchema(schema string) ([]StoredCredential, error)
-	GetCredentialsByIssuerAndSchema(issuer, schema string) ([]StoredCredential, error)
-	DeleteCredential(id string) error
-
-	StoreStatusListCredential(request StoreCredentialRequest) error
-	GetStatusListCredential(id string) (*StoredCredential, error)
-	GetStatusListCredentialsByIssuerAndSchema(issuer, schema string) ([]StoredCredential, error)
-	DeleteStatusListCredential(id string) error
-
-	GetNextStatusListRandomIndex() (int, error)
-}
-
-func NewCredentialStorage(s storage.ServiceStorage) (Storage, error) {
-	switch s.Type() {
-	case storage.Bolt:
-		gotBolt, ok := s.(*storage.BoltDB)
-		if !ok {
-			return nil, util.LoggingNewErrorf("trouble instantiating : %s", s.Type())
-		}
-		boltStorage, err := NewBoltCredentialStorage(gotBolt)
-		if err != nil {
-			return nil, util.LoggingErrorMsg(err, "could not instantiate credential bolt storage")
-		}
-		return boltStorage, err
-	default:
-		return nil, util.LoggingNewErrorf("unsupported storage type: %s", s.Type())
-	}
-}
diff --git a/pkg/service/did/key.go b/pkg/service/did/key.go
index ed13223..e1d8196 100644
--- a/pkg/service/did/key.go
+++ b/pkg/service/did/key.go
@@ -9,16 +9,15 @@ import (
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 
-	"github.com/tbd54566975/ssi-service/pkg/service/did/storage"
 	"github.com/tbd54566975/ssi-service/pkg/service/keystore"
 )
 
-func newKeyDIDHandler(s storage.Storage, ks *keystore.Service) MethodHandler {
+func newKeyDIDHandler(s *Storage, ks *keystore.Service) MethodHandler {
 	return &keyDIDHandler{storage: s, keyStore: ks}
 }
 
 type keyDIDHandler struct {
-	storage  storage.Storage
+	storage  *Storage
 	keyStore *keystore.Service
 }
 
@@ -40,7 +39,7 @@ func (h *keyDIDHandler) CreateDID(request CreateDIDRequest) (*CreateDIDResponse,
 
 	// store metadata in DID storage
 	id := doc.String()
-	storedDID := storage.StoredDID{
+	storedDID := StoredDID{
 		ID:  id,
 		DID: *expanded,
 	}
@@ -98,8 +97,8 @@ func (h *keyDIDHandler) GetDIDs(method did.Method) (*GetDIDsResponse, error) {
 		return nil, fmt.Errorf("error getting DIDs for method: %s", method)
 	}
 	dids := make([]did.DIDDocument, 0, len(gotDIDs))
-	for _, did := range gotDIDs {
-		dids = append(dids, did.DID)
+	for _, gotDID := range gotDIDs {
+		dids = append(dids, gotDID.DID)
 	}
 	return &GetDIDsResponse{DIDs: dids}, nil
 }
diff --git a/pkg/service/did/service.go b/pkg/service/did/service.go
index 011b0db..3575038 100644
--- a/pkg/service/did/service.go
+++ b/pkg/service/did/service.go
@@ -10,7 +10,6 @@ import (
 	"github.com/tbd54566975/ssi-service/config"
 	"github.com/tbd54566975/ssi-service/internal/did"
 	"github.com/tbd54566975/ssi-service/internal/util"
-	didstorage "github.com/tbd54566975/ssi-service/pkg/service/did/storage"
 	"github.com/tbd54566975/ssi-service/pkg/service/framework"
 	"github.com/tbd54566975/ssi-service/pkg/service/keystore"
 	"github.com/tbd54566975/ssi-service/pkg/storage"
@@ -18,7 +17,7 @@ import (
 
 type Service struct {
 	config   config.DIDServiceConfig
-	storage  didstorage.Storage
+	storage  *Storage
 	resolver *didsdk.Resolver
 
 	// supported DID methods
@@ -65,7 +64,7 @@ func (s *Service) GetResolver() *didsdk.Resolver {
 }
 
 func NewDIDService(config config.DIDServiceConfig, s storage.ServiceStorage, keyStore *keystore.Service) (*Service, error) {
-	didStorage, err := didstorage.NewDIDStorage(s)
+	didStorage, err := NewDIDStorage(s)
 	if err != nil {
 		return nil, errors.Wrap(err, "could not instantiate DID storage for the DID service")
 	}
diff --git a/pkg/service/did/storage/bolt.go b/pkg/service/did/storage.go
similarity index 80%
rename from pkg/service/did/storage/bolt.go
rename to pkg/service/did/storage.go
index 454aa16..8fb4bda 100644
--- a/pkg/service/did/storage/bolt.go
+++ b/pkg/service/did/storage.go
@@ -1,8 +1,9 @@
-package storage
+package did
 
 import (
 	"fmt"
 
+	"github.com/TBD54566975/ssi-sdk/did"
 	"github.com/goccy/go-json"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
@@ -24,18 +25,23 @@ var (
 	}
 )
 
-type BoltDIDStorage struct {
-	db *storage.BoltDB
+type StoredDID struct {
+	ID  string          `json:"id"`
+	DID did.DIDDocument `json:"did"`
 }
 
-func NewBoltDIDStorage(db *storage.BoltDB) (*BoltDIDStorage, error) {
+type Storage struct {
+	db storage.ServiceStorage
+}
+
+func NewDIDStorage(db storage.ServiceStorage) (*Storage, error) {
 	if db == nil {
 		return nil, errors.New("bolt db reference is nil")
 	}
-	return &BoltDIDStorage{db: db}, nil
+	return &Storage{db: db}, nil
 }
 
-func (b BoltDIDStorage) StoreDID(did StoredDID) error {
+func (ds *Storage) StoreDID(did StoredDID) error {
 	couldNotStoreDIDErr := fmt.Sprintf("could not store DID: %s", did.ID)
 	ns, err := getNamespaceForDID(did.ID)
 	if err != nil {
@@ -45,16 +51,16 @@ func (b BoltDIDStorage) StoreDID(did StoredDID) error {
 	if err != nil {
 		return util.LoggingErrorMsg(err, couldNotStoreDIDErr)
 	}
-	return b.db.Write(ns, did.ID, didBytes)
+	return ds.db.Write(ns, did.ID, didBytes)
 }
 
-func (b BoltDIDStorage) GetDID(id string) (*StoredDID, error) {
+func (ds *Storage) GetDID(id string) (*StoredDID, error) {
 	couldNotGetDIDErr := fmt.Sprintf("could not get DID: %s", id)
 	ns, err := getNamespaceForDID(id)
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, couldNotGetDIDErr)
 	}
-	docBytes, err := b.db.Read(ns, id)
+	docBytes, err := ds.db.Read(ns, id)
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, couldNotGetDIDErr)
 	}
@@ -70,13 +76,13 @@ func (b BoltDIDStorage) GetDID(id string) (*StoredDID, error) {
 }
 
 // GetDIDs attempts to get all DIDs for a given method. It will return those it can even if it has trouble with some.
-func (b BoltDIDStorage) GetDIDs(method string) ([]StoredDID, error) {
+func (ds *Storage) GetDIDs(method string) ([]StoredDID, error) {
 	couldNotGetDIDsErr := fmt.Sprintf("could not get DIDs for method: %s", method)
 	ns, err := getNamespaceForMethod(method)
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, couldNotGetDIDsErr)
 	}
-	gotDIDs, err := b.db.ReadAll(ns)
+	gotDIDs, err := ds.db.ReadAll(ns)
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, couldNotGetDIDsErr)
 	}
@@ -94,13 +100,13 @@ func (b BoltDIDStorage) GetDIDs(method string) ([]StoredDID, error) {
 	return stored, nil
 }
 
-func (b BoltDIDStorage) DeleteDID(id string) error {
+func (ds *Storage) DeleteDID(id string) error {
 	couldNotGetDIDErr := fmt.Sprintf("could not delete DID: %s", id)
 	ns, err := getNamespaceForDID(id)
 	if err != nil {
 		return util.LoggingErrorMsg(err, couldNotGetDIDErr)
 	}
-	if err = b.db.Delete(ns, id); err != nil {
+	if err = ds.db.Delete(ns, id); err != nil {
 		return util.LoggingErrorMsgf(err, "could not delete DID: %s", id)
 	}
 	return nil
diff --git a/pkg/service/did/storage/storage.go b/pkg/service/did/storage/storage.go
deleted file mode 100644
index 79325cd..0000000
--- a/pkg/service/did/storage/storage.go
+++ /dev/null
@@ -1,38 +0,0 @@
-package storage
-
-import (
-	"github.com/TBD54566975/ssi-sdk/did"
-
-	"github.com/tbd54566975/ssi-service/internal/util"
-	"github.com/tbd54566975/ssi-service/pkg/storage"
-)
-
-type StoredDID struct {
-	ID  string          `json:"id"`
-	DID did.DIDDocument `json:"did"`
-}
-
-type Storage interface {
-	StoreDID(did StoredDID) error
-	GetDID(id string) (*StoredDID, error)
-	GetDIDs(method string) ([]StoredDID, error)
-	DeleteDID(id string) error
-}
-
-// NewDIDStorage finds the DID storage impl for a given ServiceStorage value
-func NewDIDStorage(s storage.ServiceStorage) (Storage, error) {
-	switch s.Type() {
-	case storage.Bolt:
-		gotBolt, ok := s.(*storage.BoltDB)
-		if !ok {
-			return nil, util.LoggingNewErrorf("trouble instantiating : %s", s.Type())
-		}
-		boltStorage, err := NewBoltDIDStorage(gotBolt)
-		if err != nil {
-			return nil, util.LoggingErrorMsg(err, "could not instantiate credential bolt storage")
-		}
-		return boltStorage, err
-	default:
-		return nil, util.LoggingNewErrorf("unsupported storage type: %s", s.Type())
-	}
-}
diff --git a/pkg/service/did/web.go b/pkg/service/did/web.go
index a7fb1a0..d6f2b27 100644
--- a/pkg/service/did/web.go
+++ b/pkg/service/did/web.go
@@ -9,16 +9,15 @@ import (
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 
-	"github.com/tbd54566975/ssi-service/pkg/service/did/storage"
 	"github.com/tbd54566975/ssi-service/pkg/service/keystore"
 )
 
-func newWebDIDHandler(s storage.Storage, ks *keystore.Service) MethodHandler {
+func newWebDIDHandler(s *Storage, ks *keystore.Service) MethodHandler {
 	return &webDIDHandler{storage: s, keyStore: ks}
 }
 
 type webDIDHandler struct {
-	storage  storage.Storage
+	storage  *Storage
 	keyStore *keystore.Service
 }
 
@@ -52,7 +51,7 @@ func (h *webDIDHandler) CreateDID(request CreateDIDRequest) (*CreateDIDResponse,
 
 	// store metadata in DID storage
 	id := didWeb.String()
-	storedDID := storage.StoredDID{
+	storedDID := StoredDID{
 		ID:  id,
 		DID: *doc,
 	}
@@ -110,8 +109,8 @@ func (h *webDIDHandler) GetDIDs(method did.Method) (*GetDIDsResponse, error) {
 		return nil, fmt.Errorf("error getting DIDs for method: %s", method)
 	}
 	dids := make([]did.DIDDocument, 0, len(gotDIDs))
-	for _, did := range gotDIDs {
-		dids = append(dids, did.DID)
+	for _, gotDID := range gotDIDs {
+		dids = append(dids, gotDID.DID)
 	}
 	return &GetDIDsResponse{DIDs: dids}, nil
 }
diff --git a/pkg/service/keystore/service.go b/pkg/service/keystore/service.go
index 1fddc40..2df3037 100644
--- a/pkg/service/keystore/service.go
+++ b/pkg/service/keystore/service.go
@@ -14,12 +14,11 @@ import (
 	"github.com/tbd54566975/ssi-service/config"
 	"github.com/tbd54566975/ssi-service/internal/util"
 	"github.com/tbd54566975/ssi-service/pkg/service/framework"
-	keystorestorage "github.com/tbd54566975/ssi-service/pkg/service/keystore/storage"
 	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
 
 type Service struct {
-	storage keystorestorage.Storage
+	storage *Storage
 	config  config.KeyStoreServiceConfig
 }
 
@@ -53,7 +52,10 @@ func NewKeyStoreService(config config.KeyStoreServiceConfig, s storage.ServiceSt
 	}
 
 	// Next, instantiate the key storage
-	keyStoreStorage, err := keystorestorage.NewKeyStoreStorage(s, serviceKey, serviceKeySalt)
+	keyStoreStorage, err := NewKeyStoreStorage(s, ServiceKey{
+		Base58Key:  serviceKey,
+		Base58Salt: serviceKeySalt,
+	})
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not instantiate storage for the keystore service")
 	}
@@ -78,7 +80,7 @@ func (s Service) StoreKey(request StoreKeyRequest) error {
 		return util.LoggingNewErrorf("unsupported key type: %s", request.Type)
 	}
 
-	key := keystorestorage.StoredKey{
+	key := StoredKey{
 		ID:         request.ID,
 		Controller: request.Controller,
 		KeyType:    request.Type,
diff --git a/pkg/service/keystore/storage/bolt.go b/pkg/service/keystore/storage.go
similarity index 65%
rename from pkg/service/keystore/storage/bolt.go
rename to pkg/service/keystore/storage.go
index 4150424..1022b61 100644
--- a/pkg/service/keystore/storage/bolt.go
+++ b/pkg/service/keystore/storage.go
@@ -1,35 +1,54 @@
-package storage
+package keystore
 
 import (
 	"github.com/goccy/go-json"
 	"github.com/mr-tron/base58"
 	"github.com/pkg/errors"
 
+	"github.com/TBD54566975/ssi-sdk/crypto"
 	"github.com/tbd54566975/ssi-service/internal/util"
 	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
 
+// StoredKey represents a common data model to store data on all key types
+type StoredKey struct {
+	ID         string         `json:"id"`
+	Controller string         `json:"controller"`
+	KeyType    crypto.KeyType `json:"keyType"`
+	Base58Key  string         `json:"key"`
+	CreatedAt  string         `json:"createdAt"`
+}
+
+// KeyDetails represents a common data model to get information about a key, without revealing the key itself
+type KeyDetails struct {
+	ID         string         `json:"id"`
+	Controller string         `json:"controller"`
+	KeyType    crypto.KeyType `json:"keyType"`
+	CreatedAt  string         `json:"createdAt"`
+}
+
+type ServiceKey struct {
+	Base58Key  string
+	Base58Salt string
+}
+
 const (
 	namespace         = "keystore"
 	skKey             = "ssi-service-key"
 	keyNotFoundErrMsg = "key not found"
 )
 
-type BoltKeyStoreStorage struct {
-	db         *storage.BoltDB
+type Storage struct {
+	db         storage.ServiceStorage
 	serviceKey []byte
 }
 
-func NewBoltKeyStoreStorage(db *storage.BoltDB, key ServiceKey) (*BoltKeyStoreStorage, error) {
-	if db == nil {
-		return nil, errors.New("bolt db reference is nil")
-	}
-
+func NewKeyStoreStorage(db storage.ServiceStorage, key ServiceKey) (*Storage, error) {
 	keyBytes, err := base58.Decode(key.Base58Key)
 	if err != nil {
 		return nil, errors.Wrap(err, "could not decode service key")
 	}
-	bolt := &BoltKeyStoreStorage{db: db, serviceKey: keyBytes}
+	bolt := &Storage{db: db, serviceKey: keyBytes}
 
 	// first, store the service key
 	if err = bolt.storeServiceKey(key); err != nil {
@@ -39,24 +58,24 @@ func NewBoltKeyStoreStorage(db *storage.BoltDB, key ServiceKey) (*BoltKeyStoreSt
 }
 
 // TODO(gabe): support more robust service key operations, including rotation, and caching
-func (b *BoltKeyStoreStorage) storeServiceKey(key ServiceKey) error {
+func (kss *Storage) storeServiceKey(key ServiceKey) error {
 	keyBytes, err := json.Marshal(key)
 	if err != nil {
 		return util.LoggingErrorMsg(err, "could not marshal service key")
 	}
-	if err = b.db.Write(namespace, skKey, keyBytes); err != nil {
+	if err = kss.db.Write(namespace, skKey, keyBytes); err != nil {
 		return util.LoggingErrorMsg(err, "could store marshal service key")
 	}
 	return nil
 }
 
 // getAndSetServiceKey attempts to get the service key from memory, and if not available rehydrates it from the DB
-func (b *BoltKeyStoreStorage) getAndSetServiceKey() ([]byte, error) {
-	if len(b.serviceKey) != 0 {
-		return b.serviceKey, nil
+func (kss *Storage) getAndSetServiceKey() ([]byte, error) {
+	if len(kss.serviceKey) != 0 {
+		return kss.serviceKey, nil
 	}
 
-	storedKeyBytes, err := b.db.Read(namespace, skKey)
+	storedKeyBytes, err := kss.db.Read(namespace, skKey)
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not get service key")
 	}
@@ -74,11 +93,11 @@ func (b *BoltKeyStoreStorage) getAndSetServiceKey() ([]byte, error) {
 		return nil, errors.Wrap(err, "could not decode service key")
 	}
 
-	b.serviceKey = keyBytes
+	kss.serviceKey = keyBytes
 	return keyBytes, nil
 }
 
-func (b *BoltKeyStoreStorage) StoreKey(key StoredKey) error {
+func (kss *Storage) StoreKey(key StoredKey) error {
 	id := key.ID
 	if id == "" {
 		return util.LoggingNewError("could not store key without an ID")
@@ -90,7 +109,7 @@ func (b *BoltKeyStoreStorage) StoreKey(key StoredKey) error {
 	}
 
 	// get service key
-	serviceKey, err := b.getAndSetServiceKey()
+	serviceKey, err := kss.getAndSetServiceKey()
 	if err != nil {
 		return util.LoggingErrorMsgf(err, "could not get service key while storing key: %s", id)
 	}
@@ -101,11 +120,11 @@ func (b *BoltKeyStoreStorage) StoreKey(key StoredKey) error {
 		return util.LoggingErrorMsgf(err, "could not encrypt key: %s", key.ID)
 	}
 
-	return b.db.Write(namespace, id, encryptedKey)
+	return kss.db.Write(namespace, id, encryptedKey)
 }
 
-func (b *BoltKeyStoreStorage) GetKey(id string) (*StoredKey, error) {
-	storedKeyBytes, err := b.db.Read(namespace, id)
+func (kss *Storage) GetKey(id string) (*StoredKey, error) {
+	storedKeyBytes, err := kss.db.Read(namespace, id)
 	if err != nil {
 		return nil, util.LoggingErrorMsgf(err, "could not get key details for key: %s", id)
 	}
@@ -114,7 +133,7 @@ func (b *BoltKeyStoreStorage) GetKey(id string) (*StoredKey, error) {
 	}
 
 	// get service key
-	serviceKey, err := b.getAndSetServiceKey()
+	serviceKey, err := kss.getAndSetServiceKey()
 	if err != nil {
 		return nil, util.LoggingErrorMsgf(err, "could not get service key while getting key: %s", id)
 	}
@@ -132,8 +151,8 @@ func (b *BoltKeyStoreStorage) GetKey(id string) (*StoredKey, error) {
 	return &stored, nil
 }
 
-func (b *BoltKeyStoreStorage) GetKeyDetails(id string) (*KeyDetails, error) {
-	stored, err := b.GetKey(id)
+func (kss *Storage) GetKeyDetails(id string) (*KeyDetails, error) {
+	stored, err := kss.GetKey(id)
 	if err != nil {
 		return nil, util.LoggingErrorMsgf(err, "could not get key details for key: %s", id)
 	}
diff --git a/pkg/service/keystore/storage/storage.go b/pkg/service/keystore/storage/storage.go
deleted file mode 100644
index 0ef048b..0000000
--- a/pkg/service/keystore/storage/storage.go
+++ /dev/null
@@ -1,56 +0,0 @@
-package storage
-
-import (
-	"github.com/TBD54566975/ssi-sdk/crypto"
-
-	"github.com/tbd54566975/ssi-service/internal/util"
-	"github.com/tbd54566975/ssi-service/pkg/storage"
-)
-
-// StoredKey represents a common data model to store data on all key types
-type StoredKey struct {
-	ID         string         `json:"id"`
-	Controller string         `json:"controller"`
-	KeyType    crypto.KeyType `json:"keyType"`
-	Base58Key  string         `json:"key"`
-	CreatedAt  string         `json:"createdAt"`
-}
-
-// KeyDetails represents a common data model to get information about a key, without revealing the key itself
-type KeyDetails struct {
-	ID         string         `json:"id"`
-	Controller string         `json:"controller"`
-	KeyType    crypto.KeyType `json:"keyType"`
-	CreatedAt  string         `json:"createdAt"`
-}
-
-type ServiceKey struct {
-	Base58Key  string
-	Base58Salt string
-}
-
-type Storage interface {
-	StoreKey(key StoredKey) error
-	GetKey(id string) (*StoredKey, error)
-	GetKeyDetails(id string) (*KeyDetails, error)
-}
-
-func NewKeyStoreStorage(s storage.ServiceStorage, serviceKey, serviceKeySalt string) (Storage, error) {
-	switch s.Type() {
-	case storage.Bolt:
-		gotBolt, ok := s.(*storage.BoltDB)
-		if !ok {
-			return nil, util.LoggingNewErrorf("trouble instantiating : %s", s.Type())
-		}
-		boltStorage, err := NewBoltKeyStoreStorage(gotBolt, ServiceKey{
-			Base58Key:  serviceKey,
-			Base58Salt: serviceKeySalt,
-		})
-		if err != nil {
-			return nil, util.LoggingErrorMsg(err, "could not instantiate key store bolt storage")
-		}
-		return boltStorage, err
-	default:
-		return nil, util.LoggingNewErrorf("unsupported storage type: %s", s.Type())
-	}
-}
diff --git a/pkg/service/manifest/service.go b/pkg/service/manifest/service.go
index 1f6e622..99a1ba3 100644
--- a/pkg/service/manifest/service.go
+++ b/pkg/service/manifest/service.go
@@ -15,12 +15,11 @@ import (
 	"github.com/tbd54566975/ssi-service/pkg/service/credential"
 	"github.com/tbd54566975/ssi-service/pkg/service/framework"
 	"github.com/tbd54566975/ssi-service/pkg/service/keystore"
-	manifeststorage "github.com/tbd54566975/ssi-service/pkg/service/manifest/storage"
 	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
 
 type Service struct {
-	storage manifeststorage.Storage
+	storage *Storage
 	config  config.ManifestServiceConfig
 
 	// external dependencies
@@ -61,7 +60,7 @@ func (s Service) Config() config.ManifestServiceConfig {
 }
 
 func NewManifestService(config config.ManifestServiceConfig, s storage.ServiceStorage, keyStore *keystore.Service, didResolver *didsdk.Resolver, credential *credential.Service) (*Service, error) {
-	manifestStorage, err := manifeststorage.NewManifestStorage(s)
+	manifestStorage, err := NewManifestStorage(s)
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not instantiate storage for the manifest service")
 	}
@@ -139,7 +138,7 @@ func (s Service) CreateManifest(request CreateManifestRequest) (*CreateManifestR
 	}
 
 	// store the manifest
-	storageRequest := manifeststorage.StoredManifest{
+	storageRequest := StoredManifest{
 		ID:          m.ID,
 		Issuer:      m.Issuer.ID,
 		Manifest:    *m,
@@ -243,7 +242,7 @@ func (s Service) ProcessApplicationSubmission(request SubmitApplicationRequest)
 
 	// store the application
 	applicantDID := request.ApplicantDID
-	storageRequest := manifeststorage.StoredApplication{
+	storageRequest := StoredApplication{
 		ID:             applicationID,
 		ManifestID:     manifestID,
 		ApplicantDID:   applicantDID,
@@ -274,7 +273,7 @@ func (s Service) ProcessApplicationSubmission(request SubmitApplicationRequest)
 	}
 
 	// store the response we've generated
-	storeResponseRequest := manifeststorage.StoredResponse{
+	storeResponseRequest := StoredResponse{
 		ID:           credResp.ID,
 		ManifestID:   manifestID,
 		ApplicantDID: applicantDID,
diff --git a/pkg/service/manifest/storage/bolt.go b/pkg/service/manifest/storage.go
similarity index 62%
rename from pkg/service/manifest/storage/bolt.go
rename to pkg/service/manifest/storage.go
index 27273fb..1083e0d 100644
--- a/pkg/service/manifest/storage/bolt.go
+++ b/pkg/service/manifest/storage.go
@@ -1,4 +1,4 @@
-package storage
+package manifest
 
 import (
 	"fmt"
@@ -7,6 +7,10 @@ import (
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 
+	"github.com/TBD54566975/ssi-sdk/credential/manifest"
+
+	cred "github.com/tbd54566975/ssi-service/internal/credential"
+	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 	"github.com/tbd54566975/ssi-service/internal/util"
 	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
@@ -17,18 +21,43 @@ const (
 	responseNamespace    = "response"
 )
 
-type BoltManifestStorage struct {
-	db *storage.BoltDB
+type StoredManifest struct {
+	ID          string                      `json:"id"`
+	Issuer      string                      `json:"issuer"`
+	Manifest    manifest.CredentialManifest `json:"manifest"`
+	ManifestJWT keyaccess.JWT               `json:"manifestJwt"`
+}
+
+type StoredApplication struct {
+	ID             string                         `json:"id"`
+	ManifestID     string                         `json:"manifestId"`
+	ApplicantDID   string                         `json:"applicantDid"`
+	Application    manifest.CredentialApplication `json:"application"`
+	Credentials    []cred.Container               `json:"credentials"`
+	ApplicationJWT keyaccess.JWT                  `json:"applicationJwt"`
+}
+
+type StoredResponse struct {
+	ID           string                      `json:"id"`
+	ManifestID   string                      `json:"manifestId"`
+	ApplicantDID string                      `json:"applicantId"`
+	Response     manifest.CredentialResponse `json:"response"`
+	Credentials  []cred.Container            `json:"credentials"`
+	ResponseJWT  keyaccess.JWT               `json:"responseJwt"`
+}
+
+type Storage struct {
+	db storage.ServiceStorage
 }
 
-func NewBoltManifestStorage(db *storage.BoltDB) (*BoltManifestStorage, error) {
+func NewManifestStorage(db storage.ServiceStorage) (*Storage, error) {
 	if db == nil {
 		return nil, errors.New("bolt db reference is nil")
 	}
-	return &BoltManifestStorage{db: db}, nil
+	return &Storage{db: db}, nil
 }
 
-func (b BoltManifestStorage) StoreManifest(manifest StoredManifest) error {
+func (ms *Storage) StoreManifest(manifest StoredManifest) error {
 	id := manifest.Manifest.ID
 	if id == "" {
 		err := errors.New("could not store manifest without an ID")
@@ -41,11 +70,11 @@ func (b BoltManifestStorage) StoreManifest(manifest StoredManifest) error {
 		logrus.WithError(err).Error(errMsg)
 		return errors.Wrapf(err, errMsg)
 	}
-	return b.db.Write(manifestNamespace, id, manifestBytes)
+	return ms.db.Write(manifestNamespace, id, manifestBytes)
 }
 
-func (b BoltManifestStorage) GetManifest(id string) (*StoredManifest, error) {
-	manifestBytes, err := b.db.Read(manifestNamespace, id)
+func (ms *Storage) GetManifest(id string) (*StoredManifest, error) {
+	manifestBytes, err := ms.db.Read(manifestNamespace, id)
 	if err != nil {
 		errMsg := fmt.Sprintf("could not get manifest: %s", id)
 		logrus.WithError(err).Error(errMsg)
@@ -66,8 +95,8 @@ func (b BoltManifestStorage) GetManifest(id string) (*StoredManifest, error) {
 }
 
 // GetManifests attempts to get all stored manifests. It will return those it can even if it has trouble with some.
-func (b BoltManifestStorage) GetManifests() ([]StoredManifest, error) {
-	gotManifests, err := b.db.ReadAll(manifestNamespace)
+func (ms *Storage) GetManifests() ([]StoredManifest, error) {
+	gotManifests, err := ms.db.ReadAll(manifestNamespace)
 	if err != nil {
 		errMsg := "could not get all manifests"
 		logrus.WithError(err).Error(errMsg)
@@ -87,14 +116,14 @@ func (b BoltManifestStorage) GetManifests() ([]StoredManifest, error) {
 	return stored, nil
 }
 
-func (b BoltManifestStorage) DeleteManifest(id string) error {
-	if err := b.db.Delete(manifestNamespace, id); err != nil {
+func (ms *Storage) DeleteManifest(id string) error {
+	if err := ms.db.Delete(manifestNamespace, id); err != nil {
 		return util.LoggingErrorMsgf(err, "could not delete manifest: %s", id)
 	}
 	return nil
 }
 
-func (b BoltManifestStorage) StoreApplication(application StoredApplication) error {
+func (ms *Storage) StoreApplication(application StoredApplication) error {
 	id := application.Application.ID
 	if id == "" {
 		return util.LoggingNewError("could not store application without an ID")
@@ -103,11 +132,11 @@ func (b BoltManifestStorage) StoreApplication(application StoredApplication) err
 	if err != nil {
 		return util.LoggingErrorMsgf(err, "could not store application: %s", id)
 	}
-	return b.db.Write(applicationNamespace, id, applicationBytes)
+	return ms.db.Write(applicationNamespace, id, applicationBytes)
 }
 
-func (b BoltManifestStorage) GetApplication(id string) (*StoredApplication, error) {
-	applicationBytes, err := b.db.Read(applicationNamespace, id)
+func (ms *Storage) GetApplication(id string) (*StoredApplication, error) {
+	applicationBytes, err := ms.db.Read(applicationNamespace, id)
 	if err != nil {
 		return nil, util.LoggingErrorMsgf(err, "could not get application: %s", id)
 	}
@@ -122,8 +151,8 @@ func (b BoltManifestStorage) GetApplication(id string) (*StoredApplication, erro
 }
 
 // GetApplications attempts to get all stored applications. It will return those it can even if it has trouble with some.
-func (b BoltManifestStorage) GetApplications() ([]StoredApplication, error) {
-	gotApplications, err := b.db.ReadAll(applicationNamespace)
+func (ms *Storage) GetApplications() ([]StoredApplication, error) {
+	gotApplications, err := ms.db.ReadAll(applicationNamespace)
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not get all applications")
 	}
@@ -143,14 +172,14 @@ func (b BoltManifestStorage) GetApplications() ([]StoredApplication, error) {
 	return stored, nil
 }
 
-func (b BoltManifestStorage) DeleteApplication(id string) error {
-	if err := b.db.Delete(applicationNamespace, id); err != nil {
+func (ms *Storage) DeleteApplication(id string) error {
+	if err := ms.db.Delete(applicationNamespace, id); err != nil {
 		return util.LoggingErrorMsgf(err, "could not delete application: %s", id)
 	}
 	return nil
 }
 
-func (b BoltManifestStorage) StoreResponse(response StoredResponse) error {
+func (ms *Storage) StoreResponse(response StoredResponse) error {
 	id := response.Response.ID
 	if id == "" {
 		return util.LoggingNewError("could not store response without an ID")
@@ -159,11 +188,11 @@ func (b BoltManifestStorage) StoreResponse(response StoredResponse) error {
 	if err != nil {
 		return util.LoggingErrorMsgf(err, "could not store response: %s", id)
 	}
-	return b.db.Write(responseNamespace, id, responseBytes)
+	return ms.db.Write(responseNamespace, id, responseBytes)
 }
 
-func (b BoltManifestStorage) GetResponse(id string) (*StoredResponse, error) {
-	responseBytes, err := b.db.Read(responseNamespace, id)
+func (ms *Storage) GetResponse(id string) (*StoredResponse, error) {
+	responseBytes, err := ms.db.Read(responseNamespace, id)
 	if err != nil {
 		return nil, util.LoggingErrorMsgf(err, "could not get response: %s", id)
 	}
@@ -178,8 +207,8 @@ func (b BoltManifestStorage) GetResponse(id string) (*StoredResponse, error) {
 }
 
 // GetResponses attempts to get all stored responses. It will return those it can even if it has trouble with some.
-func (b BoltManifestStorage) GetResponses() ([]StoredResponse, error) {
-	gotResponses, err := b.db.ReadAll(responseNamespace)
+func (ms *Storage) GetResponses() ([]StoredResponse, error) {
+	gotResponses, err := ms.db.ReadAll(responseNamespace)
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not get all responses")
 	}
@@ -199,8 +228,8 @@ func (b BoltManifestStorage) GetResponses() ([]StoredResponse, error) {
 	return stored, nil
 }
 
-func (b BoltManifestStorage) DeleteResponse(id string) error {
-	if err := b.db.Delete(responseNamespace, id); err != nil {
+func (ms *Storage) DeleteResponse(id string) error {
+	if err := ms.db.Delete(responseNamespace, id); err != nil {
 		return util.LoggingErrorMsgf(err, "could not delete response: %s", id)
 	}
 	return nil
diff --git a/pkg/service/manifest/storage/storage.go b/pkg/service/manifest/storage/storage.go
deleted file mode 100644
index f3c5b69..0000000
--- a/pkg/service/manifest/storage/storage.go
+++ /dev/null
@@ -1,80 +0,0 @@
-package storage
-
-import (
-	"github.com/TBD54566975/ssi-sdk/credential/manifest"
-
-	cred "github.com/tbd54566975/ssi-service/internal/credential"
-	"github.com/tbd54566975/ssi-service/internal/keyaccess"
-	"github.com/tbd54566975/ssi-service/internal/util"
-	"github.com/tbd54566975/ssi-service/pkg/storage"
-)
-
-type StoredManifest struct {
-	ID          string                      `json:"id"`
-	Issuer      string                      `json:"issuer"`
-	Manifest    manifest.CredentialManifest `json:"manifest"`
-	ManifestJWT keyaccess.JWT               `json:"manifestJwt"`
-}
-
-type StoredApplication struct {
-	ID             string                         `json:"id"`
-	ManifestID     string                         `json:"manifestId"`
-	ApplicantDID   string                         `json:"applicantDid"`
-	Application    manifest.CredentialApplication `json:"application"`
-	Credentials    []cred.Container               `json:"credentials"`
-	ApplicationJWT keyaccess.JWT                  `json:"applicationJwt"`
-}
-
-type StoredResponse struct {
-	ID           string                      `json:"id"`
-	ManifestID   string                      `json:"manifestId"`
-	ApplicantDID string                      `json:"applicantId"`
-	Response     manifest.CredentialResponse `json:"response"`
-	Credentials  []cred.Container            `json:"credentials"`
-	ResponseJWT  keyaccess.JWT               `json:"responseJwt"`
-}
-
-type Storage interface {
-	CredentialManifestStorage
-	CredentialApplicationStorage
-	CredentialResponseStorage
-}
-
-type CredentialManifestStorage interface {
-	StoreManifest(manifest StoredManifest) error
-	GetManifest(id string) (*StoredManifest, error)
-	GetManifests() ([]StoredManifest, error)
-	DeleteManifest(id string) error
-}
-
-type CredentialApplicationStorage interface {
-	StoreApplication(application StoredApplication) error
-	GetApplication(id string) (*StoredApplication, error)
-	GetApplications() ([]StoredApplication, error)
-	DeleteApplication(id string) error
-}
-
-type CredentialResponseStorage interface {
-	StoreResponse(response StoredResponse) error
-	GetResponse(id string) (*StoredResponse, error)
-	GetResponses() ([]StoredResponse, error)
-	DeleteResponse(id string) error
-}
-
-// NewManifestStorage finds the manifest storage impl for a given ServiceStorage value
-func NewManifestStorage(s storage.ServiceStorage) (Storage, error) {
-	switch s.Type() {
-	case storage.Bolt:
-		gotBolt, ok := s.(*storage.BoltDB)
-		if !ok {
-			return nil, util.LoggingNewErrorf("trouble instantiating : %s", s.Type())
-		}
-		boltStorage, err := NewBoltManifestStorage(gotBolt)
-		if err != nil {
-			return nil, util.LoggingErrorMsg(err, "could not instantiate manifest bolt storage")
-		}
-		return boltStorage, err
-	default:
-		return nil, util.LoggingNewErrorf("unsupported storage type: %s", s.Type())
-	}
-}
diff --git a/pkg/service/operation/model.go b/pkg/service/operation/model.go
index fef7c62..d3e5c7a 100644
--- a/pkg/service/operation/model.go
+++ b/pkg/service/operation/model.go
@@ -1,11 +1,7 @@
 package operation
 
 import (
-	"fmt"
-	"strings"
-
 	"github.com/TBD54566975/ssi-sdk/util"
-	"github.com/tbd54566975/ssi-service/pkg/service/operation/storage"
 	"go.einride.tech/aip/filtering"
 )
 
@@ -20,16 +16,6 @@ type Operation struct {
 	Result Result `json:"result,omitempty"`
 }
 
-// SubmissionID attempts to parse the submission id from the ID of the operation. This is done by taking the last word
-// that results from splitting the id by "/". On failures, the empty string is returned.
-func SubmissionID(opID string) string {
-	i := strings.LastIndex(opID, "/")
-	if i == -1 {
-		return ""
-	}
-	return opID[(i + 1):]
-}
-
 type GetOperationsRequest struct {
 	Parent string `validate:"required"`
 	Filter filtering.Filter
@@ -52,7 +38,11 @@ func (r GetOperationRequest) Validate() error {
 	return util.NewValidator().Struct(r)
 }
 
-// IDFromSubmissionID returns a submission operation ID from the submission ID.
-func IDFromSubmissionID(id string) string {
-	return fmt.Sprintf("%s/%s", storage.SubmissionParentResource, id)
+type CancelOperationRequest struct {
+	ID string `json:"id" validate:"required"`
+}
+
+// Validate does struct validation and returns an error when invalid.
+func (r CancelOperationRequest) Validate() error {
+	return util.NewValidator().Struct(r)
 }
diff --git a/pkg/service/operation/service.go b/pkg/service/operation/service.go
index 71ab243..09dad33 100644
--- a/pkg/service/operation/service.go
+++ b/pkg/service/operation/service.go
@@ -11,13 +11,14 @@ import (
 	"github.com/tbd54566975/ssi-service/internal/util"
 	"github.com/tbd54566975/ssi-service/pkg/service/framework"
 	opstorage "github.com/tbd54566975/ssi-service/pkg/service/operation/storage"
+	"github.com/tbd54566975/ssi-service/pkg/service/operation/submission"
 	"github.com/tbd54566975/ssi-service/pkg/service/presentation/model"
 	prestorage "github.com/tbd54566975/ssi-service/pkg/service/presentation/storage"
 	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
 
 type Service struct {
-	storage opstorage.Storage
+	storage *Storage
 }
 
 func (s Service) Type() framework.Type {
@@ -58,15 +59,15 @@ func (s Service) GetOperations(request GetOperationsRequest) (*GetOperationsResp
 			logrus.WithError(err).WithField("operation_id", op.ID).Error("converting to storage operations to model")
 			continue
 		}
-		resp.Operations[i] = newOp
+		resp.Operations[i] = *newOp
 	}
 	return resp, nil
 }
 
 type ServiceModelFunc func(any) any
 
-func serviceModel(op opstorage.StoredOperation) (Operation, error) {
-	newOp := Operation{
+func serviceModel(op opstorage.StoredOperation) (*Operation, error) {
+	newOp := &Operation{
 		ID:   op.ID,
 		Done: op.Done,
 		Result: Result{
@@ -76,34 +77,46 @@ func serviceModel(op opstorage.StoredOperation) (Operation, error) {
 
 	if len(op.Response) > 0 {
 		switch {
-		case strings.HasPrefix(op.ID, opstorage.SubmissionParentResource):
+		case strings.HasPrefix(op.ID, submission.ParentResource):
 			var s prestorage.StoredSubmission
 			if err := json.Unmarshal(op.Response, &s); err != nil {
-				return Operation{}, err
+				return nil, err
 			}
 			newOp.Result.Response = model.ServiceModel(&s)
 		default:
-			return newOp, errors.New("unknown response type")
+			return nil, errors.New("unknown response type")
 		}
 	}
 
 	return newOp, nil
 }
 
-func (s Service) GetOperation(request GetOperationRequest) (Operation, error) {
+func (s Service) GetOperation(request GetOperationRequest) (*Operation, error) {
 	if err := request.Validate(); err != nil {
-		return Operation{}, errors.Wrap(err, "invalid request")
+		return nil, errors.Wrap(err, "invalid request")
 	}
 
 	storedOp, err := s.storage.GetOperation(request.ID)
 	if err != nil {
-		return Operation{}, errors.Wrap(err, "fetching from storage")
+		return nil, errors.Wrap(err, "fetching from storage")
 	}
 	return serviceModel(storedOp)
 }
 
+func (s Service) CancelOperation(request CancelOperationRequest) (*Operation, error) {
+	if err := request.Validate(); err != nil {
+		return nil, errors.Wrap(err, "invalid request")
+	}
+
+	storedOp, err := s.storage.CancelOperation(request.ID)
+	if err != nil {
+		return nil, errors.Wrap(err, "marking as done")
+	}
+	return serviceModel(*storedOp)
+}
+
 func NewOperationService(s storage.ServiceStorage) (*Service, error) {
-	opStorage, err := opstorage.NewOperationStorage(s)
+	opStorage, err := NewOperationStorage(s)
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "creating operation storage")
 	}
diff --git a/pkg/service/operation/storage.go b/pkg/service/operation/storage.go
new file mode 100644
index 0000000..57c2a21
--- /dev/null
+++ b/pkg/service/operation/storage.go
@@ -0,0 +1,116 @@
+package operation
+
+import (
+	"strings"
+
+	"github.com/goccy/go-json"
+	"github.com/pkg/errors"
+	"github.com/sirupsen/logrus"
+	"github.com/tbd54566975/ssi-service/internal/util"
+	opstorage "github.com/tbd54566975/ssi-service/pkg/service/operation/storage"
+	"github.com/tbd54566975/ssi-service/pkg/service/operation/storage/namespace"
+	"github.com/tbd54566975/ssi-service/pkg/service/operation/submission"
+	"github.com/tbd54566975/ssi-service/pkg/storage"
+	"go.einride.tech/aip/filtering"
+)
+
+const (
+	cancelledReason = "operation cancelled"
+)
+
+type Storage struct {
+	db storage.ServiceStorage
+}
+
+func (b Storage) CancelOperation(id string) (*opstorage.StoredOperation, error) {
+	if strings.HasPrefix(id, submission.ParentResource) {
+		_, opData, err := b.db.UpdateValueAndOperation(
+			submission.Namespace, submission.ID(id), storage.NewUpdater(map[string]any{
+				"status": submission.StatusCancelled,
+				"reason": cancelledReason,
+			}),
+			namespace.FromID(id), id, submission.OperationUpdater{
+				UpdaterWithMap: storage.NewUpdater(map[string]any{
+					"done": true,
+				}),
+			})
+		if err != nil {
+			return nil, errors.Wrap(err, "updating value and op")
+		}
+		var op opstorage.StoredOperation
+		if err = json.Unmarshal(opData, &op); err != nil {
+			return nil, errors.Wrap(err, "unmarshalling data")
+		}
+		return &op, nil
+	}
+	return nil, errors.New("unrecognized id structure")
+}
+
+func (b Storage) StoreOperation(op opstorage.StoredOperation) error {
+	id := op.ID
+	if id == "" {
+		return util.LoggingNewError("ID is required for storing operations")
+	}
+	jsonBytes, err := json.Marshal(op)
+	if err != nil {
+		return util.LoggingErrorMsgf(err, "marshalling operation with id: %s", id)
+	}
+	if err = b.db.Write(namespace.FromID(id), id, jsonBytes); err != nil {
+		return util.LoggingErrorMsg(err, "writing to db")
+	}
+	return nil
+}
+
+func (b Storage) GetOperation(id string) (opstorage.StoredOperation, error) {
+	var stored opstorage.StoredOperation
+	jsonBytes, err := b.db.Read(namespace.FromID(id), id)
+	if err != nil {
+		return stored, util.LoggingErrorMsgf(err, "reading operation with id: %s", id)
+	}
+	if len(jsonBytes) == 0 {
+		return stored, util.LoggingNewErrorf("operation not found with id: %s", id)
+	}
+	if err := json.Unmarshal(jsonBytes, &stored); err != nil {
+		return stored, util.LoggingErrorMsgf(err, "unmarshalling stored operation: %s", id)
+	}
+	return stored, nil
+}
+
+func (b Storage) GetOperations(parent string, filter filtering.Filter) ([]opstorage.StoredOperation, error) {
+	operations, err := b.db.ReadAll(namespace.FromParent(parent))
+	if err != nil {
+		return nil, util.LoggingErrorMsgf(err, "could not get all operations")
+	}
+
+	shouldInclude, err := storage.NewIncludeFunc(filter)
+	if err != nil {
+		return nil, err
+	}
+	stored := make([]opstorage.StoredOperation, 0, len(operations))
+	for i, manifestBytes := range operations {
+		var nextOp opstorage.StoredOperation
+		if err = json.Unmarshal(manifestBytes, &nextOp); err != nil {
+			logrus.WithError(err).WithField("idx", i).Warnf("Skipping operation")
+		}
+		include, err := shouldInclude(nextOp)
+		// We explicitly ignore evaluation errors and simply include them in the result.
+		if err != nil || include {
+			stored = append(stored, nextOp)
+		}
+	}
+	return stored, nil
+}
+
+func (b Storage) DeleteOperation(id string) error {
+	if err := b.db.Delete(namespace.FromID(id), id); err != nil {
+		return util.LoggingErrorMsgf(err, "deleting operation: %s", id)
+	}
+	return nil
+}
+
+func NewOperationStorage(db storage.ServiceStorage) (*Storage, error) {
+	if db == nil {
+		return nil, errors.New("bolt db reference is nil")
+	}
+	return &Storage{db: db}, nil
+}
diff --git a/pkg/service/operation/storage/bolt.go b/pkg/service/operation/storage/bolt.go
deleted file mode 100644
index 4952bbe..0000000
--- a/pkg/service/operation/storage/bolt.go
+++ /dev/null
@@ -1,112 +0,0 @@
-package storage
-
-import (
-	"strings"
-
-	"github.com/goccy/go-json"
-	"github.com/pkg/errors"
-	"github.com/sirupsen/logrus"
-	"github.com/tbd54566975/ssi-service/internal/util"
-	"github.com/tbd54566975/ssi-service/pkg/storage"
-	"go.einride.tech/aip/filtering"
-)
-
-const (
-	namespace = "operation_submission"
-)
-
-const SubmissionParentResource = "/presentations/submissions"
-
-// NamespaceFromID returns a namespace from a given operation ID. An empty string is returned when the namespace cannot
-// be determined.
-func NamespaceFromID(id string) string {
-	i := strings.LastIndex(id, "/")
-	if i == -1 {
-		return ""
-	}
-	return namespaceFromParent(id[:i])
-}
-
-func namespaceFromParent(parent string) string {
-	switch parent {
-	case SubmissionParentResource:
-		return namespace
-	default:
-		return ""
-	}
-}
-
-type BoltOperationStorage struct {
-	db *storage.BoltDB
-}
-
-func (b BoltOperationStorage) StoreOperation(op StoredOperation) error {
-	id := op.ID
-	if id == "" {
-		return util.LoggingNewError("ID is required for storing operations")
-	}
-	jsonBytes, err := json.Marshal(op)
-	if err != nil {
-		return util.LoggingErrorMsgf(err, "marshalling operation with id: %s", id)
-	}
-	return b.db.Write(NamespaceFromID(id), id, jsonBytes)
-}
-
-func (b BoltOperationStorage) GetOperation(id string) (StoredOperation, error) {
-	var stored StoredOperation
-	jsonBytes, err := b.db.Read(NamespaceFromID(id), id)
-	if err != nil {
-		return stored, util.LoggingErrorMsgf(err, "reading operation with id: %s", id)
-	}
-	if len(jsonBytes) == 0 {
-		return stored, util.LoggingNewErrorf("operation not found with id: %s", id)
-	}
-	if err := json.Unmarshal(jsonBytes, &stored); err != nil {
-		return stored, util.LoggingErrorMsgf(err, "unmarshalling stored operation: %s", id)
-	}
-	return stored, nil
-}
-
-func (b BoltOperationStorage) GetOperations(parent string, filter filtering.Filter) ([]StoredOperation, error) {
-	operations, err := b.db.ReadAll(namespaceFromParent(parent))
-	if err != nil {
-		return nil, util.LoggingErrorMsgf(err, "could not get all operations")
-	}
-
-	shouldInclude, err := storage.NewIncludeFunc(filter)
-	if err != nil {
-		return nil, err
-	}
-	stored := make([]StoredOperation, 0, len(operations))
-	for i, manifestBytes := range operations {
-		var nextOp StoredOperation
-		if err = json.Unmarshal(manifestBytes, &nextOp); err != nil {
-			logrus.WithError(err).WithField("idx", i).Warnf("Skipping operation")
-		}
-		include, err := shouldInclude(nextOp)
-		// We explicitly ignore evaluation errors and simply include them in the result.
-		if err != nil {
-			stored = append(stored, nextOp)
-			continue
-		}
-		if include {
-			stored = append(stored, nextOp)
-		}
-	}
-	return stored, nil
-}
-
-func (b BoltOperationStorage) DeleteOperation(id string) error {
-	if err := b.db.Delete(NamespaceFromID(id), id); err != nil {
-		return util.LoggingErrorMsgf(err, "deleting operation: %s", id)
-	}
-	return nil
-}
-
-func NewBoltOperationStorage(db *storage.BoltDB) (*BoltOperationStorage, error) {
-	if db == nil {
-		return nil, errors.New("bolt db reference is nil")
-	}
-	return &BoltOperationStorage{db: db}, nil
-
-}
diff --git a/pkg/service/operation/storage/namespace/namespace.go b/pkg/service/operation/storage/namespace/namespace.go
new file mode 100644
index 0000000..6198e93
--- /dev/null
+++ b/pkg/service/operation/storage/namespace/namespace.go
@@ -0,0 +1,30 @@
+package namespace
+
+import (
+	"strings"
+
+	"github.com/tbd54566975/ssi-service/pkg/service/operation/submission"
+)
+
+const namespace = "operation_submission"
+
+// FromID returns a namespace from a given operation ID. An empty string is returned when the namespace cannot
+// be determined.
+func FromID(id string) string {
+	i := strings.LastIndex(id, "/")
+	if i == -1 {
+		return ""
+	}
+	return FromParent(id[:i])
+}
+
+// FromParent returns a namespace from a given parent resource name like "/presentations/submissions". Empty is returned
+// when the parent resource cannot be resolved.
+func FromParent(parent string) string {
+	switch parent {
+	case submission.ParentResource:
+		return namespace
+	default:
+		return ""
+	}
+}
diff --git a/pkg/service/operation/storage/storage.go b/pkg/service/operation/storage/storage.go
index e4e9b3c..d56f4d9 100644
--- a/pkg/service/operation/storage/storage.go
+++ b/pkg/service/operation/storage/storage.go
@@ -1,8 +1,6 @@
 package storage
 
 import (
-	"github.com/tbd54566975/ssi-service/internal/util"
-	"github.com/tbd54566975/ssi-service/pkg/storage"
 	"go.einride.tech/aip/filtering"
 )
 
@@ -35,21 +33,5 @@ type Storage interface {
 	GetOperation(id string) (StoredOperation, error)
 	GetOperations(parent string, filter filtering.Filter) ([]StoredOperation, error)
 	DeleteOperation(id string) error
-}
-
-func NewOperationStorage(s storage.ServiceStorage) (Storage, error) {
-	switch s.Type() {
-	case storage.Bolt:
-		gotBolt, ok := s.(*storage.BoltDB)
-		if !ok {
-			return nil, util.LoggingNewErrorf("trouble instantiating : %s", s.Type())
-		}
-		boltStorage, err := NewBoltOperationStorage(gotBolt)
-		if err != nil {
-			return nil, util.LoggingErrorMsg(err, "could not instantiate schema bolt storage")
-		}
-		return boltStorage, err
-	default:
-		return nil, util.LoggingNewErrorf("unsupported storage type: %s", s.Type())
-	}
+	CancelOperation(id string) (*StoredOperation, error)
 }
diff --git a/pkg/service/operation/submission/submission.go b/pkg/service/operation/submission/submission.go
new file mode 100644
index 0000000..94adf35
--- /dev/null
+++ b/pkg/service/operation/submission/submission.go
@@ -0,0 +1,87 @@
+package submission
+
+import (
+	"fmt"
+	"strings"
+
+	"github.com/goccy/go-json"
+	"github.com/pkg/errors"
+	opstorage "github.com/tbd54566975/ssi-service/pkg/service/operation/storage"
+	"github.com/tbd54566975/ssi-service/pkg/storage"
+)
+
+// IDFromSubmissionID returns a submission operation ID from the submission ID.
+func IDFromSubmissionID(id string) string {
+	return fmt.Sprintf("%s/%s", ParentResource, id)
+}
+
+// ID attempts to parse the submission id from the ID of the operation. This is done by taking the last word
+// that results from splitting the id by "/". On failures, the empty string is returned.
+func ID(opID string) string {
+	i := strings.LastIndex(opID, "/")
+	if i == -1 {
+		return ""
+	}
+	return opID[(i + 1):]
+}
+
+const (
+	// Namespace is the namespace to be used for storing submissions.
+	Namespace = "presentation_submission"
+	// ParentResource is the prefix of the submission parent resource.
+	ParentResource = "/presentations/submissions"
+)
+
+// Status indicates the current state of a submission.
+type Status uint8
+
+func (s Status) String() string {
+	switch s {
+	case StatusPending:
+		return "pending"
+	case StatusDenied:
+		return "denied"
+	case StatusApproved:
+		return "approved"
+	case StatusCancelled:
+		return "cancelled"
+	default:
+		return "unknown"
+	}
+}
+
+const (
+	StatusUnknown Status = iota
+	StatusPending
+	StatusCancelled
+	StatusDenied
+	StatusApproved
+)
+
+// OperationUpdater is an implementation of the storage.ResponseSettingUpdater. It's provides a way to update the
+// operation and submission within a single transaction.
+type OperationUpdater struct {
+	storage.UpdaterWithMap
+}
+
+func (u OperationUpdater) SetUpdatedResponse(response []byte) {
+	if u.UpdaterWithMap.Values == nil {
+		return
+	}
+	u.UpdaterWithMap.Values["response"] = response
+}
+
+func (u OperationUpdater) Validate(v []byte) error {
+	var op opstorage.StoredOperation
+	if err := json.Unmarshal(v, &op); err != nil {
+		return errors.Wrap(err, "unmarshalling operation")
+	}
+
+	if op.Done {
+		return errors.New("operation already marked as done")
+	}
+
+	return nil
+}
+
+var _ storage.ResponseSettingUpdater = (*OperationUpdater)(nil)
diff --git a/pkg/service/presentation/model/model.go b/pkg/service/presentation/model/model.go
index 47cada2..edbbfa6 100644
--- a/pkg/service/presentation/model/model.go
+++ b/pkg/service/presentation/model/model.go
@@ -67,7 +67,7 @@ type ListSubmissionRequest struct {
 }
 
 type Submission struct {
-	// One of {`pending`, `approved`, `denied`}.
+	// One of {`pending`, `approved`, `denied`, `cancelled`}.
 	Status string `json:"status" validate:"required"`
 	// The reason why the submission was approved or denied.
 	Reason string `json:"reason"`
diff --git a/pkg/service/presentation/service.go b/pkg/service/presentation/service.go
index 53605fc..bbf6aa6 100644
--- a/pkg/service/presentation/service.go
+++ b/pkg/service/presentation/service.go
@@ -16,6 +16,7 @@ import (
 	"github.com/tbd54566975/ssi-service/pkg/service/framework"
 	"github.com/tbd54566975/ssi-service/pkg/service/operation"
 	opstorage "github.com/tbd54566975/ssi-service/pkg/service/operation/storage"
+	"github.com/tbd54566975/ssi-service/pkg/service/operation/submission"
 	"github.com/tbd54566975/ssi-service/pkg/service/presentation/model"
 	presentationstorage "github.com/tbd54566975/ssi-service/pkg/service/presentation/storage"
 	"github.com/tbd54566975/ssi-service/pkg/service/schema"
@@ -23,8 +24,8 @@ import (
 )
 
 type Service struct {
-	storage    presentationstorage.Storage
-	opsStorage opstorage.Storage
+	storage    *Storage
+	opsStorage *operation.Storage
 	config     config.PresentationServiceConfig
 	resolver   *didsdk.Resolver
 	schema     *schema.Service
@@ -54,11 +55,11 @@ func (s Service) Config() config.PresentationServiceConfig {
 }
 
 func NewPresentationService(config config.PresentationServiceConfig, s storage.ServiceStorage, resolver *didsdk.Resolver, schema *schema.Service) (*Service, error) {
-	presentationStorage, err := presentationstorage.NewPresentationStorage(s)
+	presentationStorage, err := NewPresentationStorage(s)
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not instantiate definition storage for the presentation service")
 	}
-	opsStorage, err := opstorage.NewOperationStorage(s)
+	opsStorage, err := operation.NewOperationStorage(s)
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not instantiate storage for the operations")
 	}
@@ -93,7 +94,7 @@ func (s Service) CreatePresentationDefinition(request model.CreatePresentationDe
 		return nil, util.LoggingErrorMsg(err, "provided value is not a valid presentation definition")
 	}
 
-	storedPresentation := presentationstorage.StoredPresentation{ID: request.PresentationDefinition.ID, PresentationDefinition: request.PresentationDefinition}
+	storedPresentation := StoredPresentation{ID: request.PresentationDefinition.ID, PresentationDefinition: request.PresentationDefinition}
 
 	if err := s.storage.StorePresentation(storedPresentation); err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not store presentation")
@@ -177,7 +178,7 @@ func (s Service) CreateSubmission(request model.CreateSubmissionRequest) (*opera
 	}
 
 	storedSubmission := presentationstorage.StoredSubmission{
-		Status:     presentationstorage.StatusPending,
+		Status:     submission.StatusPending,
 		Submission: request.Submission,
 	}
 
@@ -186,7 +187,7 @@ func (s Service) CreateSubmission(request model.CreateSubmissionRequest) (*opera
 		return nil, errors.Wrap(err, "could not store presentation")
 	}
 
-	opID := operation.IDFromSubmissionID(storedSubmission.Submission.ID)
+	opID := submission.IDFromSubmissionID(storedSubmission.Submission.ID)
 	storedOp := opstorage.StoredOperation{
 		ID:   opID,
 		Done: false,
@@ -235,7 +236,7 @@ func (s Service) ReviewSubmission(request model.ReviewSubmissionRequest) (*model
 		return nil, errors.Wrap(err, "invalid request")
 	}
 
-	updatedSubmission, _, err := s.storage.UpdateSubmission(request.ID, request.Approved, request.Reason, operation.IDFromSubmissionID(request.ID))
+	updatedSubmission, _, err := s.storage.UpdateSubmission(request.ID, request.Approved, request.Reason, submission.IDFromSubmissionID(request.ID))
 	if err != nil {
 		return nil, errors.Wrap(err, "updating submission")
 	}
diff --git a/pkg/service/presentation/storage/bolt.go b/pkg/service/presentation/storage.go
similarity index 51%
rename from pkg/service/presentation/storage/bolt.go
rename to pkg/service/presentation/storage.go
index 7556aac..a5b1bdc 100644
--- a/pkg/service/presentation/storage/bolt.go
+++ b/pkg/service/presentation/storage.go
@@ -1,85 +1,70 @@
-package storage
+package presentation
 
 import (
 	"fmt"
 
+	"github.com/TBD54566975/ssi-sdk/credential/exchange"
 	"github.com/goccy/go-json"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 	"github.com/tbd54566975/ssi-service/internal/util"
 	opstorage "github.com/tbd54566975/ssi-service/pkg/service/operation/storage"
+	"github.com/tbd54566975/ssi-service/pkg/service/operation/storage/namespace"
+	opsubmission "github.com/tbd54566975/ssi-service/pkg/service/operation/submission"
+	prestorage "github.com/tbd54566975/ssi-service/pkg/service/presentation/storage"
 	"github.com/tbd54566975/ssi-service/pkg/storage"
 	"go.einride.tech/aip/filtering"
 )
 
 const (
-	namespace           = "presentation_definition"
-	submissionNamespace = "presentation_submission"
+	presentationDefinitionNamespace = "presentation_definition"
 )
 
-type BoltPresentationStorage struct {
-	db *storage.BoltDB
+type StoredPresentation struct {
+	ID                     string                          `json:"id"`
+	PresentationDefinition exchange.PresentationDefinition `json:"presentationDefinition"`
 }
 
-type opUpdater struct {
-	storage.UpdaterWithMap
+type Storage struct {
+	db storage.ServiceStorage
 }
 
-func (u opUpdater) SetUpdatedResponse(response []byte) {
-	u.UpdaterWithMap.Values["response"] = response
-}
-
-func (u opUpdater) Validate(v []byte) error {
-	var op opstorage.StoredOperation
-	if err := json.Unmarshal(v, &op); err != nil {
-		return errors.Wrap(err, "unmarshalling operation")
-	}
-
-	if op.Done {
-		return errors.New("operation already marked as done")
-	}
-
-	return nil
-}
-
-var _ storage.ResponseSettingUpdater = (*opUpdater)(nil)
-
-func (b BoltPresentationStorage) UpdateSubmission(id string, approved bool, reason string, opID string) (StoredSubmission, opstorage.StoredOperation, error) {
+func (ps Storage) UpdateSubmission(id string, approved bool, reason string, opID string) (prestorage.StoredSubmission, opstorage.StoredOperation, error) {
 	m := map[string]any{
-		"status": StatusDenied,
+		"status": opsubmission.StatusDenied,
 		"reason": reason,
 	}
 	if approved {
-		m["status"] = StatusApproved
+		m["status"] = opsubmission.StatusApproved
 	}
-	submissionData, operationData, err := b.db.UpdateValueAndOperation(
-		submissionNamespace,
+	submissionData, operationData, err := ps.db.UpdateValueAndOperation(
+		opsubmission.Namespace,
 		id,
 		storage.NewUpdater(m),
-		opstorage.NamespaceFromID(opID),
+		namespace.FromID(opID),
 		opID,
-		opUpdater{
-			storage.NewUpdater(map[string]any{
+		opsubmission.OperationUpdater{
+			UpdaterWithMap: storage.NewUpdater(map[string]any{
 				"done": true,
 			}),
 		})
 	if err != nil {
-		return StoredSubmission{}, opstorage.StoredOperation{}, errors.Wrap(err, "updating value and operation")
+		return prestorage.StoredSubmission{}, opstorage.StoredOperation{}, errors.Wrap(err, "updating value and operation")
 	}
 
-	var s StoredSubmission
+	var s prestorage.StoredSubmission
 	if err = json.Unmarshal(submissionData, &s); err != nil {
-		return StoredSubmission{}, opstorage.StoredOperation{}, errors.Wrap(err, "unmarshalling written submission")
+		return prestorage.StoredSubmission{}, opstorage.StoredOperation{}, errors.Wrap(err, "unmarshalling written submission")
 	}
 	var op opstorage.StoredOperation
 	if err = json.Unmarshal(operationData, &op); err != nil {
-		return StoredSubmission{}, opstorage.StoredOperation{}, errors.Wrap(err, "unmarshalling written operation")
+		return prestorage.StoredSubmission{}, opstorage.StoredOperation{}, errors.Wrap(err, "unmarshalling written operation")
 	}
 	return s, op, nil
 }
 
-func (b BoltPresentationStorage) ListSubmissions(filter filtering.Filter) ([]StoredSubmission, error) {
-	allData, err := b.db.ReadAll(submissionNamespace)
+func (ps *Storage) ListSubmissions(filter filtering.Filter) ([]prestorage.StoredSubmission, error) {
+	allData, err := ps.db.ReadAll(opsubmission.Namespace)
 	if err != nil {
 		return nil, errors.Wrap(err, "reading all data")
 	}
@@ -88,9 +73,9 @@ func (b BoltPresentationStorage) ListSubmissions(filter filtering.Filter) ([]Sto
 	if err != nil {
 		return nil, err
 	}
-	storedSubmissions := make([]StoredSubmission, 0, len(allData))
+	storedSubmissions := make([]prestorage.StoredSubmission, 0, len(allData))
 	for key, data := range allData {
-		var ss StoredSubmission
+		var ss prestorage.StoredSubmission
 		if err = json.Unmarshal(data, &ss); err != nil {
 			logrus.WithError(err).WithField("key", key).Error("unmarshalling submission")
 		}
@@ -107,14 +92,14 @@ func (b BoltPresentationStorage) ListSubmissions(filter filtering.Filter) ([]Sto
 	return storedSubmissions, nil
 }
 
-func NewBoltPresentationStorage(db *storage.BoltDB) (*BoltPresentationStorage, error) {
+func NewPresentationStorage(db storage.ServiceStorage) (*Storage, error) {
 	if db == nil {
 		return nil, errors.New("bolt db reference is nil")
 	}
-	return &BoltPresentationStorage{db: db}, nil
+	return &Storage{db: db}, nil
 }
 
-func (b BoltPresentationStorage) StorePresentation(presentation StoredPresentation) error {
+func (ps *Storage) StorePresentation(presentation StoredPresentation) error {
 	id := presentation.ID
 	if id == "" {
 		err := errors.New("could not store presentation definition without an ID")
@@ -127,11 +112,11 @@ func (b BoltPresentationStorage) StorePresentation(presentation StoredPresentati
 		logrus.WithError(err).Error(errMsg)
 		return errors.Wrapf(err, errMsg)
 	}
-	return b.db.Write(namespace, id, jsonBytes)
+	return ps.db.Write(presentationDefinitionNamespace, id, jsonBytes)
 }
 
-func (b BoltPresentationStorage) GetPresentation(id string) (*StoredPresentation, error) {
-	jsonBytes, err := b.db.Read(namespace, id)
+func (ps *Storage) GetPresentation(id string) (*StoredPresentation, error) {
+	jsonBytes, err := ps.db.Read(presentationDefinitionNamespace, id)
 	if err != nil {
 		return nil, util.LoggingErrorMsgf(err, "could not get presentation definition: %s", id)
 	}
@@ -145,36 +130,36 @@ func (b BoltPresentationStorage) GetPresentation(id string) (*StoredPresentation
 	return &stored, nil
 }
 
-func (b BoltPresentationStorage) DeletePresentation(id string) error {
-	if err := b.db.Delete(namespace, id); err != nil {
+func (ps *Storage) DeletePresentation(id string) error {
+	if err := ps.db.Delete(presentationDefinitionNamespace, id); err != nil {
 		return util.LoggingNewErrorf("could not delete presentation definition: %s", id)
 	}
 	return nil
 }
 
-func (b BoltPresentationStorage) StoreSubmission(submission StoredSubmission) error {
-	id := submission.Submission.ID
+func (ps Storage) StoreSubmission(s prestorage.StoredSubmission) error {
+	id := s.Submission.ID
 	if id == "" {
 		err := errors.New("could not store submission definition without an ID")
 		logrus.WithError(err).Error()
 		return err
 	}
-	jsonBytes, err := json.Marshal(submission)
+	jsonBytes, err := json.Marshal(s)
 	if err != nil {
 		return util.LoggingNewErrorf("could not store submission definition: %s", id)
 	}
-	return b.db.Write(submissionNamespace, id, jsonBytes)
+	return ps.db.Write(opsubmission.Namespace, id, jsonBytes)
 }
 
-func (b BoltPresentationStorage) GetSubmission(id string) (*StoredSubmission, error) {
-	jsonBytes, err := b.db.Read(submissionNamespace, id)
+func (ps *Storage) GetSubmission(id string) (*prestorage.StoredSubmission, error) {
+	jsonBytes, err := ps.db.Read(opsubmission.Namespace, id)
 	if err != nil {
 		return nil, util.LoggingNewErrorf("could not get submission definition: %s", id)
 	}
 	if len(jsonBytes) == 0 {
-		return nil, util.LoggingErrorMsgf(ErrSubmissionNotFound, "reading submission with id: %s", id)
+		return nil, util.LoggingErrorMsgf(prestorage.ErrSubmissionNotFound, "reading submission with id: %s", id)
 	}
-	var stored StoredSubmission
+	var stored prestorage.StoredSubmission
 	if err := json.Unmarshal(jsonBytes, &stored); err != nil {
 		return nil, util.LoggingErrorMsgf(err, "could not unmarshal stored submission definition: %s", id)
 	}
diff --git a/pkg/service/presentation/storage/storage.go b/pkg/service/presentation/storage/storage.go
index 97f4dc1..89b7b57 100644
--- a/pkg/service/presentation/storage/storage.go
+++ b/pkg/service/presentation/storage/storage.go
@@ -3,9 +3,8 @@ package storage
 import (
 	"github.com/TBD54566975/ssi-sdk/credential/exchange"
 	"github.com/pkg/errors"
-	"github.com/tbd54566975/ssi-service/internal/util"
 	opstorage "github.com/tbd54566975/ssi-service/pkg/service/operation/storage"
-	"github.com/tbd54566975/ssi-service/pkg/storage"
+	"github.com/tbd54566975/ssi-service/pkg/service/operation/submission"
 	"go.einride.tech/aip/filtering"
 )
 
@@ -26,48 +25,8 @@ type DefinitionStorage interface {
 	DeletePresentation(id string) error
 }
 
-// NewPresentationStorage finds the presentation storage impl for a given ServiceStorage value
-func NewPresentationStorage(s storage.ServiceStorage) (Storage, error) {
-	switch s.Type() {
-	case storage.Bolt:
-		gotBolt, ok := s.(*storage.BoltDB)
-		if !ok {
-			return nil, util.LoggingNewErrorf("trouble instantiating : %s", s.Type())
-		}
-		boltStorage, err := NewBoltPresentationStorage(gotBolt)
-		if err != nil {
-			return nil, util.LoggingErrorMsg(err, "could not instantiate schema bolt storage")
-		}
-		return boltStorage, err
-	default:
-		return nil, util.LoggingNewErrorf("unsupported storage type: %s", s.Type())
-	}
-}
-
-type Status uint8
-
-func (s Status) String() string {
-	switch s {
-	case StatusPending:
-		return "pending"
-	case StatusDenied:
-		return "denied"
-	case StatusApproved:
-		return "approved"
-	default:
-		return "unknown"
-	}
-}
-
-const (
-	StatusUnknown Status = iota
-	StatusPending
-	StatusDenied
-	StatusApproved
-)
-
 type StoredSubmission struct {
-	Status     Status                          `json:"status"`
+	Status     submission.Status               `json:"status"`
 	Submission exchange.PresentationSubmission `json:"submission"`
 	Reason     string                          `json:"reason"`
 }
diff --git a/pkg/service/schema/service.go b/pkg/service/schema/service.go
index d047ef6..4ddc667 100644
--- a/pkg/service/schema/service.go
+++ b/pkg/service/schema/service.go
@@ -20,12 +20,12 @@ import (
 	"github.com/tbd54566975/ssi-service/internal/util"
 	"github.com/tbd54566975/ssi-service/pkg/service/framework"
 	"github.com/tbd54566975/ssi-service/pkg/service/keystore"
-	schemastorage "github.com/tbd54566975/ssi-service/pkg/service/schema/storage"
+
 	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
 
 type Service struct {
-	storage schemastorage.Storage
+	storage *Storage
 	config  config.SchemaServiceConfig
 
 	// external dependencies
@@ -62,7 +62,7 @@ func (s Service) Config() config.SchemaServiceConfig {
 }
 
 func NewSchemaService(config config.SchemaServiceConfig, s storage.ServiceStorage, keyStore *keystore.Service, resolver *didsdk.Resolver) (*Service, error) {
-	schemaStorage, err := schemastorage.NewSchemaStorage(s)
+	schemaStorage, err := NewSchemaStorage(s)
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not instantiate storage for the schema service")
 	}
@@ -109,7 +109,7 @@ func (s Service) CreateSchema(request CreateSchemaRequest) (*CreateSchemaRespons
 		Schema:   prepareJSONSchema(schemaID, request.Name, request.Schema),
 	}
 
-	storedSchema := schemastorage.StoredSchema{ID: schemaID, Schema: schemaValue}
+	storedSchema := StoredSchema{ID: schemaID, Schema: schemaValue}
 
 	// sign the schema
 	if request.Sign {
diff --git a/pkg/service/schema/storage/bolt.go b/pkg/service/schema/storage.go
similarity index 68%
rename from pkg/service/schema/storage/bolt.go
rename to pkg/service/schema/storage.go
index 7bc6f5f..c372a05 100644
--- a/pkg/service/schema/storage/bolt.go
+++ b/pkg/service/schema/storage.go
@@ -1,4 +1,4 @@
-package storage
+package schema
 
 import (
 	"fmt"
@@ -7,25 +7,34 @@ import (
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 
+	"github.com/TBD54566975/ssi-sdk/credential/schema"
 	"github.com/tbd54566975/ssi-service/pkg/storage"
+
+	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 )
 
 const (
 	namespace = "schema"
 )
 
-type BoltSchemaStorage struct {
-	db *storage.BoltDB
+type StoredSchema struct {
+	ID        string              `json:"id"`
+	Schema    schema.VCJSONSchema `json:"schema"`
+	SchemaJWT *keyaccess.JWT      `json:"token,omitempty"`
+}
+
+type Storage struct {
+	db storage.ServiceStorage
 }
 
-func NewBoltSchemaStorage(db *storage.BoltDB) (*BoltSchemaStorage, error) {
+func NewSchemaStorage(db storage.ServiceStorage) (*Storage, error) {
 	if db == nil {
 		return nil, errors.New("bolt db reference is nil")
 	}
-	return &BoltSchemaStorage{db: db}, nil
+	return &Storage{db: db}, nil
 }
 
-func (b BoltSchemaStorage) StoreSchema(schema StoredSchema) error {
+func (ss *Storage) StoreSchema(schema StoredSchema) error {
 	id := schema.ID
 	if id == "" {
 		err := errors.New("could not store schema without an ID")
@@ -38,11 +47,11 @@ func (b BoltSchemaStorage) StoreSchema(schema StoredSchema) error {
 		logrus.WithError(err).Error(errMsg)
 		return errors.Wrapf(err, errMsg)
 	}
-	return b.db.Write(namespace, id, schemaBytes)
+	return ss.db.Write(namespace, id, schemaBytes)
 }
 
-func (b BoltSchemaStorage) GetSchema(id string) (*StoredSchema, error) {
-	schemaBytes, err := b.db.Read(namespace, id)
+func (ss *Storage) GetSchema(id string) (*StoredSchema, error) {
+	schemaBytes, err := ss.db.Read(namespace, id)
 	if err != nil {
 		errMsg := fmt.Sprintf("could not get schema: %s", id)
 		logrus.WithError(err).Error(errMsg)
@@ -63,8 +72,8 @@ func (b BoltSchemaStorage) GetSchema(id string) (*StoredSchema, error) {
 }
 
 // GetSchemas attempts to get all stored schemas. It will return those it can even if it has trouble with some.
-func (b BoltSchemaStorage) GetSchemas() ([]StoredSchema, error) {
-	gotSchemas, err := b.db.ReadAll(namespace)
+func (ss *Storage) GetSchemas() ([]StoredSchema, error) {
+	gotSchemas, err := ss.db.ReadAll(namespace)
 	if err != nil {
 		errMsg := "could not get all schemas"
 		logrus.WithError(err).Error(errMsg)
@@ -84,8 +93,8 @@ func (b BoltSchemaStorage) GetSchemas() ([]StoredSchema, error) {
 	return stored, nil
 }
 
-func (b BoltSchemaStorage) DeleteSchema(id string) error {
-	if err := b.db.Delete(namespace, id); err != nil {
+func (ss *Storage) DeleteSchema(id string) error {
+	if err := ss.db.Delete(namespace, id); err != nil {
 		errMsg := fmt.Sprintf("could not delete schema: %s", id)
 		logrus.WithError(err).Error(errMsg)
 		return errors.Wrapf(err, errMsg)
diff --git a/pkg/service/schema/storage/storage.go b/pkg/service/schema/storage/storage.go
deleted file mode 100644
index af97520..0000000
--- a/pkg/service/schema/storage/storage.go
+++ /dev/null
@@ -1,41 +0,0 @@
-package storage
-
-import (
-	"github.com/TBD54566975/ssi-sdk/credential/schema"
-
-	"github.com/tbd54566975/ssi-service/internal/keyaccess"
-	"github.com/tbd54566975/ssi-service/internal/util"
-	"github.com/tbd54566975/ssi-service/pkg/storage"
-)
-
-type StoredSchema struct {
-	ID        string              `json:"id"`
-	Schema    schema.VCJSONSchema `json:"schema"`
-	SchemaJWT *keyaccess.JWT      `json:"token,omitempty"`
-}
-
-type Storage interface {
-	StoreSchema(schema StoredSchema) error
-	GetSchema(id string) (*StoredSchema, error)
-	// TODO(gabe) consider get schemas by DID, or more advanced querying
-	GetSchemas() ([]StoredSchema, error)
-	DeleteSchema(id string) error
-}
-
-// NewSchemaStorage finds the schema storage impl for a given ServiceStorage value
-func NewSchemaStorage(s storage.ServiceStorage) (Storage, error) {
-	switch s.Type() {
-	case storage.Bolt:
-		gotBolt, ok := s.(*storage.BoltDB)
-		if !ok {
-			return nil, util.LoggingNewErrorf("trouble instantiating : %s", s.Type())
-		}
-		boltStorage, err := NewBoltSchemaStorage(gotBolt)
-		if err != nil {
-			return nil, util.LoggingErrorMsg(err, "could not instantiate schema bolt storage")
-		}
-		return boltStorage, err
-	default:
-		return nil, util.LoggingNewErrorf("unsupported storage type: %s", s.Type())
-	}
-}
diff --git a/pkg/service/service.go b/pkg/service/service.go
index 15247a6..2a167c2 100644
--- a/pkg/service/service.go
+++ b/pkg/service/service.go
@@ -35,7 +35,7 @@ func InstantiateSSIService(config config.ServicesConfig) (*SSIService, error) {
 }
 
 func validateServiceConfig(config config.ServicesConfig) error {
-	if !storage.IsStorageAvailable(config.StorageProvider) {
+	if !storage.IsStorageAvailable(storage.Type(config.StorageProvider)) {
 		return fmt.Errorf("%s storage provider configured, but not available", config.StorageProvider)
 	}
 	if config.KeyStoreConfig.IsEmpty() {
@@ -66,7 +66,7 @@ func (ssi *SSIService) GetServices() []framework.Service {
 
 // instantiateServices begins all instantiates and their dependencies
 func instantiateServices(config config.ServicesConfig) ([]framework.Service, error) {
-	storageProvider, err := storage.NewStorage(storage.Storage(config.StorageProvider))
+	storageProvider, err := storage.NewStorage(storage.Type(config.StorageProvider), config.StorageOption)
 	if err != nil {
 		return nil, util.LoggingErrorMsgf(err, "could not instantiate storage provider: %s", config.StorageProvider)
 	}
diff --git a/pkg/storage/bolt.go b/pkg/storage/bolt.go
index d2df74b..7014f9a 100644
--- a/pkg/storage/bolt.go
+++ b/pkg/storage/bolt.go
@@ -13,29 +13,56 @@ import (
 	bolt "go.etcd.io/bbolt"
 )
 
+func init() {
+	_ = RegisterStorage(&BoltDB{})
+}
+
 const (
-	DBFile = "ssi-service.db"
+	DBFilePrefix = "ssi-service"
 )
 
 type BoltDB struct {
 	db *bolt.DB
 }
 
-func (b *BoltDB) Type() Storage {
-	return Bolt
+// Init instantiates a file-based storage instance for Bolt https://github.com/boltdb/bolt
+func (b *BoltDB) Init(options interface{}) error {
+	if b.db != nil && b.IsOpen() {
+		return fmt.Errorf("bolit db already opened with name %s", b.URI())
+	}
+	dbFilePath := fmt.Sprintf("%s_%s.db", DBFilePrefix, b.Type())
+	if options != nil {
+		customPath, ok := options.(string)
+		if !ok {
+			return fmt.Errorf("options should be a string value")
+		}
+		if customPath != "" {
+			dbFilePath = customPath
+		}
+	}
+	db, err := bolt.Open(dbFilePath, 0600, &bolt.Options{Timeout: 3 * time.Second})
+	if err != nil {
+		return err
+	}
+	b.db = db
+	return nil
 }
 
-// NewBoltDB instantiates a file-based storage instance for Bolt https://github.com/boltdb/bolt
-func NewBoltDB() (*BoltDB, error) {
-	return NewBoltDBWithFile(DBFile)
+// URI return filepath of boltDB,
+func (b *BoltDB) URI() string {
+	return b.db.Path()
 }
 
-func NewBoltDBWithFile(filePath string) (*BoltDB, error) {
-	db, err := bolt.Open(filePath, 0600, &bolt.Options{Timeout: 3 * time.Second})
-	if err != nil {
-		return nil, err
+// IsOpen return if db was opened
+func (b *BoltDB) IsOpen() bool {
+	if b.db == nil {
+		return false
 	}
-	return &BoltDB{db: db}, nil
+	return b.db.Path() != ""
+}
+
+func (b *BoltDB) Type() Type {
+	return Bolt
 }
 
 func (b *BoltDB) Close() error {
@@ -149,7 +176,7 @@ type UpdaterWithMap struct {
 
 // Validate is a default implementation for UpdaterWithMap which does no validation. Users can pass embed UpdaterWithMap
 // into a custom struct and redefine this method in order to have custom logic.
-func (u UpdaterWithMap) Validate(v []byte) error {
+func (u UpdaterWithMap) Validate(_ []byte) error {
 	return nil
 }
 
diff --git a/pkg/storage/storage.go b/pkg/storage/storage.go
index 860872d..b2417d1 100644
--- a/pkg/storage/storage.go
+++ b/pkg/storage/storage.go
@@ -2,47 +2,83 @@ package storage
 
 import (
 	"fmt"
+	"reflect"
 )
 
-type Storage string
+type Type string
 
 const (
-	Bolt Storage = "bolt"
+	Bolt Type = "bolt"
+)
+
+var (
+	availableStorages = make(map[Type]ServiceStorage)
 )
 
 // ServiceStorage describes the api for storage independent of DB providers
 type ServiceStorage interface {
-	Type() Storage
+	Init(interface{}) error
+	Type() Type
+	URI() string
+	IsOpen() bool
 	Close() error
 	Write(namespace, key string, value []byte) error
 	Read(namespace, key string) ([]byte, error)
 	ReadAll(namespace string) (map[string][]byte, error)
+	ReadPrefix(namespace, prefix string) (map[string][]byte, error)
+	ReadAllKeys(namespace string) ([]string, error)
 	Delete(namespace, key string) error
 	DeleteNamespace(namespace string) error
+	Update(namespace string, key string, values map[string]any) ([]byte, error)
+	UpdateValueAndOperation(namespace, key string, updater Updater, opNamespace, opKey string, opUpdater ResponseSettingUpdater) (first, op []byte, err error)
+}
+
+// NewStorage returns the instance of the given storageProvider. If it doesn't exist, then a default implementation
+// is created with the given option parameter.
+func NewStorage(storageProvider Type, option interface{}) (ServiceStorage, error) {
+	impl := GetStorage(storageProvider)
+	if impl == nil {
+		return impl, fmt.Errorf("unsupported storage provider: %s", storageProvider)
+	}
+	err := impl.Init(option)
+	return impl, err
 }
 
-// NewStorage creates a new storage provider based on the input
-func NewStorage(storageProvider Storage) (ServiceStorage, error) {
-	switch storageProvider {
-	case Bolt:
-		return NewBoltDB()
-	default:
-		return nil, fmt.Errorf("unsupported storage provider: %s", storageProvider)
+// RegisterStorage registers a storage dynamically by its Type.
+func RegisterStorage(storage ServiceStorage) error {
+	if availableStorages[storage.Type()] != nil {
+		return fmt.Errorf("storage implementation for %s already exists", storage.Type())
 	}
+	availableStorages[storage.Type()] = storage
+	return nil
 }
 
-// AvailableStorage returns the supported storage providers
-func AvailableStorage() []Storage {
-	return []Storage{Bolt}
+// AvailableStorage returns the supported storage providers.
+func AvailableStorage() []Type {
+	return []Type{Bolt}
 }
 
-// IsStorageAvailable determines whether a given storage provider is available for instantiation
-func IsStorageAvailable(storage string) bool {
+// IsStorageAvailable determines whether a given storage provider is available for instantiation.
+func IsStorageAvailable(storage Type) bool {
 	all := AvailableStorage()
 	for _, s := range all {
-		if storage == string(s) {
+		if storage == s {
 			return true
 		}
 	}
 	return false
 }
+
+// GetStorage fetches a previously registered storage by storage type.
+func GetStorage(storageType Type) ServiceStorage {
+	tmp := availableStorages[storageType]
+	if tmp == nil {
+		return tmp
+	}
+	if reflect.TypeOf(tmp).Kind() == reflect.Ptr {
+		// Pointer:
+		return reflect.New(reflect.ValueOf(tmp).Elem().Type()).Interface().(ServiceStorage)
+	}
+	// Not pointer:
+	return reflect.New(reflect.TypeOf(tmp)).Elem().Interface().(ServiceStorage)
+}


Test patch:
diff --git a/pkg/server/router/credential_test.go b/pkg/server/router/credential_test.go
index 637bbd4..d825bf8 100644
--- a/pkg/server/router/credential_test.go
+++ b/pkg/server/router/credential_test.go
@@ -2,7 +2,6 @@ package router
 
 import (
 	"fmt"
-	"os"
 	"testing"
 	"time"
 
@@ -16,14 +15,9 @@ import (
 	"github.com/tbd54566975/ssi-service/pkg/service/did"
 	"github.com/tbd54566975/ssi-service/pkg/service/framework"
 	"github.com/tbd54566975/ssi-service/pkg/service/schema"
-	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
 
 func TestCredentialRouter(t *testing.T) {
-	// remove the db file after the test
-	t.Cleanup(func() {
-		_ = os.Remove(storage.DBFile)
-	})
 
 	t.Run("Nil Service", func(tt *testing.T) {
 		credRouter, err := NewCredentialRouter(nil)
@@ -41,15 +35,8 @@ func TestCredentialRouter(t *testing.T) {
 
 	t.Run("Credential Service Test", func(tt *testing.T) {
 
-		bolt, err := storage.NewBoltDB()
-		assert.NoError(tt, err)
-		assert.NotEmpty(tt, bolt)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		assert.NotNil(tt, bolt)
 
 		serviceConfig := config.CredentialServiceConfig{BaseServiceConfig: &config.BaseServiceConfig{Name: "credential"}}
 		keyStoreService := testKeyStoreService(tt, bolt)
@@ -203,15 +190,8 @@ func TestCredentialRouter(t *testing.T) {
 	})
 
 	t.Run("Credential Status List Test", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		assert.NoError(tt, err)
-		assert.NotEmpty(tt, bolt)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		assert.NotNil(tt, bolt)
 
 		serviceConfig := config.CredentialServiceConfig{BaseServiceConfig: &config.BaseServiceConfig{Name: "credential"}}
 		keyStoreService := testKeyStoreService(tt, bolt)
diff --git a/pkg/server/router/did_test.go b/pkg/server/router/did_test.go
index 58c875c..c7e97a9 100644
--- a/pkg/server/router/did_test.go
+++ b/pkg/server/router/did_test.go
@@ -1,7 +1,6 @@
 package router
 
 import (
-	"os"
 	"testing"
 
 	"github.com/TBD54566975/ssi-sdk/crypto"
@@ -11,16 +10,9 @@ import (
 	"github.com/tbd54566975/ssi-service/config"
 	"github.com/tbd54566975/ssi-service/pkg/service/did"
 	"github.com/tbd54566975/ssi-service/pkg/service/framework"
-	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
 
 func TestDIDRouter(t *testing.T) {
-
-	// remove the db file after the test
-	t.Cleanup(func() {
-		_ = os.Remove(storage.DBFile)
-	})
-
 	t.Run("Nil Service", func(tt *testing.T) {
 		didRouter, err := NewDIDRouter(nil)
 		assert.Error(tt, err)
@@ -36,9 +28,9 @@ func TestDIDRouter(t *testing.T) {
 	})
 
 	t.Run("DID Service Test", func(tt *testing.T) {
-		db, err := storage.NewBoltDB()
-		assert.NoError(tt, err)
-		assert.NotEmpty(tt, db)
+
+		db := setupTestDB(tt)
+		assert.NotNil(tt, db)
 
 		keyStoreService := testKeyStoreService(tt, db)
 		methods := []string{didsdk.KeyMethod.String()}
@@ -94,22 +86,20 @@ func TestDIDRouter(t *testing.T) {
 		assert.Len(tt, getDIDsResponse.DIDs, 2)
 
 		knownDIDs := map[string]bool{createDIDResponse.DID.ID: true, createDIDResponse2.DID.ID: true}
-		for _, did := range getDIDsResponse.DIDs {
-			if _, ok := knownDIDs[did.ID]; !ok {
+		for _, gotDID := range getDIDsResponse.DIDs {
+			if _, ok := knownDIDs[gotDID.ID]; !ok {
 				tt.Error("got unknown DID")
 			} else {
-				delete(knownDIDs, did.ID)
+				delete(knownDIDs, gotDID.ID)
 			}
 		}
 		assert.Len(tt, knownDIDs, 0)
 	})
 
 	t.Run("DID Web Service Test", func(tt *testing.T) {
-		_ = os.Remove(storage.DBFile)
 
-		db, err := storage.NewBoltDB()
-		assert.NoError(tt, err)
-		assert.NotEmpty(tt, db)
+		db := setupTestDB(tt)
+		assert.NotNil(tt, db)
 
 		keyStoreService := testKeyStoreService(tt, db)
 		methods := []string{didsdk.KeyMethod.String(), didsdk.WebMethod.String()}
@@ -166,11 +156,11 @@ func TestDIDRouter(t *testing.T) {
 		assert.Len(tt, getDIDsResponse.DIDs, 2)
 
 		knownDIDs := map[string]bool{createDIDResponse.DID.ID: true, createDIDResponse2.DID.ID: true}
-		for _, did := range getDIDsResponse.DIDs {
-			if _, ok := knownDIDs[did.ID]; !ok {
+		for _, gotDID := range getDIDsResponse.DIDs {
+			if _, ok := knownDIDs[gotDID.ID]; !ok {
 				tt.Error("got unknown DID")
 			} else {
-				delete(knownDIDs, did.ID)
+				delete(knownDIDs, gotDID.ID)
 			}
 		}
 		assert.Len(tt, knownDIDs, 0)
diff --git a/pkg/server/router/keystore_test.go b/pkg/server/router/keystore_test.go
index 870f21e..0434cc7 100644
--- a/pkg/server/router/keystore_test.go
+++ b/pkg/server/router/keystore_test.go
@@ -1,7 +1,6 @@
 package router
 
 import (
-	"os"
 	"testing"
 
 	"github.com/TBD54566975/ssi-sdk/crypto"
@@ -11,16 +10,10 @@ import (
 	"github.com/tbd54566975/ssi-service/config"
 	"github.com/tbd54566975/ssi-service/pkg/service/framework"
 	"github.com/tbd54566975/ssi-service/pkg/service/keystore"
-	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
 
 func TestKeyStoreRouter(t *testing.T) {
 
-	// remove the db file after the test
-	t.Cleanup(func() {
-		_ = os.Remove(storage.DBFile)
-	})
-
 	t.Run("Nil Service", func(tt *testing.T) {
 		keyStoreRouter, err := NewKeyStoreRouter(nil)
 		assert.Error(tt, err)
@@ -36,9 +29,8 @@ func TestKeyStoreRouter(t *testing.T) {
 	})
 
 	t.Run("Key Store Service Test", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		assert.NoError(tt, err)
-		assert.NotEmpty(tt, bolt)
+		bolt := setupTestDB(tt)
+		assert.NotNil(tt, bolt)
 
 		serviceConfig := config.KeyStoreServiceConfig{
 			BaseServiceConfig:  &config.BaseServiceConfig{Name: "keystore"},
diff --git a/pkg/server/router/manifest_test.go b/pkg/server/router/manifest_test.go
index ba860e8..d379ead 100644
--- a/pkg/server/router/manifest_test.go
+++ b/pkg/server/router/manifest_test.go
@@ -1,7 +1,6 @@
 package router
 
 import (
-	"os"
 	"testing"
 
 	"github.com/TBD54566975/ssi-sdk/credential/exchange"
@@ -19,14 +18,9 @@ import (
 	"github.com/tbd54566975/ssi-service/pkg/service/framework"
 	"github.com/tbd54566975/ssi-service/pkg/service/manifest"
 	"github.com/tbd54566975/ssi-service/pkg/service/schema"
-	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
 
 func TestManifestRouter(t *testing.T) {
-	// remove the db file after the test
-	t.Cleanup(func() {
-		_ = os.Remove(storage.DBFile)
-	})
 
 	t.Run("Nil Service", func(tt *testing.T) {
 		manifestRouter, err := NewManifestRouter(nil)
@@ -43,16 +37,14 @@ func TestManifestRouter(t *testing.T) {
 	})
 
 	t.Run("Manifest Service Test", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		assert.NoError(tt, err)
-		assert.NotEmpty(tt, bolt)
+		bolt := setupTestDB(tt)
+		assert.NotNil(tt, bolt)
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
 		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
 		credentialService := testCredentialService(tt, bolt, keyStoreService, didService, schemaService)
 		manifestService := testManifestService(tt, bolt, keyStoreService, didService, credentialService)
-		assert.NoError(tt, err)
 		assert.NotEmpty(tt, manifestService)
 
 		// check type and status
diff --git a/pkg/server/router/presentation_test.go b/pkg/server/router/presentation_test.go
index d77db5b..1a00b9f 100644
--- a/pkg/server/router/presentation_test.go
+++ b/pkg/server/router/presentation_test.go
@@ -1,7 +1,6 @@
 package router
 
 import (
-	"os"
 	"testing"
 
 	"github.com/TBD54566975/ssi-sdk/credential/exchange"
@@ -10,7 +9,6 @@ import (
 	"github.com/tbd54566975/ssi-service/config"
 	"github.com/tbd54566975/ssi-service/pkg/service/presentation"
 	"github.com/tbd54566975/ssi-service/pkg/service/presentation/model"
-	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
 
 func TestPresentationDefinitionRouter(t *testing.T) {
@@ -30,12 +28,9 @@ func TestPresentationDefinitionRouter(t *testing.T) {
 }
 
 func TestPresentationDefinitionService(t *testing.T) {
-	t.Cleanup(func() {
-		_ = os.Remove(storage.DBFile)
-	})
 
-	s, err := storage.NewStorage(storage.Bolt)
-	assert.NoError(t, err)
+	s := setupTestDB(t)
+	assert.NotNil(t, s)
 
 	keyStoreService := testKeyStoreService(t, s)
 	didService := testDIDService(t, s, keyStoreService)
diff --git a/pkg/server/router/router_test.go b/pkg/server/router/router_test.go
index 89ebd6b..7e263dd 100644
--- a/pkg/server/router/router_test.go
+++ b/pkg/server/router/router_test.go
@@ -1,10 +1,15 @@
 package router
 
 import (
+	"os"
+	"testing"
+
 	didsdk "github.com/TBD54566975/ssi-sdk/did"
+	"github.com/stretchr/testify/require"
 
 	"github.com/tbd54566975/ssi-service/config"
 	"github.com/tbd54566975/ssi-service/pkg/service/framework"
+	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
 
 // generic test config to be used by all tests in this package
@@ -29,3 +34,17 @@ func (s *testService) Config() config.ServicesConfig {
 		ManifestConfig:   config.ManifestServiceConfig{},
 	}
 }
+
+func setupTestDB(t *testing.T) storage.ServiceStorage {
+	file, err := os.CreateTemp("", "bolt")
+	require.NoError(t, err)
+	name := file.Name()
+	file.Close()
+	s, err := storage.NewStorage(storage.Bolt, name)
+	require.NoError(t, err)
+	t.Cleanup(func() {
+		_ = s.Close()
+		_ = os.Remove(s.URI())
+	})
+	return s
+}
diff --git a/pkg/server/router/schema_test.go b/pkg/server/router/schema_test.go
index 9e06b57..f408dd3 100644
--- a/pkg/server/router/schema_test.go
+++ b/pkg/server/router/schema_test.go
@@ -1,28 +1,20 @@
 package router
 
 import (
-	"os"
 	"testing"
 
 	"github.com/TBD54566975/ssi-sdk/crypto"
 	didsdk "github.com/TBD54566975/ssi-sdk/did"
 	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/require"
 
 	"github.com/tbd54566975/ssi-service/config"
 	"github.com/tbd54566975/ssi-service/pkg/service/did"
 	"github.com/tbd54566975/ssi-service/pkg/service/framework"
 	"github.com/tbd54566975/ssi-service/pkg/service/schema"
-	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
 
 func TestSchemaRouter(t *testing.T) {
 
-	// remove the db file after the test
-	t.Cleanup(func() {
-		_ = os.Remove(storage.DBFile)
-	})
-
 	t.Run("Nil Service", func(tt *testing.T) {
 		schemaRouter, err := NewSchemaRouter(nil)
 		assert.Error(tt, err)
@@ -38,9 +30,8 @@ func TestSchemaRouter(t *testing.T) {
 	})
 
 	t.Run("Schema Service Test", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-		require.NotEmpty(tt, bolt)
+		bolt := setupTestDB(tt)
+		assert.NotNil(tt, bolt)
 
 		serviceConfig := config.SchemaServiceConfig{BaseServiceConfig: &config.BaseServiceConfig{Name: "schema"}}
 		keyStoreService := testKeyStoreService(tt, bolt)
@@ -123,15 +114,10 @@ func TestSchemaRouter(t *testing.T) {
 }
 
 func TestSchemaSigning(t *testing.T) {
-	// remove the db file after the test
-	t.Cleanup(func() {
-		_ = os.Remove(storage.DBFile)
-	})
 
 	t.Run("Unsigned Schema Test", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-		require.NotEmpty(tt, bolt)
+		bolt := setupTestDB(tt)
+		assert.NotNil(tt, bolt)
 
 		serviceConfig := config.SchemaServiceConfig{BaseServiceConfig: &config.BaseServiceConfig{Name: "schema"}}
 		keyStoreService := testKeyStoreService(tt, bolt)
diff --git a/pkg/server/router/testutils_test.go b/pkg/server/router/testutils_test.go
index 6bee356..b0ce5be 100644
--- a/pkg/server/router/testutils_test.go
+++ b/pkg/server/router/testutils_test.go
@@ -47,7 +47,7 @@ func testSchemaService(t *testing.T, db storage.ServiceStorage, keyStore *keysto
 	return schemaService
 }
 
-func testCredentialService(t *testing.T, db *storage.BoltDB, keyStore *keystore.Service, did *did.Service, schema *schema.Service) *credential.Service {
+func testCredentialService(t *testing.T, db storage.ServiceStorage, keyStore *keystore.Service, did *did.Service, schema *schema.Service) *credential.Service {
 	serviceConfig := config.CredentialServiceConfig{BaseServiceConfig: &config.BaseServiceConfig{Name: "credential"}}
 	// create a credential service
 	credentialService, err := credential.NewCredentialService(serviceConfig, db, keyStore, did.GetResolver(), schema)
@@ -56,7 +56,7 @@ func testCredentialService(t *testing.T, db *storage.BoltDB, keyStore *keystore.
 	return credentialService
 }
 
-func testManifestService(t *testing.T, db *storage.BoltDB, keyStore *keystore.Service, did *did.Service, credential *credential.Service) *manifest.Service {
+func testManifestService(t *testing.T, db storage.ServiceStorage, keyStore *keystore.Service, did *did.Service, credential *credential.Service) *manifest.Service {
 	serviceConfig := config.ManifestServiceConfig{BaseServiceConfig: &config.BaseServiceConfig{Name: "manifest"}}
 	// create a manifest service
 	manifestService, err := manifest.NewManifestService(serviceConfig, db, keyStore, did.GetResolver(), credential)
diff --git a/pkg/server/server_credential_test.go b/pkg/server/server_credential_test.go
index 74872bc..14ac92b 100644
--- a/pkg/server/server_credential_test.go
+++ b/pkg/server/server_credential_test.go
@@ -4,7 +4,6 @@ import (
 	"fmt"
 	"net/http"
 	"net/http/httptest"
-	"os"
 	"strings"
 	"testing"
 	"time"
@@ -21,19 +20,12 @@ import (
 	"github.com/tbd54566975/ssi-service/pkg/server/router"
 	"github.com/tbd54566975/ssi-service/pkg/service/did"
 	"github.com/tbd54566975/ssi-service/pkg/service/schema"
-	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
 
 func TestCredentialAPI(t *testing.T) {
 	t.Run("Test Create Credential", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
@@ -108,14 +100,8 @@ func TestCredentialAPI(t *testing.T) {
 	})
 
 	t.Run("Test Create Credential with Schema", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
@@ -206,14 +192,8 @@ func TestCredentialAPI(t *testing.T) {
 	})
 
 	t.Run("Test Get Credential By ID", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
@@ -224,7 +204,7 @@ func TestCredentialAPI(t *testing.T) {
 
 		// get a cred that doesn't exit
 		req := httptest.NewRequest(http.MethodGet, "https://ssi-service.com/v1/credentials/bad", nil)
-		err = credRouter.GetCredential(newRequestContext(), w, req)
+		err := credRouter.GetCredential(newRequestContext(), w, req)
 		assert.Error(tt, err)
 		assert.Contains(tt, err.Error(), "cannot get credential without ID parameter")
 
@@ -282,14 +262,8 @@ func TestCredentialAPI(t *testing.T) {
 	})
 
 	t.Run("Test Get Credential By Schema", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
@@ -361,14 +335,8 @@ func TestCredentialAPI(t *testing.T) {
 	})
 
 	t.Run("Test Get Credential By Issuer", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
@@ -420,14 +388,8 @@ func TestCredentialAPI(t *testing.T) {
 	})
 
 	t.Run("Test Get Credential By Subject", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
@@ -481,14 +443,8 @@ func TestCredentialAPI(t *testing.T) {
 	})
 
 	t.Run("Test Delete Credential", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
@@ -552,14 +508,8 @@ func TestCredentialAPI(t *testing.T) {
 	})
 
 	t.Run("Test Verifying a Credential", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
@@ -625,14 +575,8 @@ func TestCredentialAPI(t *testing.T) {
 	})
 
 	t.Run("Test Create Revocable Credential", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
@@ -801,14 +745,8 @@ func TestCredentialAPI(t *testing.T) {
 	})
 
 	t.Run("Test Get Revoked Status Of Credential", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
@@ -879,14 +817,8 @@ func TestCredentialAPI(t *testing.T) {
 	})
 
 	t.Run("Test Get Status List Credential", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
diff --git a/pkg/server/server_did_test.go b/pkg/server/server_did_test.go
index 4733cd2..06ed88b 100644
--- a/pkg/server/server_did_test.go
+++ b/pkg/server/server_did_test.go
@@ -4,7 +4,6 @@ import (
 	"fmt"
 	"net/http"
 	"net/http/httptest"
-	"os"
 	"testing"
 
 	"github.com/TBD54566975/ssi-sdk/crypto"
@@ -14,19 +13,12 @@ import (
 	"github.com/stretchr/testify/require"
 
 	"github.com/tbd54566975/ssi-service/pkg/server/router"
-	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
 
 func TestDIDAPI(t *testing.T) {
 	t.Run("Test Get DID Methods", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		_, keyStoreService := testKeyStore(tt, bolt)
 		didService := testDIDRouter(tt, bolt, keyStoreService)
@@ -35,7 +27,7 @@ func TestDIDAPI(t *testing.T) {
 		req := httptest.NewRequest(http.MethodGet, "https://ssi-service.com/v1/dids", nil)
 		w := httptest.NewRecorder()
 
-		err = didService.GetDIDMethods(newRequestContext(), w, req)
+		err := didService.GetDIDMethods(newRequestContext(), w, req)
 		assert.NoError(tt, err)
 		assert.Equal(tt, http.StatusOK, w.Result().StatusCode)
 
@@ -48,14 +40,8 @@ func TestDIDAPI(t *testing.T) {
 	})
 
 	t.Run("Test Create DID By Method: Key", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		_, keyStoreService := testKeyStore(tt, bolt)
 		didService := testDIDRouter(tt, bolt, keyStoreService)
@@ -67,7 +53,7 @@ func TestDIDAPI(t *testing.T) {
 			"method": "key",
 		}
 
-		err = didService.CreateDIDByMethod(newRequestContextWithParams(params), w, req)
+		err := didService.CreateDIDByMethod(newRequestContextWithParams(params), w, req)
 		assert.Error(tt, err)
 		assert.Contains(tt, err.Error(), "invalid create DID request")
 
@@ -102,14 +88,8 @@ func TestDIDAPI(t *testing.T) {
 	})
 
 	t.Run("Test Get DID By Method", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		_, keyStore := testKeyStore(tt, bolt)
 		didService := testDIDRouter(tt, bolt, keyStore)
@@ -123,7 +103,7 @@ func TestDIDAPI(t *testing.T) {
 			"method": "bad",
 			"id":     "worse",
 		}
-		err = didService.GetDIDByMethod(newRequestContextWithParams(badParams), w, req)
+		err := didService.GetDIDByMethod(newRequestContextWithParams(badParams), w, req)
 		assert.Error(tt, err)
 		assert.Contains(tt, err.Error(), "could not get DID for method<bad>")
 
@@ -177,15 +157,8 @@ func TestDIDAPI(t *testing.T) {
 	})
 
 	t.Run("Test Get DIDs By Method", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
-
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 		_, keyStore := testKeyStore(tt, bolt)
 		didService := testDIDRouter(tt, bolt, keyStore)
 
@@ -197,7 +170,7 @@ func TestDIDAPI(t *testing.T) {
 		badParams := map[string]string{
 			"method": "bad",
 		}
-		err = didService.GetDIDsByMethod(newRequestContextWithParams(badParams), w, req)
+		err := didService.GetDIDsByMethod(newRequestContextWithParams(badParams), w, req)
 		assert.Error(tt, err)
 		assert.Contains(tt, err.Error(), "could not get DIDs for method: bad")
 
@@ -266,14 +239,8 @@ func TestDIDAPI(t *testing.T) {
 	})
 
 	t.Run("Test Resolve DIDs", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		_, keyStore := testKeyStore(tt, bolt)
 		didService := testDIDRouter(tt, bolt, keyStore)
@@ -285,7 +252,7 @@ func TestDIDAPI(t *testing.T) {
 		badParams := map[string]string{
 			"id": "bad",
 		}
-		err = didService.ResolveDID(newRequestContextWithParams(badParams), w, req)
+		err := didService.ResolveDID(newRequestContextWithParams(badParams), w, req)
 		assert.Error(tt, err)
 		assert.Contains(tt, err.Error(), "not a valid did: bad")
 
diff --git a/pkg/server/server_keystore_test.go b/pkg/server/server_keystore_test.go
index 1df30d4..3811c81 100644
--- a/pkg/server/server_keystore_test.go
+++ b/pkg/server/server_keystore_test.go
@@ -4,7 +4,6 @@ import (
 	"fmt"
 	"net/http"
 	"net/http/httptest"
-	"os"
 	"testing"
 
 	"github.com/TBD54566975/ssi-sdk/crypto"
@@ -14,19 +13,12 @@ import (
 	"github.com/stretchr/testify/require"
 
 	"github.com/tbd54566975/ssi-service/pkg/server/router"
-	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
 
 func TestKeyStoreAPI(t *testing.T) {
 	t.Run("Test Store Key", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		keyStoreRouter, _ := testKeyStore(tt, bolt)
 		w := httptest.NewRecorder()
@@ -40,7 +32,7 @@ func TestKeyStoreAPI(t *testing.T) {
 		}
 		badRequestValue := newRequestValue(tt, badKeyStoreRequest)
 		req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/keys", badRequestValue)
-		err = keyStoreRouter.StoreKey(newRequestContext(), w, req)
+		err := keyStoreRouter.StoreKey(newRequestContext(), w, req)
 		assert.Error(tt, err)
 		assert.Contains(tt, err.Error(), "unsupported key type: bad")
 
@@ -69,14 +61,8 @@ func TestKeyStoreAPI(t *testing.T) {
 	})
 
 	t.Run("Test Get Key Details", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		keyStoreService, _ := testKeyStore(tt, bolt)
 		w := httptest.NewRecorder()
diff --git a/pkg/server/server_manifest_test.go b/pkg/server/server_manifest_test.go
index 8f1fa3e..ac8f17c 100644
--- a/pkg/server/server_manifest_test.go
+++ b/pkg/server/server_manifest_test.go
@@ -4,7 +4,6 @@ import (
 	"fmt"
 	"net/http"
 	"net/http/httptest"
-	"os"
 	"testing"
 
 	"github.com/TBD54566975/ssi-sdk/crypto"
@@ -21,19 +20,12 @@ import (
 	"github.com/tbd54566975/ssi-service/pkg/service/did"
 	manifestsvc "github.com/tbd54566975/ssi-service/pkg/service/manifest"
 	"github.com/tbd54566975/ssi-service/pkg/service/schema"
-	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
 
 func TestManifestAPI(t *testing.T) {
 	t.Run("Test Create Manifest", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
@@ -47,7 +39,7 @@ func TestManifestAPI(t *testing.T) {
 		req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/manifests", badRequestValue)
 		w := httptest.NewRecorder()
 
-		err = manifestRouter.CreateManifest(newRequestContext(), w, req)
+		err := manifestRouter.CreateManifest(newRequestContext(), w, req)
 		assert.Error(tt, err)
 		assert.Contains(tt, err.Error(), "invalid create manifest request")
 
@@ -99,14 +91,8 @@ func TestManifestAPI(t *testing.T) {
 	})
 
 	t.Run("Test Get Manifest By ID", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
@@ -118,7 +104,7 @@ func TestManifestAPI(t *testing.T) {
 
 		// get a manifest that doesn't exit
 		req := httptest.NewRequest(http.MethodGet, "https://ssi-service.com/v1/manifests/bad", nil)
-		err = manifestRouter.GetManifest(newRequestContext(), w, req)
+		err := manifestRouter.GetManifest(newRequestContext(), w, req)
 		assert.Error(tt, err)
 		assert.Contains(tt, err.Error(), "cannot get manifest without ID parameter")
 
@@ -181,14 +167,8 @@ func TestManifestAPI(t *testing.T) {
 	})
 
 	t.Run("Test Get Manifests", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
@@ -233,7 +213,7 @@ func TestManifestAPI(t *testing.T) {
 		assert.NoError(tt, err)
 
 		// get manifest by id
-		req = httptest.NewRequest(http.MethodGet, fmt.Sprintf("https://ssi-service.com/v1/manifests"), nil)
+		req = httptest.NewRequest(http.MethodGet, "https://ssi-service.com/v1/manifests", nil)
 		err = manifestRouter.GetManifests(newRequestContext(), w, req)
 		assert.NoError(tt, err)
 
@@ -254,14 +234,8 @@ func TestManifestAPI(t *testing.T) {
 	})
 
 	t.Run("Test Delete Manifest", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
@@ -334,14 +308,8 @@ func TestManifestAPI(t *testing.T) {
 	})
 
 	t.Run("Test Submit Application", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
@@ -358,7 +326,7 @@ func TestManifestAPI(t *testing.T) {
 		req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/manifests/applications", badRequestValue)
 		w := httptest.NewRecorder()
 
-		err = manifestRouter.SubmitApplication(newRequestContext(), w, req)
+		err := manifestRouter.SubmitApplication(newRequestContext(), w, req)
 		assert.Error(tt, err)
 		assert.Contains(tt, err.Error(), "invalid submit application request")
 
@@ -457,14 +425,8 @@ func TestManifestAPI(t *testing.T) {
 	})
 
 	t.Run("Test Denied Application", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
@@ -481,7 +443,7 @@ func TestManifestAPI(t *testing.T) {
 		req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/manifests/applications", badRequestValue)
 		w := httptest.NewRecorder()
 
-		err = manifestRouter.SubmitApplication(newRequestContext(), w, req)
+		err := manifestRouter.SubmitApplication(newRequestContext(), w, req)
 		assert.Error(tt, err)
 		assert.Contains(tt, err.Error(), "invalid submit application request")
 
@@ -608,14 +570,8 @@ func TestManifestAPI(t *testing.T) {
 	})
 
 	t.Run("Test Get Application By ID and Get Applications", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
@@ -626,7 +582,7 @@ func TestManifestAPI(t *testing.T) {
 
 		// get a application that doesn't exit
 		req := httptest.NewRequest(http.MethodGet, "https://ssi-service.com/v1/manifests/applications/bad", nil)
-		err = manifestRouter.GetApplication(newRequestContext(), w, req)
+		err := manifestRouter.GetApplication(newRequestContext(), w, req)
 		assert.Error(tt, err)
 		assert.Contains(tt, err.Error(), "cannot get application without ID parameter")
 
@@ -763,14 +719,8 @@ func TestManifestAPI(t *testing.T) {
 	})
 
 	t.Run("Test Delete Application", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
diff --git a/pkg/server/server_operation_test.go b/pkg/server/server_operation_test.go
index 01c9272..d48c2aa 100644
--- a/pkg/server/server_operation_test.go
+++ b/pkg/server/server_operation_test.go
@@ -15,19 +15,20 @@ import (
 	"github.com/stretchr/testify/require"
 	"github.com/tbd54566975/ssi-service/pkg/server/router"
 	"github.com/tbd54566975/ssi-service/pkg/service/operation"
+	"github.com/tbd54566975/ssi-service/pkg/service/operation/submission"
 	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
 
 func TestOperationsAPI(t *testing.T) {
-	t.Run("Marks operation as done after reviewing submission", func(t *testing.T) {
-		s := setupTestDB(t)
+	t.Run("Marks operation as done after reviewing submission", func(tt *testing.T) {
+		s := setupTestDB(tt)
 		pRouter := setupPresentationRouter(t, s)
 		opRouter := setupOperationsRouter(t, s)
 
 		holderSigner, holderDID := getSigner(t)
 		definition := createPresentationDefinition(t, pRouter)
 		submissionOp := createSubmission(t, pRouter, definition.PresentationDefinition.ID, VerifiableCredential(), holderDID, holderSigner)
-		submission := reviewSubmission(t, pRouter, operation.SubmissionID(submissionOp.ID))
+		sub := reviewSubmission(t, pRouter, submission.ID(submissionOp.ID))
 
 		createdID := submissionOp.ID
 		req := httptest.NewRequest(
@@ -43,7 +44,7 @@ func TestOperationsAPI(t *testing.T) {
 		assert.NoError(t, json.NewDecoder(w.Body).Decode(&resp))
 		assert.True(t, resp.Done)
 		assert.Empty(t, resp.Result.Error)
-		data, err := json.Marshal(submission)
+		data, err := json.Marshal(sub)
 		assert.NoError(t, err)
 		var responseAsMap map[string]any
 		assert.NoError(t, json.Unmarshal(data, &responseAsMap))
@@ -51,8 +52,8 @@ func TestOperationsAPI(t *testing.T) {
 	})
 
 	t.Run("GetOperation", func(t *testing.T) {
-		t.Run("Returns operation after submission", func(t *testing.T) {
-			s := setupTestDB(t)
+		t.Run("Returns operation after submission", func(tt *testing.T) {
+			s := setupTestDB(tt)
 			pRouter := setupPresentationRouter(t, s)
 			opRouter := setupOperationsRouter(t, s)
 
@@ -76,8 +77,8 @@ func TestOperationsAPI(t *testing.T) {
 			assert.Contains(t, resp.ID, "/presentations/submissions/")
 		})
 
-		t.Run("Returns error when id doesn't exist", func(t *testing.T) {
-			s := setupTestDB(t)
+		t.Run("Returns error when id doesn't exist", func(tt *testing.T) {
+			s := setupTestDB(tt)
 			opRouter := setupOperationsRouter(t, s)
 
 			req := httptest.NewRequest(
@@ -94,8 +95,8 @@ func TestOperationsAPI(t *testing.T) {
 	})
 
 	t.Run("GetOperations", func(t *testing.T) {
-		t.Run("Returns empty when no operations stored", func(t *testing.T) {
-			s := setupTestDB(t)
+		t.Run("Returns empty when no operations stored", func(tt *testing.T) {
+			s := setupTestDB(tt)
 			opRouter := setupOperationsRouter(t, s)
 
 			request := router.GetOperationsRequest{
@@ -112,8 +113,8 @@ func TestOperationsAPI(t *testing.T) {
 			assert.Empty(t, resp.Operations)
 		})
 
-		t.Run("Returns one operation for every submission", func(t *testing.T) {
-			s := setupTestDB(t)
+		t.Run("Returns one operation for every submission", func(tt *testing.T) {
+			s := setupTestDB(tt)
 			pRouter := setupPresentationRouter(t, s)
 			opRouter := setupOperationsRouter(t, s)
 
@@ -147,8 +148,8 @@ func TestOperationsAPI(t *testing.T) {
 			}
 		})
 
-		t.Run("Returns operation when filtering to include", func(t *testing.T) {
-			s := setupTestDB(t)
+		t.Run("Returns operation when filtering to include", func(tt *testing.T) {
+			s := setupTestDB(tt)
 			pRouter := setupPresentationRouter(t, s)
 			opRouter := setupOperationsRouter(t, s)
 
@@ -172,8 +173,8 @@ func TestOperationsAPI(t *testing.T) {
 			assert.False(t, resp.Operations[0].Done)
 		})
 
-		t.Run("Returns zero operations when filtering to exclude", func(t *testing.T) {
-			s := setupTestDB(t)
+		t.Run("Returns zero operations when filtering to exclude", func(tt *testing.T) {
+			s := setupTestDB(tt)
 			pRouter := setupPresentationRouter(t, s)
 			opRouter := setupOperationsRouter(t, s)
 
@@ -196,8 +197,8 @@ func TestOperationsAPI(t *testing.T) {
 			assert.Empty(t, resp.Operations)
 		})
 
-		t.Run("Returns zero operations when wrong parent is specified", func(t *testing.T) {
-			s := setupTestDB(t)
+		t.Run("Returns zero operations when wrong parent is specified", func(tt *testing.T) {
+			s := setupTestDB(tt)
 			pRouter := setupPresentationRouter(t, s)
 			opRouter := setupOperationsRouter(t, s)
 
@@ -220,13 +221,65 @@ func TestOperationsAPI(t *testing.T) {
 		})
 	})
 
+	t.Run("CancelOperation", func(t *testing.T) {
+		t.Run("Marks an operation as done", func(t *testing.T) {
+			s := setupTestDB(t)
+			pRouter := setupPresentationRouter(t, s)
+			opRouter := setupOperationsRouter(t, s)
+
+			holderSigner, holderDID := getSigner(t)
+			definition := createPresentationDefinition(t, pRouter)
+			submissionOp := createSubmission(t, pRouter, definition.PresentationDefinition.ID, VerifiableCredential(), holderDID, holderSigner)
+
+			createdID := submissionOp.ID
+			req := httptest.NewRequest(
+				http.MethodPut,
+				fmt.Sprintf("https://ssi-service.com/v1/operations/%s", createdID),
+				nil)
+			w := httptest.NewRecorder()
+
+			err := opRouter.CancelOperation(newRequestContextWithParams(map[string]string{"id": createdID}), w, req)
+
+			assert.NoError(t, err)
+			var resp router.Operation
+			assert.NoError(t, json.NewDecoder(w.Body).Decode(&resp))
+			assert.True(t, resp.Done)
+			assert.Contains(t, resp.Result.Response, "definition_id")
+			assert.Contains(t, resp.Result.Response, "descriptor_map")
+			assert.Equal(t, "cancelled", resp.Result.Response.(map[string]any)["status"])
+		})
+
+		t.Run("Returns error when operation is done already", func(t *testing.T) {
+			s := setupTestDB(t)
+			pRouter := setupPresentationRouter(t, s)
+			opRouter := setupOperationsRouter(t, s)
+
+			holderSigner, holderDID := getSigner(t)
+			definition := createPresentationDefinition(t, pRouter)
+			submissionOp := createSubmission(t, pRouter, definition.PresentationDefinition.ID, VerifiableCredential(), holderDID, holderSigner)
+			_ = reviewSubmission(t, pRouter, submission.ID(submissionOp.ID))
+
+			createdID := submissionOp.ID
+			req := httptest.NewRequest(
+				http.MethodPut,
+				fmt.Sprintf("https://ssi-service.com/v1/operations/%s", createdID),
+				nil)
+			w := httptest.NewRecorder()
+
+			err := opRouter.CancelOperation(newRequestContextWithParams(map[string]string{"id": createdID}), w, req)
+
+			assert.Error(t, err)
+		})
+	})
+
 }
 
 func setupTestDB(t *testing.T) storage.ServiceStorage {
 	file, err := os.CreateTemp("", "bolt")
 	require.NoError(t, err)
 	name := file.Name()
-	s, err := storage.NewBoltDBWithFile(name)
+	file.Close()
+	s, err := storage.NewStorage(storage.Bolt, name)
 	require.NoError(t, err)
 	t.Cleanup(func() {
 		_ = s.Close()
diff --git a/pkg/server/server_presentation_test.go b/pkg/server/server_presentation_test.go
index ebbde08..aabda15 100644
--- a/pkg/server/server_presentation_test.go
+++ b/pkg/server/server_presentation_test.go
@@ -20,7 +20,7 @@ import (
 	"github.com/tbd54566975/ssi-service/config"
 	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 	"github.com/tbd54566975/ssi-service/pkg/server/router"
-	"github.com/tbd54566975/ssi-service/pkg/service/operation"
+	opsubmission "github.com/tbd54566975/ssi-service/pkg/service/operation/submission"
 	"github.com/tbd54566975/ssi-service/pkg/service/presentation"
 	"github.com/tbd54566975/ssi-service/pkg/service/presentation/model"
 	"github.com/tbd54566975/ssi-service/pkg/storage"
@@ -45,9 +45,9 @@ func TestPresentationAPI(t *testing.T) {
 	pd, err := builder.Build()
 	assert.NoError(t, err)
 
-	t.Run("Create, Get, and Delete PresentationDefinition", func(t *testing.T) {
-		s := setupTestDB(t)
-		pRouter := setupPresentationRouter(t, s)
+	t.Run("Create, Get, and Delete PresentationDefinition", func(tt *testing.T) {
+		s := setupTestDB(tt)
+		pRouter := setupPresentationRouter(tt, s)
 
 		var createdID string
 		{
@@ -59,15 +59,15 @@ func TestPresentationAPI(t *testing.T) {
 				SubmissionRequirements: nil,
 				InputDescriptors:       inputDescriptors,
 			}
-			value := newRequestValue(t, request)
+			value := newRequestValue(tt, request)
 			req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/presentations/definitions", value)
 			w := httptest.NewRecorder()
 
 			err = pRouter.CreatePresentationDefinition(newRequestContext(), w, req)
-			assert.NoError(t, err)
+			assert.NoError(tt, err)
 
 			var resp router.CreatePresentationDefinitionResponse
-			assert.NoError(t, json.NewDecoder(w.Body).Decode(&resp))
+			assert.NoError(tt, json.NewDecoder(w.Body).Decode(&resp))
 			if diff := cmp.Diff(*pd, resp.PresentationDefinition, cmpopts.IgnoreFields(exchange.PresentationDefinition{}, "ID")); diff != "" {
 				t.Errorf("PresentationDefinition mismatch (-want +got):\n%s", diff)
 			}
@@ -79,11 +79,11 @@ func TestPresentationAPI(t *testing.T) {
 			// We can get the PD after it's created.
 			req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("https://ssi-service.com/v1/presentations/definitions/%s", createdID), nil)
 			w := httptest.NewRecorder()
-			assert.NoError(t, pRouter.GetPresentationDefinition(newRequestContextWithParams(map[string]string{"id": createdID}), w, req))
+			assert.NoError(tt, pRouter.GetPresentationDefinition(newRequestContextWithParams(map[string]string{"id": createdID}), w, req))
 
 			var resp router.GetPresentationDefinitionResponse
-			assert.NoError(t, json.NewDecoder(w.Body).Decode(&resp))
-			assert.Equal(t, createdID, resp.PresentationDefinition.ID)
+			assert.NoError(tt, json.NewDecoder(w.Body).Decode(&resp))
+			assert.Equal(tt, createdID, resp.PresentationDefinition.ID)
 			if diff := cmp.Diff(*pd, resp.PresentationDefinition, cmpopts.IgnoreFields(exchange.PresentationDefinition{}, "ID")); diff != "" {
 				t.Errorf("PresentationDefinition mismatch (-want +got):\n%s", diff)
 			}
@@ -101,15 +101,15 @@ func TestPresentationAPI(t *testing.T) {
 			// And we cannot get the PD after it's been deleted.
 			req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("https://ssi-service.com/v1/presentations/definitions/%s", createdID), nil)
 			w := httptest.NewRecorder()
-			assert.Error(t, pRouter.GetPresentationDefinition(newRequestContextWithParams(map[string]string{"id": createdID}), w, req))
+			assert.Error(tt, pRouter.GetPresentationDefinition(newRequestContextWithParams(map[string]string{"id": createdID}), w, req))
 		}
 	})
 
-	t.Run("Create returns error without input descriptors", func(t *testing.T) {
-		s := setupTestDB(t)
-		pRouter := setupPresentationRouter(t, s)
+	t.Run("Create returns error without input descriptors", func(tt *testing.T) {
+		s := setupTestDB(tt)
+		pRouter := setupPresentationRouter(tt, s)
 		request := router.CreatePresentationDefinitionRequest{}
-		value := newRequestValue(t, request)
+		value := newRequestValue(tt, request)
 		req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/presentations/definitions", value)
 		w := httptest.NewRecorder()
 
@@ -118,43 +118,43 @@ func TestPresentationAPI(t *testing.T) {
 		assert.Error(t, err)
 	})
 
-	t.Run("Get without an ID returns error", func(t *testing.T) {
-		s := setupTestDB(t)
-		pRouter := setupPresentationRouter(t, s)
+	t.Run("Get without an ID returns error", func(tt *testing.T) {
+		s := setupTestDB(tt)
+		pRouter := setupPresentationRouter(tt, s)
 		req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("https://ssi-service.com/v1/presentations/definitions/%s", pd.ID), nil)
 		w := httptest.NewRecorder()
 
-		assert.Error(t, pRouter.GetPresentationDefinition(newRequestContext(), w, req))
+		assert.Error(tt, pRouter.GetPresentationDefinition(newRequestContext(), w, req))
 	})
 
-	t.Run("Delete without an ID returns error", func(t *testing.T) {
-		s := setupTestDB(t)
-		pRouter := setupPresentationRouter(t, s)
+	t.Run("Delete without an ID returns error", func(tt *testing.T) {
+		s := setupTestDB(tt)
+		pRouter := setupPresentationRouter(tt, s)
 
 		req := httptest.NewRequest(http.MethodDelete, fmt.Sprintf("https://ssi-service.com/v1/presentations/definitions/%s", pd.ID), nil)
 		w := httptest.NewRecorder()
-		assert.Error(t, pRouter.DeletePresentationDefinition(newRequestContext(), w, req))
+		assert.Error(tt, pRouter.DeletePresentationDefinition(newRequestContext(), w, req))
 		w.Flush()
 	})
 
-	t.Run("Submission endpoints", func(t *testing.T) {
+	t.Run("Submission endpoints", func(tt *testing.T) {
 
-		t.Run("Get non-existing ID returns error", func(t *testing.T) {
-			s := setupTestDB(t)
-			pRouter := setupPresentationRouter(t, s)
+		tt.Run("Get non-existing ID returns error", func(ttt *testing.T) {
+			s := setupTestDB(ttt)
+			pRouter := setupPresentationRouter(ttt, s)
 
 			req := httptest.NewRequest(http.MethodGet, "https://ssi-service.com/v1/presentations/submissions/myrandomid", nil)
 			w := httptest.NewRecorder()
-			assert.Error(t, pRouter.GetSubmission(newRequestContext(), w, req))
+			assert.Error(ttt, pRouter.GetSubmission(newRequestContext(), w, req))
 		})
 
-		t.Run("Get returns submission after creation", func(t *testing.T) {
-			s := setupTestDB(t)
-			pRouter := setupPresentationRouter(t, s)
+		tt.Run("Get returns submission after creation", func(ttt *testing.T) {
+			s := setupTestDB(ttt)
+			pRouter := setupPresentationRouter(ttt, s)
 
-			holderSigner, holderDID := getSigner(t)
-			definition := createPresentationDefinition(t, pRouter)
-			op := createSubmission(t, pRouter, definition.PresentationDefinition.ID, VerifiableCredential(
+			holderSigner, holderDID := getSigner(ttt)
+			definition := createPresentationDefinition(ttt, pRouter)
+			op := createSubmission(ttt, pRouter, definition.PresentationDefinition.ID, VerifiableCredential(
 				WithCredentialSubject(credential.CredentialSubject{
 					"additionalName": "Mclovin",
 					"dateOfBirth":    "1987-01-02",
@@ -163,25 +163,25 @@ func TestPresentationAPI(t *testing.T) {
 					"id":             "did:web:andresuribe.com",
 				})), holderDID, holderSigner)
 
-			req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("https://ssi-service.com/v1/presentations/submissions/%s", operation.SubmissionID(op.ID)), nil)
+			req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("https://ssi-service.com/v1/presentations/submissions/%s", opsubmission.ID(op.ID)), nil)
 			w := httptest.NewRecorder()
 
-			assert.NoError(t, pRouter.GetSubmission(newRequestContextWithParams(map[string]string{"id": operation.SubmissionID(op.ID)}), w, req))
+			assert.NoError(ttt, pRouter.GetSubmission(newRequestContextWithParams(map[string]string{"id": opsubmission.ID(op.ID)}), w, req))
 
 			var resp router.GetSubmissionResponse
-			assert.NoError(t, json.NewDecoder(w.Body).Decode(&resp))
-			assert.Equal(t, operation.SubmissionID(op.ID), resp.Submission.ID)
-			assert.Equal(t, definition.PresentationDefinition.ID, resp.Submission.DefinitionID)
-			assert.Equal(t, "pending", resp.Submission.Status)
+			assert.NoError(ttt, json.NewDecoder(w.Body).Decode(&resp))
+			assert.Equal(ttt, opsubmission.ID(op.ID), resp.Submission.ID)
+			assert.Equal(ttt, definition.PresentationDefinition.ID, resp.Submission.DefinitionID)
+			assert.Equal(ttt, "pending", resp.Submission.Status)
 		})
 
-		t.Run("Create well formed submission returns operation", func(t *testing.T) {
-			s := setupTestDB(t)
-			pRouter := setupPresentationRouter(t, s)
+		tt.Run("Create well formed submission returns operation", func(ttt *testing.T) {
+			s := setupTestDB(ttt)
+			pRouter := setupPresentationRouter(ttt, s)
 
-			holderSigner, holderDID := getSigner(t)
-			definition := createPresentationDefinition(t, pRouter)
-			request := createSubmissionRequest(t, definition.PresentationDefinition.ID, VerifiableCredential(
+			holderSigner, holderDID := getSigner(ttt)
+			definition := createPresentationDefinition(ttt, pRouter)
+			request := createSubmissionRequest(ttt, definition.PresentationDefinition.ID, VerifiableCredential(
 				WithCredentialSubject(credential.CredentialSubject{
 					"additionalName": "Mclovin",
 					"dateOfBirth":    "1987-01-02",
@@ -190,26 +190,26 @@ func TestPresentationAPI(t *testing.T) {
 					"id":             "did:web:andresuribe.com",
 				})), holderSigner, holderDID)
 
-			value := newRequestValue(t, request)
+			value := newRequestValue(ttt, request)
 			req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/presentations/submissions", value)
 			w := httptest.NewRecorder()
 
 			err = pRouter.CreateSubmission(newRequestContext(), w, req)
 
-			require.NoError(t, err)
+			require.NoError(ttt, err)
 			var resp router.Operation
-			assert.NoError(t, json.NewDecoder(w.Body).Decode(&resp))
-			assert.Contains(t, resp.ID, "presentations/submissions/")
-			assert.False(t, resp.Done)
-			assert.Zero(t, resp.Result)
+			assert.NoError(ttt, json.NewDecoder(w.Body).Decode(&resp))
+			assert.Contains(ttt, resp.ID, "presentations/submissions/")
+			assert.False(ttt, resp.Done)
+			assert.Zero(ttt, resp.Result)
 		})
 
-		t.Run("Review submission returns approved submission", func(t *testing.T) {
-			s := setupTestDB(t)
-			pRouter := setupPresentationRouter(t, s)
+		tt.Run("Review submission returns approved submission", func(ttt *testing.T) {
+			s := setupTestDB(ttt)
+			pRouter := setupPresentationRouter(ttt, s)
 
-			holderSigner, holderDID := getSigner(t)
-			definition := createPresentationDefinition(t, pRouter)
+			holderSigner, holderDID := getSigner(ttt)
+			definition := createPresentationDefinition(ttt, pRouter)
 			submissionOp := createSubmission(t, pRouter, definition.PresentationDefinition.ID, VerifiableCredential(), holderDID, holderSigner)
 
 			request := router.ReviewSubmissionRequest{
@@ -217,8 +217,8 @@ func TestPresentationAPI(t *testing.T) {
 				Reason:   "because I want to",
 			}
 
-			value := newRequestValue(t, request)
-			createdID := operation.SubmissionID(submissionOp.ID)
+			value := newRequestValue(ttt, request)
+			createdID := opsubmission.ID(submissionOp.ID)
 			req := httptest.NewRequest(
 				http.MethodPut,
 				fmt.Sprintf("https://ssi-service.com/v1/presentations/submissions/%s/review", createdID),
@@ -227,31 +227,31 @@ func TestPresentationAPI(t *testing.T) {
 
 			err = pRouter.ReviewSubmission(newRequestContextWithParams(map[string]string{"id": createdID}), w, req)
 
-			assert.NoError(t, err)
+			assert.NoError(ttt, err)
 			var resp router.ReviewSubmissionResponse
-			assert.NoError(t, json.NewDecoder(w.Body).Decode(&resp))
-			assert.Equal(t, "because I want to", resp.Reason)
-			assert.NotEmpty(t, resp.ID)
-			assert.Equal(t, "approved", resp.Status)
-			assert.Equal(t, definition.PresentationDefinition.ID, resp.DefinitionID)
+			assert.NoError(ttt, json.NewDecoder(w.Body).Decode(&resp))
+			assert.Equal(ttt, "because I want to", resp.Reason)
+			assert.NotEmpty(ttt, resp.ID)
+			assert.Equal(ttt, "approved", resp.Status)
+			assert.Equal(ttt, definition.PresentationDefinition.ID, resp.DefinitionID)
 		})
 
-		t.Run("Review submission twice fails", func(t *testing.T) {
-			s := setupTestDB(t)
-			pRouter := setupPresentationRouter(t, s)
+		tt.Run("Review submission twice fails", func(ttt *testing.T) {
+			s := setupTestDB(ttt)
+			pRouter := setupPresentationRouter(ttt, s)
 
-			holderSigner, holderDID := getSigner(t)
-			definition := createPresentationDefinition(t, pRouter)
+			holderSigner, holderDID := getSigner(ttt)
+			definition := createPresentationDefinition(ttt, pRouter)
 			submissionOp := createSubmission(t, pRouter, definition.PresentationDefinition.ID, VerifiableCredential(), holderDID, holderSigner)
-			createdID := operation.SubmissionID(submissionOp.ID)
-			_ = reviewSubmission(t, pRouter, createdID)
+			createdID := opsubmission.ID(submissionOp.ID)
+			_ = reviewSubmission(ttt, pRouter, createdID)
 
 			request := router.ReviewSubmissionRequest{
 				Approved: true,
 				Reason:   "because I want to review again",
 			}
 
-			value := newRequestValue(t, request)
+			value := newRequestValue(ttt, request)
 			req := httptest.NewRequest(
 				http.MethodPut,
 				fmt.Sprintf("https://ssi-service.com/v1/presentations/submissions/%s/review", createdID),
@@ -260,33 +260,33 @@ func TestPresentationAPI(t *testing.T) {
 
 			err = pRouter.ReviewSubmission(newRequestContextWithParams(map[string]string{"id": createdID}), w, req)
 
-			assert.Error(t, err)
-			assert.Contains(t, err.Error(), "operation already marked as done")
+			assert.Error(ttt, err)
+			assert.Contains(ttt, err.Error(), "operation already marked as done")
 		})
 
-		t.Run("List submissions returns empty when there are none", func(t *testing.T) {
-			s := setupTestDB(t)
-			pRouter := setupPresentationRouter(t, s)
+		tt.Run("List submissions returns empty when there are none", func(ttt *testing.T) {
+			s := setupTestDB(ttt)
+			pRouter := setupPresentationRouter(ttt, s)
 
 			request := router.ListSubmissionRequest{}
 
-			value := newRequestValue(t, request)
+			value := newRequestValue(ttt, request)
 			req := httptest.NewRequest(http.MethodGet, "https://ssi-service.com/v1/presentations/submissions", value)
 			w := httptest.NewRecorder()
 
 			err = pRouter.ListSubmissions(newRequestContext(), w, req)
 
-			require.NoError(t, err)
+			require.NoError(ttt, err)
 			var resp router.ListSubmissionResponse
-			assert.NoError(t, json.NewDecoder(w.Body).Decode(&resp))
-			assert.Empty(t, resp.Submissions)
+			assert.NoError(ttt, json.NewDecoder(w.Body).Decode(&resp))
+			assert.Empty(ttt, resp.Submissions)
 		})
 
-		t.Run("List submissions returns many submissions", func(t *testing.T) {
-			s := setupTestDB(t)
-			pRouter := setupPresentationRouter(t, s)
+		tt.Run("List submissions returns many submissions", func(ttt *testing.T) {
+			s := setupTestDB(ttt)
+			pRouter := setupPresentationRouter(ttt, s)
 
-			holderSigner, holderDID := getSigner(t)
+			holderSigner, holderDID := getSigner(ttt)
 			definition := createPresentationDefinition(t, pRouter)
 			op := createSubmission(t, pRouter, definition.PresentationDefinition.ID, VerifiableCredential(
 				WithCredentialSubject(credential.CredentialSubject{
@@ -297,8 +297,8 @@ func TestPresentationAPI(t *testing.T) {
 					"id":             "did:web:andresuribe.com",
 				})), holderDID, holderSigner)
 
-			mrTeeSigner, mrTeeDID := getSigner(t)
-			op2 := createSubmission(t, pRouter, definition.PresentationDefinition.ID, VerifiableCredential(
+			mrTeeSigner, mrTeeDID := getSigner(ttt)
+			op2 := createSubmission(ttt, pRouter, definition.PresentationDefinition.ID, VerifiableCredential(
 				WithCredentialSubject(credential.CredentialSubject{
 					"additionalName": "Mr. T",
 					"dateOfBirth":    "1999-01-02",
@@ -308,29 +308,29 @@ func TestPresentationAPI(t *testing.T) {
 
 			request := router.ListSubmissionRequest{}
 
-			value := newRequestValue(t, request)
+			value := newRequestValue(ttt, request)
 			req := httptest.NewRequest(http.MethodGet, "https://ssi-service.com/v1/presentations/submissions", value)
 			w := httptest.NewRecorder()
 
 			err = pRouter.ListSubmissions(newRequestContext(), w, req)
 
-			require.NoError(t, err)
+			require.NoError(ttt, err)
 			var resp router.ListSubmissionResponse
-			assert.NoError(t, json.NewDecoder(w.Body).Decode(&resp))
-			assert.Len(t, resp.Submissions, 2)
+			assert.NoError(ttt, json.NewDecoder(w.Body).Decode(&resp))
+			assert.Len(ttt, resp.Submissions, 2)
 
 			expectedSubmissions := []model.Submission{
 				{
 					Status: "pending",
 					PresentationSubmission: &exchange.PresentationSubmission{
-						ID:           operation.SubmissionID(op.ID),
+						ID:           opsubmission.ID(op.ID),
 						DefinitionID: definition.PresentationDefinition.ID,
 					},
 				},
 				{
 					Status: "pending",
 					PresentationSubmission: &exchange.PresentationSubmission{
-						ID:           operation.SubmissionID(op2.ID),
+						ID:           opsubmission.ID(op2.ID),
 						DefinitionID: definition.PresentationDefinition.ID,
 					},
 				},
@@ -342,33 +342,33 @@ func TestPresentationAPI(t *testing.T) {
 				}),
 			)
 			if diff != "" {
-				t.Errorf("Mismatch on submissions (-want +got):\n%s", diff)
+				ttt.Errorf("Mismatch on submissions (-want +got):\n%s", diff)
 			}
 		})
 
-		t.Run("bad filter returns error", func(t *testing.T) {
-			s := setupTestDB(t)
-			pRouter := setupPresentationRouter(t, s)
+		tt.Run("bad filter returns error", func(ttt *testing.T) {
+			s := setupTestDB(ttt)
+			pRouter := setupPresentationRouter(ttt, s)
 			request := router.ListSubmissionRequest{
 				Filter: `im a baaad filter that's trying to break a lot of stuff'`,
 			}
 
-			value := newRequestValue(t, request)
+			value := newRequestValue(ttt, request)
 			req := httptest.NewRequest(http.MethodGet, "https://ssi-service.com/v1/presentations/submissions", value)
 			w := httptest.NewRecorder()
 
 			err = pRouter.ListSubmissions(newRequestContext(), w, req)
 
-			require.Error(t, err)
+			require.Error(ttt, err)
 		})
 
-		t.Run("List submissions filters based on status", func(t *testing.T) {
-			s := setupTestDB(t)
-			pRouter := setupPresentationRouter(t, s)
+		tt.Run("List submissions filters based on status", func(ttt *testing.T) {
+			s := setupTestDB(ttt)
+			pRouter := setupPresentationRouter(ttt, s)
 
-			holderSigner, holderDID := getSigner(t)
-			definition := createPresentationDefinition(t, pRouter)
-			op := createSubmission(t, pRouter, definition.PresentationDefinition.ID, VerifiableCredential(
+			holderSigner, holderDID := getSigner(ttt)
+			definition := createPresentationDefinition(ttt, pRouter)
+			op := createSubmission(ttt, pRouter, definition.PresentationDefinition.ID, VerifiableCredential(
 				WithCredentialSubject(credential.CredentialSubject{
 					"additionalName": "Mclovin",
 					"dateOfBirth":    "1987-01-02",
@@ -381,21 +381,21 @@ func TestPresentationAPI(t *testing.T) {
 				Filter: `status="pending"`,
 			}
 
-			value := newRequestValue(t, request)
+			value := newRequestValue(ttt, request)
 			req := httptest.NewRequest(http.MethodGet, "https://ssi-service.com/v1/presentations/submissions", value)
 			w := httptest.NewRecorder()
 
 			err = pRouter.ListSubmissions(newRequestContext(), w, req)
 
-			require.NoError(t, err)
+			require.NoError(ttt, err)
 			var resp router.ListSubmissionResponse
-			assert.NoError(t, json.NewDecoder(w.Body).Decode(&resp))
+			assert.NoError(ttt, json.NewDecoder(w.Body).Decode(&resp))
 
 			expectedSubmissions := []model.Submission{
 				{
 					Status: "pending",
 					PresentationSubmission: &exchange.PresentationSubmission{
-						ID:           operation.SubmissionID(op.ID),
+						ID:           opsubmission.ID(op.ID),
 						DefinitionID: definition.PresentationDefinition.ID,
 					},
 				},
@@ -407,16 +407,16 @@ func TestPresentationAPI(t *testing.T) {
 				}),
 			)
 			if diff != "" {
-				t.Errorf("Mismatch on submissions (-want +got):\n%s", diff)
+				ttt.Errorf("Mismatch on submissions (-want +got):\n%s", diff)
 			}
 		})
 
-		t.Run("List submissions filter returns empty when status does not match", func(t *testing.T) {
-			s := setupTestDB(t)
-			pRouter := setupPresentationRouter(t, s)
+		tt.Run("List submissions filter returns empty when status does not match", func(ttt *testing.T) {
+			s := setupTestDB(ttt)
+			pRouter := setupPresentationRouter(ttt, s)
 
-			holderSigner, holderDID := getSigner(t)
-			definition := createPresentationDefinition(t, pRouter)
+			holderSigner, holderDID := getSigner(ttt)
+			definition := createPresentationDefinition(ttt, pRouter)
 			_ = createSubmission(t, pRouter, definition.PresentationDefinition.ID, VerifiableCredential(
 				WithCredentialSubject(credential.CredentialSubject{
 					"additionalName": "Mclovin",
@@ -430,17 +430,17 @@ func TestPresentationAPI(t *testing.T) {
 				Filter: `status = "done"`,
 			}
 
-			value := newRequestValue(t, request)
+			value := newRequestValue(ttt, request)
 			req := httptest.NewRequest(http.MethodGet, "https://ssi-service.com/v1/presentations/submissions", value)
 			w := httptest.NewRecorder()
 
 			err = pRouter.ListSubmissions(newRequestContext(), w, req)
 
-			require.NoError(t, err)
+			require.NoError(ttt, err)
 			var resp router.ListSubmissionResponse
-			assert.NoError(t, json.NewDecoder(w.Body).Decode(&resp))
+			assert.NoError(ttt, json.NewDecoder(w.Body).Decode(&resp))
 
-			assert.Empty(t, resp.Submissions)
+			assert.Empty(ttt, resp.Submissions)
 		})
 	})
 
diff --git a/pkg/server/server_schema_test.go b/pkg/server/server_schema_test.go
index 633322a..87f696b 100644
--- a/pkg/server/server_schema_test.go
+++ b/pkg/server/server_schema_test.go
@@ -4,7 +4,6 @@ import (
 	"fmt"
 	"net/http"
 	"net/http/httptest"
-	"os"
 	"testing"
 
 	"github.com/TBD54566975/ssi-sdk/credential/schema"
@@ -16,19 +15,12 @@ import (
 
 	"github.com/tbd54566975/ssi-service/pkg/server/router"
 	"github.com/tbd54566975/ssi-service/pkg/service/did"
-	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
 
 func TestSchemaAPI(t *testing.T) {
 	t.Run("Test Create Schema", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
@@ -40,7 +32,7 @@ func TestSchemaAPI(t *testing.T) {
 		req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/schemas", schemaRequestValue)
 		w := httptest.NewRecorder()
 
-		err = schemaService.CreateSchema(newRequestContext(), w, req)
+		err := schemaService.CreateSchema(newRequestContext(), w, req)
 		assert.Error(tt, err)
 		assert.Contains(tt, err.Error(), "invalid create schema request")
 
@@ -62,14 +54,8 @@ func TestSchemaAPI(t *testing.T) {
 	})
 
 	t.Run("Test Sign & Verify Schema", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
@@ -82,7 +68,7 @@ func TestSchemaAPI(t *testing.T) {
 		schemaRequest := router.CreateSchemaRequest{Author: "did:test", Name: "test schema", Schema: simpleSchema, Sign: true}
 		schemaRequestValue := newRequestValue(tt, schemaRequest)
 		req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/schemas", schemaRequestValue)
-		err = schemaService.CreateSchema(newRequestContext(), w, req)
+		err := schemaService.CreateSchema(newRequestContext(), w, req)
 		assert.Error(tt, err)
 		assert.Contains(tt, err.Error(), "could not create schema with authoring DID: did:test")
 
@@ -137,14 +123,8 @@ func TestSchemaAPI(t *testing.T) {
 	})
 
 	t.Run("Test Get Schema and Get Schemas", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
@@ -153,7 +133,7 @@ func TestSchemaAPI(t *testing.T) {
 		// get schema that doesn't exist
 		w := httptest.NewRecorder()
 		req := httptest.NewRequest(http.MethodGet, "https://ssi-service.com/v1/schemas/bad", nil)
-		err = schemaService.GetSchema(newRequestContext(), w, req)
+		err := schemaService.GetSchema(newRequestContext(), w, req)
 		assert.Error(tt, err)
 		assert.Contains(tt, err.Error(), "cannot get schema without ID parameter")
 
@@ -226,14 +206,8 @@ func TestSchemaAPI(t *testing.T) {
 	})
 
 	t.Run("Test Delete Schema", func(tt *testing.T) {
-		bolt, err := storage.NewBoltDB()
-		require.NoError(tt, err)
-
-		// remove the db file after the test
-		tt.Cleanup(func() {
-			_ = bolt.Close()
-			_ = os.Remove(storage.DBFile)
-		})
+		bolt := setupTestDB(tt)
+		require.NotNil(tt, bolt)
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
@@ -243,7 +217,7 @@ func TestSchemaAPI(t *testing.T) {
 
 		// delete a schema that doesn't exist
 		req := httptest.NewRequest(http.MethodDelete, "https://ssi-service.com/v1/schemas/bad", nil)
-		err = schemaService.DeleteSchema(newRequestContextWithParams(map[string]string{"id": "bad"}), w, req)
+		err := schemaService.DeleteSchema(newRequestContextWithParams(map[string]string{"id": "bad"}), w, req)
 		assert.Error(tt, err)
 		assert.Contains(tt, err.Error(), "could not delete schema with id: bad")
 
diff --git a/pkg/server/server_test.go b/pkg/server/server_test.go
index 2fcc7a2..70d16c3 100644
--- a/pkg/server/server_test.go
+++ b/pkg/server/server_test.go
@@ -34,11 +34,6 @@ import (
 )
 
 func TestHealthCheckAPI(t *testing.T) {
-	// remove the db file after the test
-	t.Cleanup(func() {
-		_ = os.Remove(storage.DBFile)
-	})
-
 	shutdown := make(chan os.Signal, 1)
 	serviceConfig, err := config.LoadConfig("")
 	assert.NoError(t, err)
@@ -61,14 +56,16 @@ func TestHealthCheckAPI(t *testing.T) {
 }
 
 func TestReadinessAPI(t *testing.T) {
+	dbFile := "test_readiness_api.db"
 	// remove the db file after the test
 	t.Cleanup(func() {
-		_ = os.Remove(storage.DBFile)
+		_ = os.Remove(dbFile)
 	})
 
 	shutdown := make(chan os.Signal, 1)
 	serviceConfig, err := config.LoadConfig("")
 	assert.NoError(t, err)
+	serviceConfig.Services.StorageOption = dbFile
 
 	server, err := NewSSIServer(shutdown, *serviceConfig)
 	assert.NoError(t, err)
@@ -184,7 +181,7 @@ func getValidApplicationRequest(manifestID, presDefID, submissionDescriptorID st
 	}
 }
 
-func testKeyStore(t *testing.T, bolt *storage.BoltDB) (*router.KeyStoreRouter, *keystore.Service) {
+func testKeyStore(t *testing.T, bolt storage.ServiceStorage) (*router.KeyStoreRouter, *keystore.Service) {
 	keyStoreService := testKeyStoreService(t, bolt)
 
 	// create router for service
@@ -222,7 +219,7 @@ func testDIDService(t *testing.T, bolt storage.ServiceStorage, keyStore *keystor
 	return didService
 }
 
-func testDIDRouter(t *testing.T, bolt *storage.BoltDB, keyStore *keystore.Service) *router.DIDRouter {
+func testDIDRouter(t *testing.T, bolt storage.ServiceStorage, keyStore *keystore.Service) *router.DIDRouter {
 	didService := testDIDService(t, bolt, keyStore)
 
 	// create router for service
@@ -239,7 +236,7 @@ func testSchemaService(t *testing.T, bolt storage.ServiceStorage, keyStore *keys
 	return schemaService
 }
 
-func testSchemaRouter(t *testing.T, bolt *storage.BoltDB, keyStore *keystore.Service, did *did.Service) *router.SchemaRouter {
+func testSchemaRouter(t *testing.T, bolt storage.ServiceStorage, keyStore *keystore.Service, did *did.Service) *router.SchemaRouter {
 	schemaService := testSchemaService(t, bolt, keyStore, did)
 
 	// create router for service
@@ -259,7 +256,7 @@ func testCredentialService(t *testing.T, db storage.ServiceStorage, keyStore *ke
 	return credentialService
 }
 
-func testCredentialRouter(t *testing.T, bolt *storage.BoltDB, keyStore *keystore.Service, did *did.Service, schema *schema.Service) *router.CredentialRouter {
+func testCredentialRouter(t *testing.T, bolt storage.ServiceStorage, keyStore *keystore.Service, did *did.Service, schema *schema.Service) *router.CredentialRouter {
 	credentialService := testCredentialService(t, bolt, keyStore, did, schema)
 
 	// create router for service
@@ -270,7 +267,7 @@ func testCredentialRouter(t *testing.T, bolt *storage.BoltDB, keyStore *keystore
 	return credentialRouter
 }
 
-func testManifest(t *testing.T, db *storage.BoltDB, keyStore *keystore.Service, did *did.Service, credential *credential.Service) (*router.ManifestRouter, *manifest.Service) {
+func testManifest(t *testing.T, db storage.ServiceStorage, keyStore *keystore.Service, did *did.Service, credential *credential.Service) (*router.ManifestRouter, *manifest.Service) {
 	serviceConfig := config.ManifestServiceConfig{BaseServiceConfig: &config.BaseServiceConfig{Name: "manifest"}}
 	// create a manifest service
 	manifestService, err := manifest.NewManifestService(serviceConfig, db, keyStore, did.GetResolver(), credential)
diff --git a/pkg/service/keystore/service_test.go b/pkg/service/keystore/service_test.go
index 3fb8a10..9357db7 100644
--- a/pkg/service/keystore/service_test.go
+++ b/pkg/service/keystore/service_test.go
@@ -7,6 +7,7 @@ import (
 	"github.com/TBD54566975/ssi-sdk/crypto"
 	"github.com/mr-tron/base58"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 
 	"github.com/tbd54566975/ssi-service/config"
 	"github.com/tbd54566975/ssi-service/pkg/storage"
@@ -91,14 +92,18 @@ func TestEncryptDecryptAllKeyTypes(t *testing.T) {
 }
 
 func TestStoreAndGetKey(t *testing.T) {
-	bolt, err := storage.NewBoltDB()
+	file, err := os.CreateTemp("", "bolt")
+	require.NoError(t, err)
+	name := file.Name()
+	assert.NoError(t, file.Close())
+	bolt, err := storage.NewStorage(storage.Bolt, name)
 	assert.NoError(t, err)
 	assert.NotEmpty(t, bolt)
 
 	// remove the db file after the test
 	t.Cleanup(func() {
 		_ = bolt.Close()
-		_ = os.Remove(storage.DBFile)
+		_ = os.Remove(bolt.URI())
 	})
 
 	keyStore, err := NewKeyStoreService(
diff --git a/pkg/service/operation/model_test.go b/pkg/service/operation/submission/submission_test.go
similarity index 89%
rename from pkg/service/operation/model_test.go
rename to pkg/service/operation/submission/submission_test.go
index db8084c..14b43b1 100644
--- a/pkg/service/operation/model_test.go
+++ b/pkg/service/operation/submission/submission_test.go
@@ -1,4 +1,4 @@
-package operation
+package submission
 
 import (
 	"testing"
@@ -30,7 +30,7 @@ func TestSubmissionID(t *testing.T) {
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			assert.Equal(t, tt.want, SubmissionID(tt.opID))
+			assert.Equal(t, tt.want, ID(tt.opID))
 		})
 	}
 }
diff --git a/pkg/storage/bolt_test.go b/pkg/storage/bolt_test.go
index 55af21d..8c4e9d4 100644
--- a/pkg/storage/bolt_test.go
+++ b/pkg/storage/bolt_test.go
@@ -131,7 +131,7 @@ func TestBoltDBPrefixAndKeys(t *testing.T) {
 }
 
 func setupBoltDB(t *testing.T) *BoltDB {
-	db, err := NewBoltDBWithFile("test.db")
+	db, err := NewStorage(Bolt, "test.db")
 	assert.NoError(t, err)
 	assert.NotEmpty(t, db)
 
@@ -139,7 +139,7 @@ func setupBoltDB(t *testing.T) *BoltDB {
 		_ = db.Close()
 		_ = os.Remove("test.db")
 	})
-	return db
+	return db.(*BoltDB)
 }
 
 type testStruct struct {