Repository: kurtosis-tech/kurtosis
Pull request #1105 (2023-08-11 19:50:29)

feat: Implements service registration repository in Docker Kurtosis Backend
## Description:
Implements service registration repository in Docker Kurtosis Backend

## Is this change user facing?
NO

## References (if applicable):
this is part of the APIC restart project

@victorcolombo review this after this one: https://github.com/kurtosis-tech/kurtosis/pull/1095 get merged



Patch:
diff --git a/.circleci/config.yml b/.circleci/config.yml
index b6a880600..cddbb2da4 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -774,6 +774,24 @@ jobs:
       - run: "${KURTOSIS_BINPATH} engine restart"
       - run: "${KURTOSIS_BINPATH} engine status"
 
+      # Test APIC restart
+      - when:
+          condition:
+            equal: [ "docker", << parameters.cli-cluster-backend >> ]
+          steps:
+            - run:
+                name: Test APIC restart
+                command: |
+                  ${KURTOSIS_BINPATH} enclave add -n test-apic-restart
+                  ${KURTOSIS_BINPATH} enclave inspect --full-uuids test-apic-restart > /tmp/inspect_output.txt
+                  inspect_output_uuid_line=$(grep "^UUID:" /tmp/inspect_output.txt) 
+                  enclave_uuid=$(echo ${inspect_output_uuid_line:17:54})
+                  ${KURTOSIS_BINPATH} service add test-apic-restart service-test kurtosistech/example-datastore-server
+                  apic_container_id=$(docker ps --filter "label=com.kurtosistech.container-type=api-container" --filter "label=com.kurtosistech.enclave-id=$(echo $enclave_uuid)" --format "{{.ID}}")
+                  docker container restart $(echo $apic_container_id)
+                  ${KURTOSIS_BINPATH} service rm test-apic-restart service-test
+
+      # Clean all at the end
       - run: "${KURTOSIS_BINPATH} clean -a"
 
       # Ensure Kubernetes resources clean up successfully
diff --git a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/backend_creator/backend_creator.go b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/backend_creator/backend_creator.go
index 622fbe8c7..99fb9caca 100644
--- a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/backend_creator/backend_creator.go
+++ b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/backend_creator/backend_creator.go
@@ -14,6 +14,7 @@ import (
 	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/enclave"
 	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/enclave_db"
 	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/enclave_db/free_ip_addr_tracker"
+	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/enclave_db/service_registration"
 	"github.com/kurtosis-tech/stacktrace"
 	"github.com/sirupsen/logrus"
 	"net"
@@ -166,6 +167,9 @@ func getDockerKurtosisBackend(
 	// If running within the API container context, detect the network that the API container is running inside
 	// so, we can create the free IP address trackers
 	enclaveFreeIpAddrTrackers := map[enclave.EnclaveUUID]*free_ip_addr_tracker.FreeIpAddrTracker{}
+
+	// It's only used by API container so can be nil for other contexts
+	var serviceRegistrationRepository *service_registration.ServiceRegistrationRepository
 	if optionalApiContainerModeArgs != nil {
 		enclaveDb, err := enclave_db.GetOrCreateEnclaveDatabase()
 		if err != nil {
@@ -219,9 +223,14 @@ func getDockerKurtosisBackend(
 		}
 
 		enclaveFreeIpAddrTrackers[enclaveUuid] = freeIpAddrProvider
+
+		serviceRegistrationRepository, err = service_registration.GetOrCreateNewServiceRegistrationRepository(enclaveDb)
+		if err != nil {
+			return nil, stacktrace.Propagate(err, "An error occurred creating the service registration repository")
+		}
 	}
 
-	dockerKurtosisBackend := docker_kurtosis_backend.NewDockerKurtosisBackend(dockerManager, enclaveFreeIpAddrTrackers)
+	dockerKurtosisBackend := docker_kurtosis_backend.NewDockerKurtosisBackend(dockerManager, enclaveFreeIpAddrTrackers, serviceRegistrationRepository)
 
 	wrappedBackend := metrics_reporting.NewMetricsReportingKurtosisBackend(dockerKurtosisBackend)
 
diff --git a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/docker_kurtosis_backend.go b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/docker_kurtosis_backend.go
index 53ed14932..20feafad4 100644
--- a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/docker_kurtosis_backend.go
+++ b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/docker_kurtosis_backend.go
@@ -23,6 +23,7 @@ import (
 	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/logs_collector"
 	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service"
 	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/enclave_db/free_ip_addr_tracker"
+	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/enclave_db/service_registration"
 	"github.com/kurtosis-tech/stacktrace"
 	"io"
 	"sync"
@@ -49,11 +50,7 @@ type DockerKurtosisBackend struct {
 	// This map is set exactly once, upon creation of the DockerKubernetesBackend, and never modified afterwards. Therefore, it doesn't need to be protected with a mutex (because the FreeIPProviders are themselves threadsafe)
 	enclaveFreeIpProviders map[enclave.EnclaveUUID]*free_ip_addr_tracker.FreeIpAddrTracker
 
-	// TODO Migrate this to an on-disk database, so that the API container can be shut down & restarted!
-	// Canonical store of the registrations being tracked by this *DockerKurtosisBackend instance
-	// NOTE: Unlike Kubernetes, Docker doesn't have a concrete object representing a service registration/IP address
-	//  allocation. We use this in-memory store to accomplish the same thing.
-	serviceRegistrations map[enclave.EnclaveUUID]map[service.ServiceUUID]*service.ServiceRegistration
+	serviceRegistrationRepository *service_registration.ServiceRegistrationRepository
 
 	// Control concurrent access to serviceRegistrations
 	serviceRegistrationMutex *sync.Mutex
@@ -62,19 +59,16 @@ type DockerKurtosisBackend struct {
 func NewDockerKurtosisBackend(
 	dockerManager *docker_manager.DockerManager,
 	enclaveFreeIpProviders map[enclave.EnclaveUUID]*free_ip_addr_tracker.FreeIpAddrTracker,
+	serviceRegistrationRepository *service_registration.ServiceRegistrationRepository,
 ) *DockerKurtosisBackend {
 	dockerNetworkAllocator := docker_network_allocator.NewDockerNetworkAllocator(dockerManager)
-	serviceRegistrations := map[enclave.EnclaveUUID]map[service.ServiceUUID]*service.ServiceRegistration{}
-	for enclaveUuid := range enclaveFreeIpProviders {
-		serviceRegistrations[enclaveUuid] = map[service.ServiceUUID]*service.ServiceRegistration{}
-	}
 	return &DockerKurtosisBackend{
-		dockerManager:            dockerManager,
-		dockerNetworkAllocator:   dockerNetworkAllocator,
-		objAttrsProvider:         object_attributes_provider.GetDockerObjectAttributesProvider(),
-		enclaveFreeIpProviders:   enclaveFreeIpProviders,
-		serviceRegistrations:     serviceRegistrations,
-		serviceRegistrationMutex: &sync.Mutex{},
+		dockerManager:                 dockerManager,
+		dockerNetworkAllocator:        dockerNetworkAllocator,
+		objAttrsProvider:              object_attributes_provider.GetDockerObjectAttributesProvider(),
+		enclaveFreeIpProviders:        enclaveFreeIpProviders,
+		serviceRegistrationRepository: serviceRegistrationRepository,
+		serviceRegistrationMutex:      &sync.Mutex{},
 	}
 }
 
@@ -148,15 +142,6 @@ func (backend *DockerKurtosisBackend) DumpKurtosis(ctx context.Context, outputDi
 }
 
 func (backend *DockerKurtosisBackend) RegisterUserServices(_ context.Context, enclaveUuid enclave.EnclaveUUID, services map[service.ServiceName]bool) (map[service.ServiceName]*service.ServiceRegistration, map[service.ServiceName]error, error) {
-	serviceRegistrationsForEnclave, found := backend.serviceRegistrations[enclaveUuid]
-	if !found {
-		return nil, nil, stacktrace.NewError(
-			"No service registrations are being tracked for enclave '%v'; this likely means that the registration "+
-				"request is being called where it shouldn't be (i.e. outside the API container)",
-			enclaveUuid,
-		)
-	}
-
 	freeIpAddrProviderForEnclave, found := backend.enclaveFreeIpProviders[enclaveUuid]
 	if !found {
 		return nil, nil, stacktrace.NewError(
@@ -167,7 +152,7 @@ func (backend *DockerKurtosisBackend) RegisterUserServices(_ context.Context, en
 		)
 	}
 
-	registeredService, failedServices, err := user_service_functions.RegisterUserServices(enclaveUuid, services, serviceRegistrationsForEnclave, freeIpAddrProviderForEnclave, backend.serviceRegistrationMutex)
+	registeredService, failedServices, err := user_service_functions.RegisterUserServices(enclaveUuid, services, backend.serviceRegistrationRepository, freeIpAddrProviderForEnclave, backend.serviceRegistrationMutex)
 	if err != nil {
 		return nil, nil, stacktrace.Propagate(err, "Unexpected error registering services to enclave '%s'", enclaveUuid)
 	}
@@ -175,15 +160,6 @@ func (backend *DockerKurtosisBackend) RegisterUserServices(_ context.Context, en
 }
 
 func (backend *DockerKurtosisBackend) UnregisterUserServices(_ context.Context, enclaveUuid enclave.EnclaveUUID, services map[service.ServiceUUID]bool) (map[service.ServiceUUID]bool, map[service.ServiceUUID]error, error) {
-	serviceRegistrationsForEnclave, found := backend.serviceRegistrations[enclaveUuid]
-	if !found {
-		return nil, nil, stacktrace.NewError(
-			"No service registrations are being tracked for enclave '%v'; this likely means that the registration "+
-				"request is being called where it shouldn't be (i.e. outside the API container)",
-			enclaveUuid,
-		)
-	}
-
 	freeIpAddrProviderForEnclave, found := backend.enclaveFreeIpProviders[enclaveUuid]
 	if !found {
 		return nil, nil, stacktrace.NewError(
@@ -194,20 +170,15 @@ func (backend *DockerKurtosisBackend) UnregisterUserServices(_ context.Context,
 		)
 	}
 
-	servicesSuccessfullyUnregistered, failedServices := user_service_functions.UnregisterUserServices(services, serviceRegistrationsForEnclave, freeIpAddrProviderForEnclave, backend.serviceRegistrationMutex)
+	servicesSuccessfullyUnregistered, failedServices, err := user_service_functions.UnregisterUserServices(enclaveUuid, services, backend.serviceRegistrationRepository, freeIpAddrProviderForEnclave, backend.serviceRegistrationMutex)
+	if err != nil {
+		return nil, nil, stacktrace.Propagate(err, "An error occurred unregistering services '%+v' for enclave with UUID '%v'", services, enclaveUuid)
+	}
+
 	return servicesSuccessfullyUnregistered, failedServices, nil
 }
 
 func (backend *DockerKurtosisBackend) StartRegisteredUserServices(ctx context.Context, enclaveUuid enclave.EnclaveUUID, services map[service.ServiceUUID]*service.ServiceConfig) (map[service.ServiceUUID]*service.Service, map[service.ServiceUUID]error, error) {
-	serviceRegistrationsForEnclave, found := backend.serviceRegistrations[enclaveUuid]
-	if !found {
-		return nil, nil, stacktrace.NewError(
-			"No service registrations are being tracked for enclave '%v'; this likely means that the registration "+
-				"request is being called where it shouldn't be (i.e. outside the API container)",
-			enclaveUuid,
-		)
-	}
-
 	freeIpAddrProviderForEnclave, found := backend.enclaveFreeIpProviders[enclaveUuid]
 	if !found {
 		return nil, nil, stacktrace.NewError(
@@ -237,7 +208,7 @@ func (backend *DockerKurtosisBackend) StartRegisteredUserServices(ctx context.Co
 		ctx,
 		enclaveUuid,
 		services,
-		serviceRegistrationsForEnclave,
+		backend.serviceRegistrationRepository,
 		logsCollector,
 		logsCollectorAvailabilityChecker,
 		backend.objAttrsProvider,
@@ -250,20 +221,11 @@ func (backend *DockerKurtosisBackend) StartRegisteredUserServices(ctx context.Co
 }
 
 func (backend *DockerKurtosisBackend) RemoveRegisteredUserServiceProcesses(ctx context.Context, enclaveUuid enclave.EnclaveUUID, services map[service.ServiceUUID]bool) (map[service.ServiceUUID]bool, map[service.ServiceUUID]error, error) {
-	serviceRegistrationsForEnclave, found := backend.serviceRegistrations[enclaveUuid]
-	if !found {
-		return nil, nil, stacktrace.NewError(
-			"No service registrations are being tracked for enclave '%v'; this likely means that the registration "+
-				"request is being called where it shouldn't be (i.e. outside the API container)",
-			enclaveUuid,
-		)
-	}
-
 	successfullyStartedService, failedService, err := user_service_functions.RemoveRegisteredUserServiceProcesses(
 		ctx,
 		enclaveUuid,
 		services,
-		serviceRegistrationsForEnclave,
+		backend.serviceRegistrationRepository,
 		backend.dockerManager)
 	if err != nil {
 		return nil, nil, stacktrace.Propagate(err, "Unexpected error while updating user services")
@@ -341,14 +303,7 @@ func (backend *DockerKurtosisBackend) StopUserServices(
 	resultErroredServiceUUIDs map[service.ServiceUUID]error,
 	resultErr error,
 ) {
-	serviceRegistrationsForEnclave, found := backend.serviceRegistrations[enclaveUuid]
-	if !found {
-		return nil, nil, stacktrace.NewError(
-			"No service registrations are being tracked for enclave '%v'",
-			enclaveUuid,
-		)
-	}
-	return user_service_functions.StopUserServices(ctx, enclaveUuid, filters, serviceRegistrationsForEnclave, backend.dockerManager)
+	return user_service_functions.StopUserServices(ctx, enclaveUuid, filters, backend.serviceRegistrationRepository, backend.dockerManager)
 }
 
 func (backend *DockerKurtosisBackend) DestroyUserServices(
@@ -360,15 +315,6 @@ func (backend *DockerKurtosisBackend) DestroyUserServices(
 	resultErroredUuids map[service.ServiceUUID]error,
 	resultErr error,
 ) {
-	serviceRegistrationsForEnclave, found := backend.serviceRegistrations[enclaveUuid]
-	if !found {
-		return nil, nil, stacktrace.NewError(
-			"No service registrations are being tracked for enclave '%v'; this likely means that the registration "+
-				"request is being called where it shouldn't be (i.e. outside the API container)",
-			enclaveUuid,
-		)
-	}
-
 	freeIpAddrProviderForEnclave, found := backend.enclaveFreeIpProviders[enclaveUuid]
 	if !found {
 		return nil, nil, stacktrace.NewError(
@@ -382,7 +328,7 @@ func (backend *DockerKurtosisBackend) DestroyUserServices(
 		ctx,
 		enclaveUuid,
 		filters,
-		serviceRegistrationsForEnclave,
+		backend.serviceRegistrationRepository,
 		backend.serviceRegistrationMutex,
 		freeIpAddrProviderForEnclave,
 		backend.dockerManager)
diff --git a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/docker_kurtosis_backend_enclave_functions.go b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/docker_kurtosis_backend_enclave_functions.go
index e2b19a172..c3a577d17 100644
--- a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/docker_kurtosis_backend_enclave_functions.go
+++ b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/docker_kurtosis_backend_enclave_functions.go
@@ -328,13 +328,6 @@ func (backend *DockerKurtosisBackend) DestroyEnclaves(
 				enclaveUuid,
 			)
 		}
-		if _, found := backend.serviceRegistrations[enclaveUuid]; found {
-			return nil, nil, stacktrace.NewError(
-				"Received a request to destroy enclave '%v' for which services are being tracked; this likely "+
-					"means that destroy enclave is being called where it shouldn't be (i.e. inside the API container)",
-				enclaveUuid,
-			)
-		}
 	}
 
 	erroredEnclaveUuids := map[enclave.EnclaveUUID]error{}
diff --git a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/user_services_functions/destroy_user_services.go b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/user_services_functions/destroy_user_services.go
index 43fa93b13..0af129d48 100644
--- a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/user_services_functions/destroy_user_services.go
+++ b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/user_services_functions/destroy_user_services.go
@@ -6,6 +6,7 @@ import (
 	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/enclave"
 	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service"
 	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/enclave_db/free_ip_addr_tracker"
+	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/enclave_db/service_registration"
 	"github.com/kurtosis-tech/stacktrace"
 	"sync"
 )
@@ -27,7 +28,7 @@ func DestroyUserServices(
 	ctx context.Context,
 	enclaveUuid enclave.EnclaveUUID,
 	filters *service.ServiceFilters,
-	serviceRegistrationsForEnclave map[service.ServiceUUID]*service.ServiceRegistration,
+	serviceRegistrationRepository *service_registration.ServiceRegistrationRepository,
 	serviceRegistrationMutex *sync.Mutex,
 	freeIpProviderForEnclave *free_ip_addr_tracker.FreeIpAddrTracker,
 	dockerManager *docker_manager.DockerManager,
@@ -40,7 +41,7 @@ func DestroyUserServices(
 	serviceRegistrationMutex.Lock()
 	defer serviceRegistrationMutex.Unlock()
 
-	successfulUuids, erroredUuids, err := destroyUserServicesUnlocked(ctx, enclaveUuid, filters, serviceRegistrationsForEnclave, freeIpProviderForEnclave, dockerManager)
+	successfulUuids, erroredUuids, err := destroyUserServicesUnlocked(ctx, enclaveUuid, filters, serviceRegistrationRepository, freeIpProviderForEnclave, dockerManager)
 	if err != nil {
 		return nil, nil, stacktrace.Propagate(err, "An error occurred while destroying user services")
 	}
diff --git a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/user_services_functions/package_private_helpers.go b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/user_services_functions/package_private_helpers.go
index 7e28f33ca..d1c8bcf2a 100644
--- a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/user_services_functions/package_private_helpers.go
+++ b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/user_services_functions/package_private_helpers.go
@@ -9,6 +9,7 @@ import (
 	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/enclave"
 	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service"
 	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/enclave_db/free_ip_addr_tracker"
+	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/enclave_db/service_registration"
 	"github.com/kurtosis-tech/stacktrace"
 	"github.com/sirupsen/logrus"
 	"strings"
@@ -16,9 +17,9 @@ import (
 
 func destroyUserServicesUnlocked(
 	ctx context.Context,
-	enclaveId enclave.EnclaveUUID,
+	enclaveUuid enclave.EnclaveUUID,
 	filters *service.ServiceFilters,
-	serviceRegistrationsForEnclave map[service.ServiceUUID]*service.ServiceRegistration,
+	serviceRegistrationRepository *service_registration.ServiceRegistrationRepository,
 	enclaveFreeIpProvidersForEnclave *free_ip_addr_tracker.FreeIpAddrTracker,
 	dockerManager *docker_manager.DockerManager,
 ) (
@@ -29,6 +30,12 @@ func destroyUserServicesUnlocked(
 	// We filter registrations here because a registration is the canonical resource for a Kurtosis user service - no registration,
 	// no Kurtosis service - and not all registrations will have Docker resources
 	matchingRegistrations := map[service.ServiceUUID]*service.ServiceRegistration{}
+
+	serviceRegistrationsForEnclave, err := serviceRegistrationRepository.GetAllEnclaveServiceRegistrations(enclaveUuid)
+	if err != nil {
+		return nil, nil, stacktrace.Propagate(err, "An error occurred getting all enclave service registrations from the repository for enclave with UUID '%v'", enclaveUuid)
+	}
+
 	for uuid, registration := range serviceRegistrationsForEnclave {
 		if filters.UUIDs != nil && len(filters.UUIDs) > 0 {
 			if _, found := filters.UUIDs[registration.GetUUID()]; !found {
@@ -47,7 +54,7 @@ func destroyUserServicesUnlocked(
 
 	// NOTE: This may end up with less results here than we have registrations, if the user registered but did not start a service,
 	// though we should never end up with _more_ Docker resources
-	allServiceObjs, allDockerResources, err := shared_helpers.GetMatchingUserServiceObjsAndDockerResourcesNoMutex(ctx, enclaveId, filters, dockerManager)
+	allServiceObjs, allDockerResources, err := shared_helpers.GetMatchingUserServiceObjsAndDockerResourcesNoMutex(ctx, enclaveUuid, filters, dockerManager)
 	if err != nil {
 		return nil, nil, stacktrace.Propagate(err, "An error occurred getting user services matching filters '%+v'", filters)
 	}
@@ -127,7 +134,20 @@ func destroyUserServicesUnlocked(
 		if err = enclaveFreeIpProvidersForEnclave.ReleaseIpAddr(ipAddr); err != nil {
 			logrus.Errorf("Error releasing IP address '%v'", ipAddr)
 		}
-		delete(serviceRegistrationsForEnclave, uuid)
+
+		serviceRegistration, found := serviceRegistrationsForEnclave[uuid]
+		if !found {
+			erroredUuids[uuid] = stacktrace.NewError("Failed to get service registration for service UUID '%v'. This should never happen. This is a Kurtosis bug.", uuid)
+			delete(successfulUuids, uuid)
+			continue
+		}
+
+		serviceName := serviceRegistration.GetName()
+		if err := serviceRegistrationRepository.Delete(serviceName); err != nil {
+			erroredUuids[uuid] = stacktrace.Propagate(err, "An error occurred deleting the service registration for service '%v' from the repository", serviceName)
+			delete(successfulUuids, uuid)
+			continue
+		}
 	}
 
 	return successfulUuids, erroredUuids, nil
diff --git a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/user_services_functions/start_user_services.go b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/user_services_functions/start_user_services.go
index 69bf3795b..3662c7180 100644
--- a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/user_services_functions/start_user_services.go
+++ b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/user_services_functions/start_user_services.go
@@ -4,6 +4,7 @@ import (
 	"context"
 	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/logs_collector_functions"
 	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/logs_collector"
+	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/enclave_db/service_registration"
 	"strings"
 	"sync"
 
@@ -31,7 +32,7 @@ const (
 func RegisterUserServices(
 	enclaveUuid enclave.EnclaveUUID,
 	servicesToRegister map[service.ServiceName]bool,
-	serviceRegistrationsForEnclave map[service.ServiceUUID]*service.ServiceRegistration,
+	serviceRegistrationRepository *service_registration.ServiceRegistrationRepository,
 	freeIpProvidersForEnclave *free_ip_addr_tracker.FreeIpAddrTracker,
 	serviceRegistrationMutex *sync.Mutex,
 ) (
@@ -50,7 +51,7 @@ func RegisterUserServices(
 		return successfulServicesPool, failedServicesPool, nil
 	}
 
-	successfulRegistrations, failedRegistrations, err := registerUserServices(enclaveUuid, servicesToRegister, serviceRegistrationsForEnclave, freeIpProvidersForEnclave)
+	successfulRegistrations, failedRegistrations, err := registerUserServices(enclaveUuid, servicesToRegister, serviceRegistrationRepository, freeIpProvidersForEnclave)
 	if err != nil {
 		return nil, nil, stacktrace.Propagate(err, "An error occurred registering services with Names '%v'", servicesToRegister)
 	}
@@ -60,13 +61,15 @@ func RegisterUserServices(
 // UnregisterUserServices unregisters all services currently registered for this enclave.
 // If the service is not registered for this enclave, it no-ops and the service is returned as "successfully unregistered"
 func UnregisterUserServices(
+	enclaveUuid enclave.EnclaveUUID,
 	serviceUUIDsToUnregister map[service.ServiceUUID]bool,
-	enclaveServiceRegistrations map[service.ServiceUUID]*service.ServiceRegistration,
+	serviceRegistrationRepository *service_registration.ServiceRegistrationRepository,
 	freeIpAddrProviderForEnclave *free_ip_addr_tracker.FreeIpAddrTracker,
 	serviceRegistrationMutex *sync.Mutex,
 ) (
 	map[service.ServiceUUID]bool,
 	map[service.ServiceUUID]error,
+	error,
 ) {
 	serviceRegistrationMutex.Lock()
 	defer serviceRegistrationMutex.Unlock()
@@ -74,7 +77,12 @@ func UnregisterUserServices(
 	servicesFailed := map[service.ServiceUUID]error{}
 
 	if len(serviceUUIDsToUnregister) == 0 {
-		return servicesSuccessfullyUnregistered, servicesFailed
+		return servicesSuccessfullyUnregistered, servicesFailed, nil
+	}
+
+	enclaveServiceRegistrations, err := serviceRegistrationRepository.GetAllEnclaveServiceRegistrations(enclaveUuid)
+	if err != nil {
+		return nil, nil, stacktrace.Propagate(err, "An error occurred getting all enclave service registrations from the repository for enclave with UUID '%v'", enclaveUuid)
 	}
 
 	for serviceUuid := range serviceUUIDsToUnregister {
@@ -85,21 +93,28 @@ func UnregisterUserServices(
 		}
 
 		serviceIpAddr := serviceRegistration.GetPrivateIP()
+
 		if err := freeIpAddrProviderForEnclave.ReleaseIpAddr(serviceIpAddr); err != nil {
 			servicesFailed[serviceUuid] = err
-		} else {
-			delete(enclaveServiceRegistrations, serviceUuid)
-			servicesSuccessfullyUnregistered[serviceUuid] = true
+			continue
 		}
+
+		if err := serviceRegistrationRepository.Delete(serviceRegistration.GetName()); err != nil {
+			servicesFailed[serviceUuid] = err
+			continue
+		}
+
+		servicesSuccessfullyUnregistered[serviceUuid] = true
+
 	}
-	return servicesSuccessfullyUnregistered, servicesFailed
+	return servicesSuccessfullyUnregistered, servicesFailed, nil
 }
 
 func StartRegisteredUserServices(
 	ctx context.Context,
 	enclaveUuid enclave.EnclaveUUID,
 	services map[service.ServiceUUID]*service.ServiceConfig,
-	serviceRegistrations map[service.ServiceUUID]*service.ServiceRegistration,
+	serviceRegistrationRepository *service_registration.ServiceRegistrationRepository,
 	logsCollector *logs_collector.LogsCollector,
 	logsCollectorAvailabilityChecker logs_collector_functions.LogsCollectorAvailabilityChecker,
 	objAttrsProvider object_attributes_provider.DockerObjectAttributesProvider,
@@ -115,6 +130,12 @@ func StartRegisteredUserServices(
 
 	serviceConfigsToStart := map[service.ServiceUUID]*service.ServiceConfig{}
 	serviceRegistrationsToStart := map[service.ServiceUUID]*service.ServiceRegistration{}
+
+	serviceRegistrations, err := serviceRegistrationRepository.GetAllEnclaveServiceRegistrations(enclaveUuid)
+	if err != nil {
+		return nil, nil, stacktrace.Propagate(err, "An error occurred getting all enclave service registrations from the repository for enclave with UUID '%v'", enclaveUuid)
+	}
+
 	for serviceUuid, serviceConfig := range services {
 		serviceRegistration, found := serviceRegistrations[serviceUuid]
 		if !found {
@@ -143,7 +164,7 @@ func StartRegisteredUserServices(
 			// If the first service to start is stopped, we know that the other ones are too because
 			// of a check done at the service network layer.
 			// Restarting stopped services is a much lighter operation so we branch out to a simpler function
-			return restartUserServices(ctx, enclaveUuid, serviceRegistrationsToStart, dockerManager)
+			return restartUserServices(ctx, enclaveUuid, serviceRegistrationsToStart, serviceRegistrationRepository, dockerManager)
 		}
 	}
 
@@ -207,7 +228,14 @@ func StartRegisteredUserServices(
 	// Add operations to their respective pools
 	for serviceUuid, successfullyStartedService := range successfulStarts {
 		successfulServicesPool[serviceUuid] = successfullyStartedService
-		serviceRegistrations[serviceUuid].SetStatus(service.ServiceStatus_Started)
+		serviceName := successfullyStartedService.GetRegistration().GetName()
+		serviceStatus := service.ServiceStatus_Started
+		if err := serviceRegistrationRepository.UpdateStatus(serviceName, serviceStatus); err != nil {
+			failedServicesPool[serviceUuid] = stacktrace.Propagate(err, "An error occurred while updating service status to '%s' in service registration for service '%s'", serviceStatus, serviceName)
+			delete(successfulStarts, serviceUuid)
+			delete(successfulServicesPool, serviceUuid)
+			continue
+		}
 	}
 
 	for serviceUuid, serviceErr := range failedStarts {
@@ -222,7 +250,7 @@ func RemoveRegisteredUserServiceProcesses(
 	ctx context.Context,
 	enclaveUuid enclave.EnclaveUUID,
 	services map[service.ServiceUUID]bool,
-	serviceRegistrations map[service.ServiceUUID]*service.ServiceRegistration,
+	serviceRegistrationRepository *service_registration.ServiceRegistrationRepository,
 	dockerManager *docker_manager.DockerManager,
 ) (
 	map[service.ServiceUUID]bool,
@@ -232,6 +260,11 @@ func RemoveRegisteredUserServiceProcesses(
 	successfullyRemovedService := map[service.ServiceUUID]bool{}
 	failedServicesPool := map[service.ServiceUUID]error{}
 
+	serviceRegistrations, err := serviceRegistrationRepository.GetAllEnclaveServiceRegistrations(enclaveUuid)
+	if err != nil {
+		return nil, nil, stacktrace.Propagate(err, "An error occurred getting all enclave service registrations from the repository for enclave with UUID '%v'", enclaveUuid)
+	}
+
 	serviceUuidsToUpdate := map[service.ServiceUUID]bool{}
 	for serviceUuid := range services {
 		if _, found := serviceRegistrations[serviceUuid]; found {
@@ -311,6 +344,7 @@ func restartUserServices(
 	ctx context.Context,
 	enclaveUuid enclave.EnclaveUUID,
 	serviceRegistrations map[service.ServiceUUID]*service.ServiceRegistration,
+	serviceRegistrationRepository *service_registration.ServiceRegistrationRepository,
 	dockerManager *docker_manager.DockerManager,
 ) (
 	map[service.ServiceUUID]*service.Service,
@@ -319,8 +353,10 @@ func restartUserServices(
 ) {
 
 	serviceUuids := map[service.ServiceUUID]bool{}
-	for serviceUuid := range serviceRegistrations {
+	serviceNamesByUuids := map[service.ServiceUUID]service.ServiceName{}
+	for serviceUuid, serviceRegistration := range serviceRegistrations {
 		serviceUuids[serviceUuid] = true
+		serviceNamesByUuids[serviceUuid] = serviceRegistration.GetName()
 	}
 	startServiceFilters := &service.ServiceFilters{
 		Names:    nil,
@@ -369,13 +405,26 @@ func restartUserServices(
 	successfulServices := map[service.ServiceUUID]*service.Service{}
 	for uuidStr := range successfulUuidStrs {
 		serviceUuid := service.ServiceUUID(uuidStr)
-		successfulServices[service.ServiceUUID(serviceUuid)] = service.NewService(
+		serviceName, found := serviceNamesByUuids[serviceUuid]
+		if !found {
+			erroredUuidStrs[uuidStr] = stacktrace.NewError("Expected to find service name by UUID '%v' in map '%+v', but none was found; this is a bug in Kurtosis", serviceUuid, serviceNamesByUuids)
+			continue
+		}
+
+		successfulServices[serviceUuid] = service.NewService(
 			serviceRegistrations[serviceUuid],
 			container_status.ContainerStatus_Running,
 			nil,
 			nil,
-			nil)
-		serviceRegistrations[serviceUuid].SetStatus(service.ServiceStatus_Started)
+			nil,
+		)
+
+		serviceStatus := service.ServiceStatus_Started
+		if err := serviceRegistrationRepository.UpdateStatus(serviceName, serviceStatus); err != nil {
+			erroredUuidStrs[uuidStr] = stacktrace.Propagate(err, "An error occurred while updating service status to '%s' in service registration for service '%s'", serviceStatus, serviceName)
+			delete(successfulServices, serviceUuid)
+			continue
+		}
 	}
 
 	erroredUuids := map[service.ServiceUUID]error{}
@@ -708,7 +757,7 @@ func checkPrivateAndPublicPortsAreOneToOne(privatePorts map[string]*port_spec.Po
 func registerUserServices(
 	enclaveUuid enclave.EnclaveUUID,
 	serviceNames map[service.ServiceName]bool,
-	serviceRegistrationsForEnclave map[service.ServiceUUID]*service.ServiceRegistration,
+	serviceRegistrationRepository *service_registration.ServiceRegistrationRepository,
 	freeIpAddrProvider *free_ip_addr_tracker.FreeIpAddrTracker) (map[service.ServiceName]*service.ServiceRegistration, map[service.ServiceName]error, error) {
 	successfulServicesPool := map[service.ServiceName]*service.ServiceRegistration{}
 	failedServicesPool := map[service.ServiceName]error{}
@@ -750,11 +799,16 @@ func registerUserServices(
 			string(serviceName), // in Docker, hostname = serviceName because we're setting the "alias" of the container to serviceName
 		)
 
-		serviceRegistrationsForEnclave[serviceUuid] = registration
+		if err := serviceRegistrationRepository.Save(registration); err != nil {
+			failedRegistrations[serviceName] = stacktrace.Propagate(err, "An error occurred saving service registration '%+v' for service '%s'", registration, serviceName)
+		}
+
 		shouldRemoveRegistration := true
 		defer func() {
 			if shouldRemoveRegistration {
-				delete(serviceRegistrationsForEnclave, serviceUuid)
+				if err := serviceRegistrationRepository.Delete(serviceName); err != nil {
+					logrus.Errorf("We tried to delete the service registration for service  '%s' we had stored but failed:\n%v", serviceName, err)
+				}
 			}
 		}()
 
diff --git a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/user_services_functions/stop_user_services.go b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/user_services_functions/stop_user_services.go
index 407c61b18..c5300e424 100644
--- a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/user_services_functions/stop_user_services.go
+++ b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/user_services_functions/stop_user_services.go
@@ -7,6 +7,7 @@ import (
 	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_impls/docker/docker_operation_parallelizer"
 	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/enclave"
 	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service"
+	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/enclave_db/service_registration"
 	"github.com/kurtosis-tech/stacktrace"
 )
 
@@ -14,7 +15,7 @@ func StopUserServices(
 	ctx context.Context,
 	enclaveUuid enclave.EnclaveUUID,
 	filters *service.ServiceFilters,
-	serviceRegistrations map[service.ServiceUUID]*service.ServiceRegistration,
+	serviceRegistrationRepository *service_registration.ServiceRegistrationRepository,
 	dockerManager *docker_manager.DockerManager,
 ) (
 	resultSuccessfulServiceUUIDs map[service.ServiceUUID]bool,
@@ -48,6 +49,11 @@ func StopUserServices(
 		return nil
 	}
 
+	serviceRegistrationsByServiceUuid, err := serviceRegistrationRepository.GetAllEnclaveServiceRegistrations(enclaveUuid)
+	if err != nil {
+		return nil, nil, stacktrace.Propagate(err, "An error occurred getting all enclave service registrations from the repository for enclave with UUID '%v'", enclaveUuid)
+	}
+
 	successfulUuidStrs, erroredUuidStrs, err := docker_operation_parallelizer.RunDockerOperationInParallelForKurtosisObjects(
 		ctx,
 		servicesToStopByContainerId,
@@ -63,7 +69,19 @@ func StopUserServices(
 	for uuidStr := range successfulUuidStrs {
 		serviceUuid := service.ServiceUUID(uuidStr)
 		successfulUuids[serviceUuid] = true
-		serviceRegistrations[serviceUuid].SetStatus(service.ServiceStatus_Stopped)
+		serviceRegistration, found := serviceRegistrationsByServiceUuid[serviceUuid]
+		if !found {
+			erroredUuidStrs[uuidStr] = stacktrace.NewError("Expected to find service registration by service UUID '%v' in map '%+v', but none was found; this is a bug in Kurtosis", serviceUuid, serviceRegistrationsByServiceUuid)
+			delete(successfulUuidStrs, uuidStr)
+			continue
+		}
+		serviceName := serviceRegistration.GetName()
+		serviceStatus := service.ServiceStatus_Stopped
+		if err := serviceRegistrationRepository.UpdateStatus(serviceName, serviceStatus); err != nil {
+			erroredUuidStrs[uuidStr] = stacktrace.Propagate(err, "An error occurred while updating service status to '%s' in service registration for service '%s'", serviceStatus, serviceName)
+			delete(successfulUuidStrs, uuidStr)
+			continue
+		}
 	}
 
 	erroredUuids := map[service.ServiceUUID]error{}
diff --git a/container-engine-lib/lib/backend_interface/objects/port_spec/port_spec.go b/container-engine-lib/lib/backend_interface/objects/port_spec/port_spec.go
index 62df222d1..3a6e0cf1f 100644
--- a/container-engine-lib/lib/backend_interface/objects/port_spec/port_spec.go
+++ b/container-engine-lib/lib/backend_interface/objects/port_spec/port_spec.go
@@ -1,14 +1,21 @@
 package port_spec
 
 import (
+	"encoding/json"
 	"github.com/kurtosis-tech/stacktrace"
 )
 
 type PortSpec struct {
-	number              uint16
-	transportProtocol   TransportProtocol
-	applicationProtocol *string
-	wait                *Wait
+	// we do this way in order to have exported fields which can be marshalled
+	// and an unexported type for encapsulation
+	privatePortSpec *privatePortSpec
+}
+
+type privatePortSpec struct {
+	Number              uint16
+	TransportProtocol   TransportProtocol
+	ApplicationProtocol *string
+	Wait                *Wait
 }
 
 // This method accepts port number, transportProtocol, and application protocol (which is optional), and port wait
@@ -28,28 +35,48 @@ func NewPortSpec(
 		return nil, stacktrace.NewError("Unrecognized transportProtocol '%v'", transportProtocol.String())
 	}
 
-	portSpec := &PortSpec{
-		number:              number,
-		transportProtocol:   transportProtocol,
-		applicationProtocol: appProtocol,
-		wait:                wait,
+	internalPortSpec := &privatePortSpec{
+		Number:              number,
+		TransportProtocol:   transportProtocol,
+		ApplicationProtocol: appProtocol,
+		Wait:                wait,
 	}
 
-	return portSpec, nil
+	portSpecObj := &PortSpec{internalPortSpec}
+
+	return portSpecObj, nil
 }
 
 func (spec *PortSpec) GetNumber() uint16 {
-	return spec.number
+	return spec.privatePortSpec.Number
 }
 
 func (spec *PortSpec) GetTransportProtocol() TransportProtocol {
-	return spec.transportProtocol
+	return spec.privatePortSpec.TransportProtocol
 }
 
 func (spec *PortSpec) GetMaybeApplicationProtocol() *string {
-	return spec.applicationProtocol
+	return spec.privatePortSpec.ApplicationProtocol
 }
 
 func (spec *PortSpec) GetWait() *Wait {
-	return spec.wait
+	return spec.privatePortSpec.Wait
+}
+
+func (spec *PortSpec) MarshalJSON() ([]byte, error) {
+	return json.Marshal(spec.privatePortSpec)
+}
+
+func (spec *PortSpec) UnmarshalJSON(data []byte) error {
+
+	// Suppressing exhaustruct requirement because we want an object with zero values
+	// nolint: exhaustruct
+	unmarshalledPrivateStructPtr := &privatePortSpec{}
+
+	if err := json.Unmarshal(data, unmarshalledPrivateStructPtr); err != nil {
+		return stacktrace.Propagate(err, "An error occurred unmarshalling the private struct")
+	}
+
+	spec.privatePortSpec = unmarshalledPrivateStructPtr
+	return nil
 }
diff --git a/container-engine-lib/lib/backend_interface/objects/port_spec/wait.go b/container-engine-lib/lib/backend_interface/objects/port_spec/wait.go
index 1cde3b8fe..1a7559587 100644
--- a/container-engine-lib/lib/backend_interface/objects/port_spec/wait.go
+++ b/container-engine-lib/lib/backend_interface/objects/port_spec/wait.go
@@ -1,6 +1,7 @@
 package port_spec
 
 import (
+	"encoding/json"
 	"github.com/kurtosis-tech/stacktrace"
 	"time"
 )
@@ -24,9 +25,7 @@ func CreateWaitWithDefaultValues() (*Wait, error) {
 		return nil, stacktrace.Propagate(err, "An error occurred creating a new wait with default values")
 	}
 
-	newWait := &Wait{
-		timeout: defaultTimeout,
-	}
+	newWait := NewWait(defaultTimeout)
 
 	return newWait, nil
 }
@@ -38,7 +37,9 @@ func CreateWait(timeoutStr string) (*Wait, error) {
 		return nil, stacktrace.Propagate(err, "An error occurred creating a wait object using time out string '%s'", timeoutStr)
 	}
 
-	return &Wait{timeout: timeoutDuration}, nil
+	newWait := NewWait(timeoutDuration)
+
+	return newWait, nil
 }
 
 func (wait *Wait) GetTimeout() time.Duration {
@@ -48,3 +49,22 @@ func (wait *Wait) GetTimeout() time.Duration {
 func (wait *Wait) String() string {
 	return wait.timeout.String()
 }
+
+func (wait *Wait) MarshalJSON() ([]byte, error) {
+
+	return json.Marshal(wait.timeout)
+}
+
+func (wait *Wait) UnmarshalJSON(data []byte) error {
+
+	var timeout time.Duration
+
+	timeOutPtr := &timeout
+
+	if err := json.Unmarshal(data, timeOutPtr); err != nil {
+		return stacktrace.Propagate(err, "An error occurred unmarshalling time duration")
+	}
+
+	wait.timeout = timeout
+	return nil
+}
diff --git a/container-engine-lib/lib/backend_interface/objects/service/service_config.go b/container-engine-lib/lib/backend_interface/objects/service/service_config.go
index d206b77a5..6d28d04aa 100644
--- a/container-engine-lib/lib/backend_interface/objects/service/service_config.go
+++ b/container-engine-lib/lib/backend_interface/objects/service/service_config.go
@@ -1,38 +1,46 @@
 package service
 
 import (
+	"encoding/json"
 	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/port_spec"
 	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service_directory"
+	"github.com/kurtosis-tech/stacktrace"
 )
 
 // Config options for the underlying container of a service
 type ServiceConfig struct {
-	containerImageName string
+	// we do this way in order to have exported fields which can be marshalled
+	// and an unexported type for encapsulation
+	privateServiceConfig *privateServiceConfig
+}
+
+type privateServiceConfig struct {
+	ContainerImageName string
 
-	privatePorts map[string]*port_spec.PortSpec
+	PrivatePorts map[string]*port_spec.PortSpec
 
-	publicPorts map[string]*port_spec.PortSpec //TODO this is a huge hack to temporarily enable static ports for NEAR until we have a more productized solution
+	PublicPorts map[string]*port_spec.PortSpec //TODO this is a huge hack to temporarily enable static ports for NEAR until we have a more productized solution
 
-	entrypointArgs []string
+	EntrypointArgs []string
 
-	cmdArgs []string
+	CmdArgs []string
 
-	envVars map[string]string
+	EnvVars map[string]string
 
 	// Leave as nil to not do any files artifact expansion
-	filesArtifactExpansion *service_directory.FilesArtifactsExpansion
+	FilesArtifactExpansion *service_directory.FilesArtifactsExpansion
 
-	persistentDirectories *service_directory.PersistentDirectories
+	PersistentDirectories *service_directory.PersistentDirectories
 
-	cpuAllocationMillicpus uint64
+	CpuAllocationMillicpus uint64
 
-	memoryAllocationMegabytes uint64
+	MemoryAllocationMegabytes uint64
 
-	privateIPAddrPlaceholder string
+	PrivateIPAddrPlaceholder string
 
-	minCpuAllocationMilliCpus uint64
+	MinCpuAllocationMilliCpus uint64
 
-	minMemoryAllocationMegabytes uint64
+	MinMemoryAllocationMegabytes uint64
 }
 
 func NewServiceConfig(
@@ -50,74 +58,93 @@ func NewServiceConfig(
 	minCpuMilliCores uint64,
 	minMemoryMegaBytes uint64,
 ) *ServiceConfig {
-	return &ServiceConfig{
-		containerImageName:        containerImageName,
-		privatePorts:              privatePorts,
-		publicPorts:               publicPorts,
-		entrypointArgs:            entrypointArgs,
-		cmdArgs:                   cmdArgs,
-		envVars:                   envVars,
-		filesArtifactExpansion:    filesArtifactExpansion,
-		persistentDirectories:     persistentDirectories,
-		cpuAllocationMillicpus:    cpuAllocationMillicpus,
-		memoryAllocationMegabytes: memoryAllocationMegabytes,
-		privateIPAddrPlaceholder:  privateIPAddrPlaceholder,
+	internalServiceConfig := &privateServiceConfig{
+		ContainerImageName:        containerImageName,
+		PrivatePorts:              privatePorts,
+		PublicPorts:               publicPorts,
+		EntrypointArgs:            entrypointArgs,
+		CmdArgs:                   cmdArgs,
+		EnvVars:                   envVars,
+		FilesArtifactExpansion:    filesArtifactExpansion,
+		PersistentDirectories:     persistentDirectories,
+		CpuAllocationMillicpus:    cpuAllocationMillicpus,
+		MemoryAllocationMegabytes: memoryAllocationMegabytes,
+		PrivateIPAddrPlaceholder:  privateIPAddrPlaceholder,
 		// The minimum resources specification is only available for kubernetes
-		minCpuAllocationMilliCpus:    minCpuMilliCores,
-		minMemoryAllocationMegabytes: minMemoryMegaBytes,
+		MinCpuAllocationMilliCpus:    minCpuMilliCores,
+		MinMemoryAllocationMegabytes: minMemoryMegaBytes,
 	}
+	return &ServiceConfig{internalServiceConfig}
 }
 
 func (serviceConfig *ServiceConfig) GetContainerImageName() string {
-	return serviceConfig.containerImageName
+	return serviceConfig.privateServiceConfig.ContainerImageName
 }
 
 func (serviceConfig *ServiceConfig) GetPrivatePorts() map[string]*port_spec.PortSpec {
-	return serviceConfig.privatePorts
+	return serviceConfig.privateServiceConfig.PrivatePorts
 }
 
 func (serviceConfig *ServiceConfig) GetPublicPorts() map[string]*port_spec.PortSpec {
-	return serviceConfig.publicPorts
+	return serviceConfig.privateServiceConfig.PublicPorts
 }
 
 func (serviceConfig *ServiceConfig) GetEntrypointArgs() []string {
-	return serviceConfig.entrypointArgs
+	return serviceConfig.privateServiceConfig.EntrypointArgs
 }
 
 func (serviceConfig *ServiceConfig) GetCmdArgs() []string {
-	return serviceConfig.cmdArgs
+	return serviceConfig.privateServiceConfig.CmdArgs
 }
 
 func (serviceConfig *ServiceConfig) GetEnvVars() map[string]string {
-	return serviceConfig.envVars
+	return serviceConfig.privateServiceConfig.EnvVars
 }
 
 func (serviceConfig *ServiceConfig) GetFilesArtifactsExpansion() *service_directory.FilesArtifactsExpansion {
-	return serviceConfig.filesArtifactExpansion
+	return serviceConfig.privateServiceConfig.FilesArtifactExpansion
 }
 
 func (serviceConfig *ServiceConfig) GetPersistentDirectories() *service_directory.PersistentDirectories {
-	return serviceConfig.persistentDirectories
+	return serviceConfig.privateServiceConfig.PersistentDirectories
 }
 
 func (serviceConfig *ServiceConfig) GetCPUAllocationMillicpus() uint64 {
-	return serviceConfig.cpuAllocationMillicpus
+	return serviceConfig.privateServiceConfig.CpuAllocationMillicpus
 }
 
 func (serviceConfig *ServiceConfig) GetMemoryAllocationMegabytes() uint64 {
-	return serviceConfig.memoryAllocationMegabytes
+	return serviceConfig.privateServiceConfig.MemoryAllocationMegabytes
 }
 
 func (serviceConfig *ServiceConfig) GetPrivateIPAddrPlaceholder() string {
-	return serviceConfig.privateIPAddrPlaceholder
+	return serviceConfig.privateServiceConfig.PrivateIPAddrPlaceholder
 }
 
 // only available for Kubernetes
 func (serviceConfig *ServiceConfig) GetMinCPUAllocationMillicpus() uint64 {
-	return serviceConfig.minCpuAllocationMilliCpus
+	return serviceConfig.privateServiceConfig.MinCpuAllocationMilliCpus
 }
 
 // only available for Kubernetes
 func (serviceConfig *ServiceConfig) GetMinMemoryAllocationMegabytes() uint64 {
-	return serviceConfig.minMemoryAllocationMegabytes
+	return serviceConfig.privateServiceConfig.MinMemoryAllocationMegabytes
+}
+
+func (serviceConfig *ServiceConfig) MarshalJSON() ([]byte, error) {
+	return json.Marshal(serviceConfig.privateServiceConfig)
+}
+
+func (serviceConfig *ServiceConfig) UnmarshalJSON(data []byte) error {
+
+	// Suppressing exhaustruct requirement because we want an object with zero values
+	// nolint: exhaustruct
+	unmarshalledPrivateStructPtr := &privateServiceConfig{}
+
+	if err := json.Unmarshal(data, unmarshalledPrivateStructPtr); err != nil {
+		return stacktrace.Propagate(err, "An error occurred unmarshalling the private struct")
+	}
+
+	serviceConfig.privateServiceConfig = unmarshalledPrivateStructPtr
+	return nil
 }
diff --git a/container-engine-lib/lib/backend_interface/objects/service/service_registration.go b/container-engine-lib/lib/backend_interface/objects/service/service_registration.go
index 303c9af8b..14589d89b 100644
--- a/container-engine-lib/lib/backend_interface/objects/service/service_registration.go
+++ b/container-engine-lib/lib/backend_interface/objects/service/service_registration.go
@@ -1,6 +1,8 @@
 package service
 
 import (
+	"encoding/json"
+	"github.com/kurtosis-tech/stacktrace"
 	"net"
 
 	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/enclave"
@@ -10,74 +12,100 @@ import (
 // We had created this to return the user's IP before the container exists
 // The user doesn't need the private IP address anymore.
 // Now this is used for caches in APIC & DockerKurtosisBackend
-// TODO visit removing this  after data is stored in a database
 type ServiceRegistration struct {
-	name      ServiceName
-	uuid      ServiceUUID
-	enclaveId enclave.EnclaveUUID
+	// we do this way in order to have exported fields which can be marshalled
+	// and an unexported type for encapsulation
+	privateServiceRegistration *privateServiceRegistration
+}
+
+type privateServiceRegistration struct {
+	Name        ServiceName
+	Uuid        ServiceUUID
+	EnclaveUuid enclave.EnclaveUUID
 
 	// The private IP is the IP of the service within the enclave, meaning other services can use this IP to communicate
 	// with the service
-	privateIp net.IP
+	PrivateIp net.IP
 
 	// The hostname differs whether Kurtosis is using a Kubernetes backend of a Docker backend.
 	// In Docker, we set the serviceName as the hostname, whereas in Kubernetes the hostname is automatically assigned
 	// to the "Kubernetes Service Name", which is something like user-services-<SERVICE_UUID>
 	// TODO: for consistency we should probably set the hostname to user-services-<SERVICE_UUID> in docker as well
-	hostname string
+	Hostname string
 
 	// Service state: registered, started or stopped
-	status ServiceStatus
+	Status ServiceStatus
 
 	// Service config used during service creation
 	// Used when the service is restarted
-	config *ServiceConfig
+	Config *ServiceConfig
 }
 
-func NewServiceRegistration(name ServiceName, guid ServiceUUID, enclaveId enclave.EnclaveUUID, privateIp net.IP, hostname string) *ServiceRegistration {
+func NewServiceRegistration(name ServiceName, uuid ServiceUUID, enclaveUuid enclave.EnclaveUUID, privateIp net.IP, hostname string) *ServiceRegistration {
+	privateServiceRegistrationObj := &privateServiceRegistration{
+		Name:        name,
+		Uuid:        uuid,
+		EnclaveUuid: enclaveUuid,
+		PrivateIp:   privateIp,
+		Hostname:    hostname,
+		Status:      ServiceStatus_Registered,
+		Config:      nil,
+	}
 	return &ServiceRegistration{
-		name:      name,
-		uuid:      guid,
-		enclaveId: enclaveId,
-		privateIp: privateIp,
-		hostname:  hostname,
-		status:    ServiceStatus_Registered,
-		config:    nil,
+		privateServiceRegistration: privateServiceRegistrationObj,
 	}
 }
 
 func (registration *ServiceRegistration) GetName() ServiceName {
-	return registration.name
+	return registration.privateServiceRegistration.Name
 }
 
 func (registration *ServiceRegistration) GetUUID() ServiceUUID {
-	return registration.uuid
+	return registration.privateServiceRegistration.Uuid
 }
 
 func (registration *ServiceRegistration) GetEnclaveID() enclave.EnclaveUUID {
-	return registration.enclaveId
+	return registration.privateServiceRegistration.EnclaveUuid
 }
 
 func (registration *ServiceRegistration) GetPrivateIP() net.IP {
-	return registration.privateIp
+	return registration.privateServiceRegistration.PrivateIp
 }
 
 func (registration *ServiceRegistration) GetHostname() string {
-	return registration.hostname
+	return registration.privateServiceRegistration.Hostname
 }
 
 func (registration *ServiceRegistration) GetStatus() ServiceStatus {
-	return registration.status
+	return registration.privateServiceRegistration.Status
 }
 
 func (registration *ServiceRegistration) SetStatus(status ServiceStatus) {
-	registration.status = status
+	registration.privateServiceRegistration.Status = status
 }
 
 func (registration *ServiceRegistration) GetConfig() *ServiceConfig {
-	return registration.config
+	return registration.privateServiceRegistration.Config
 }
 
 func (registration *ServiceRegistration) SetConfig(config *ServiceConfig) {
-	registration.config = config
+	registration.privateServiceRegistration.Config = config
+}
+
+func (registration *ServiceRegistration) MarshalJSON() ([]byte, error) {
+	return json.Marshal(registration.privateServiceRegistration)
+}
+
+func (registration *ServiceRegistration) UnmarshalJSON(data []byte) error {
+
+	// Suppressing exhaustruct requirement because we want an object with zero values
+	// nolint: exhaustruct
+	unmarshalledPrivateStructPtr := &privateServiceRegistration{}
+
+	if err := json.Unmarshal(data, unmarshalledPrivateStructPtr); err != nil {
+		return stacktrace.Propagate(err, "An error occurred unmarshalling the private struct")
+	}
+
+	registration.privateServiceRegistration = unmarshalledPrivateStructPtr
+	return nil
 }
diff --git a/container-engine-lib/lib/database_accessors/enclave_db/service_registration/repository.go b/container-engine-lib/lib/database_accessors/enclave_db/service_registration/repository.go
new file mode 100644
index 000000000..b285b3282
--- /dev/null
+++ b/container-engine-lib/lib/database_accessors/enclave_db/service_registration/repository.go
@@ -0,0 +1,342 @@
+package service_registration
+
+import (
+	"encoding/json"
+	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/enclave"
+	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service"
+	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/enclave_db"
+	"github.com/kurtosis-tech/stacktrace"
+	"github.com/sirupsen/logrus"
+	bolt "go.etcd.io/bbolt"
+)
+
+var (
+	serviceRegistrationBucketName = []byte("service-registration-repository")
+)
+
+type ServiceRegistrationRepository struct {
+	enclaveDb *enclave_db.EnclaveDB
+}
+
+func GetOrCreateNewServiceRegistrationRepository(enclaveDb *enclave_db.EnclaveDB) (*ServiceRegistrationRepository, error) {
+	if err := enclaveDb.Update(func(tx *bolt.Tx) error {
+		bucket, err := tx.CreateBucketIfNotExists(serviceRegistrationBucketName)
+		if err != nil {
+			return stacktrace.Propagate(err, "An error occurred while creating the service registration database bucket")
+		}
+		logrus.Debugf("Service registration bucket: '%+v'", bucket)
+
+		return nil
+	}); err != nil {
+		return nil, stacktrace.Propagate(err, "An error occurred while building the service registration repository")
+	}
+
+	serviceRegistrationRepository := &ServiceRegistrationRepository{
+		enclaveDb: enclaveDb,
+	}
+
+	return serviceRegistrationRepository, nil
+}
+
+func (repository *ServiceRegistrationRepository) GetAll() (map[service.ServiceName]*service.ServiceRegistration, error) {
+	allServiceRegistrationsByServiceName := map[service.ServiceName]*service.ServiceRegistration{}
+
+	if err := repository.enclaveDb.View(func(tx *bolt.Tx) error {
+		bucket := tx.Bucket(serviceRegistrationBucketName)
+
+		if err := bucket.ForEach(func(serviceNameKey, serviceRegistrationBytes []byte) error {
+			serviceNameStr := string(serviceNameKey)
+			serviceName := service.ServiceName(serviceNameStr)
+
+			serviceRegistration, err := getServiceRegistrationFromBytes(serviceRegistrationBytes, serviceName)
+			if err != nil {
+				return stacktrace.Propagate(err, "An error occurred getting service registrations for service '%s' from service registrations bytes", serviceName)
+			}
+			allServiceRegistrationsByServiceName[serviceName] = serviceRegistration
+
+			return nil
+		}); err != nil {
+			return stacktrace.Propagate(err, "An error occurred while iterating the service registration repository to get all registrations")
+		}
+
+		return nil
+	}); err != nil {
+		return nil, stacktrace.Propagate(err, "An error occurred while getting all service registrations from the service registration repository")
+	}
+
+	return allServiceRegistrationsByServiceName, nil
+}
+
+// Get returns a service registration struct previously saved, never returns a nil struct if it doesn't fail
+// Exist() method can used for checking existence instead
+func (repository *ServiceRegistrationRepository) Get(serviceName service.ServiceName) (*service.ServiceRegistration, error) {
+	var (
+		serviceRegistration *service.ServiceRegistration
+		err                 error
+	)
+
+	if err := repository.enclaveDb.View(func(tx *bolt.Tx) error {
+		bucket := tx.Bucket(serviceRegistrationBucketName)
+
+		serviceRegistration, err = getServiceRegistrationFromBucket(bucket, serviceName)
+		if err != nil {
+			return stacktrace.Propagate(err, "An error occurred getting service registration for service '%s' from bucket with name '%s'", serviceName, serviceRegistrationBucketName)
+		}
+
+		return nil
+	}); err != nil {
+		return nil, stacktrace.Propagate(err, "An error occurred while getting service registration from the service registration repository")
+	}
+	return serviceRegistration, nil
+}
+
+func (repository *ServiceRegistrationRepository) Exist(serviceName service.ServiceName) (bool, error) {
+
+	exist := false
+
+	if err := repository.enclaveDb.View(func(tx *bolt.Tx) error {
+		bucket := tx.Bucket(serviceRegistrationBucketName)
+
+		serviceNameKey := getServiceNameKey(serviceName)
+		bytes := bucket.Get(serviceNameKey)
+		if bytes != nil {
+			exist = true
+		}
+		return nil
+	}); err != nil {
+		return false, stacktrace.Propagate(err, "An error occurred while checking if service registration for service '%s' exist in service registration repository", serviceName)
+	}
+
+	return exist, nil
+}
+
+func (repository *ServiceRegistrationRepository) GetAllServiceNames() (map[service.ServiceName]bool, error) {
+	serviceNames := map[service.ServiceName]bool{}
+
+	if err := repository.enclaveDb.View(func(tx *bolt.Tx) error {
+		bucket := tx.Bucket(serviceRegistrationBucketName)
+
+		if err := bucket.ForEach(func(serviceNameKey, _ []byte) error {
+			serviceNameStr := string(serviceNameKey)
+			serviceName := service.ServiceName(serviceNameStr)
+			serviceNames[serviceName] = true
+			return nil
+		}); err != nil {
+			return stacktrace.Propagate(err, "An error occurred while iterating the service registration repository to get the service names list")
+		}
+
+		return nil
+	}); err != nil {
+		return nil, stacktrace.Propagate(err, "An error occurred while getting all service names from the service registration repository")
+	}
+	return serviceNames, nil
+}
+
+func (repository *ServiceRegistrationRepository) GetAllEnclaveServiceRegistrations(
+	enclaveUuid enclave.EnclaveUUID,
+) (map[service.ServiceUUID]*service.ServiceRegistration, error) {
+	allEnclaveServiceRegistrations := map[service.ServiceUUID]*service.ServiceRegistration{}
+
+	if err := repository.enclaveDb.View(func(tx *bolt.Tx) error {
+		bucket := tx.Bucket(serviceRegistrationBucketName)
+
+		if err := bucket.ForEach(func(serviceNameKey, serviceRegistrationBytes []byte) error {
+			serviceNameStr := string(serviceNameKey)
+			serviceName := service.ServiceName(serviceNameStr)
+			serviceRegistration, err := getServiceRegistrationFromBytes(serviceRegistrationBytes, serviceName)
+			if err != nil {
+				return stacktrace.Propagate(err, "An error occurred getting service registration from bytes for service '%s'", serviceName)
+			}
+
+			if serviceRegistration.GetEnclaveID() == enclaveUuid {
+				serviceUuid := serviceRegistration.GetUUID()
+				allEnclaveServiceRegistrations[serviceUuid] = serviceRegistration
+			}
+			return nil
+		}); err != nil {
+			return stacktrace.Propagate(err, "An error occurred while iterating the service registration repository to get the service names list")
+		}
+
+		return nil
+	}); err != nil {
+		return nil, stacktrace.Propagate(err, "An error occurred while getting all service names from the service registration repository")
+	}
+
+	return allEnclaveServiceRegistrations, nil
+}
+
+func (repository *ServiceRegistrationRepository) Save(
+	serviceRegistration *service.ServiceRegistration,
+) error {
+
+	if err := repository.enclaveDb.Update(func(tx *bolt.Tx) error {
+		bucket := tx.Bucket(serviceRegistrationBucketName)
+
+		serviceName := serviceRegistration.GetName()
+		if err := saveServiceRegistrationIntoTheBucket(bucket, serviceName, serviceRegistration); err != nil {
+			return stacktrace.Propagate(err, "An error occurred saving service registration '%+v' for service '%s' in the service registration bucket", serviceRegistration, serviceName)
+		}
+		return nil
+	}); err != nil {
+		return stacktrace.Propagate(err, "An error occurred while saving service registration '%v' into the service registration repository", serviceRegistration)
+	}
+	return nil
+}
+
+func (repository *ServiceRegistrationRepository) UpdateStatus(
+	serviceName service.ServiceName,
+	newServiceStatus service.ServiceStatus,
+) error {
+
+	if err := repository.enclaveDb.Update(func(tx *bolt.Tx) error {
+		bucket := tx.Bucket(serviceRegistrationBucketName)
+
+		// get the object form db
+		serviceRegistration, err := getServiceRegistrationFromBucket(bucket, serviceName)
+		if err != nil {
+			return stacktrace.Propagate(err, "An error occurred getting service registration for service '%s' from bucket with name '%s'", serviceName, serviceRegistrationBucketName)
+		}
+
+		// update the object
+		serviceRegistration.SetStatus(newServiceStatus)
+
+		// save the updated object
+		if err := saveServiceRegistrationIntoTheBucket(bucket, serviceName, serviceRegistration); err != nil {
+			return stacktrace.Propagate(err, "An error occurred saving service registration '%+v' for service '%s' in the service registration bucket", serviceRegistration, serviceName)
+		}
+
+		return nil
+	}); err != nil {
+		return stacktrace.Propagate(err, "An error occurred while updating the service status '%s' into the service registration repository for service '%s'", newServiceStatus, serviceName)
+	}
+	return nil
+}
+
+func (repository *ServiceRegistrationRepository) UpdateConfig(
+	serviceName service.ServiceName,
+	newServiceConfig *service.ServiceConfig,
+) error {
+
+	if err := repository.enclaveDb.Update(func(tx *bolt.Tx) error {
+		bucket := tx.Bucket(serviceRegistrationBucketName)
+
+		// get the object form db
+		serviceRegistration, err := getServiceRegistrationFromBucket(bucket, serviceName)
+		if err != nil {
+			return stacktrace.Propagate(err, "An error occurred getting service registration for service '%s' from bucket with name '%s'", serviceName, serviceRegistrationBucketName)
+		}
+
+		// update the object
+		serviceRegistration.SetConfig(newServiceConfig)
+
+		// save the updated object
+		if err := saveServiceRegistrationIntoTheBucket(bucket, serviceName, serviceRegistration); err != nil {
+			return stacktrace.Propagate(err, "An error occurred saving service registration '%+v' for service '%s' in the service registration bucket", serviceRegistration, serviceName)
+		}
+
+		return nil
+	}); err != nil {
+		return stacktrace.Propagate(err, "An error occurred while updating the service config '%+v' into the service registration repository for service '%s'", newServiceConfig, serviceName)
+	}
+	return nil
+}
+
+func (repository *ServiceRegistrationRepository) UpdateStatusAndConfig(
+	serviceName service.ServiceName,
+	newServiceStatus service.ServiceStatus,
+	newServiceConfig *service.ServiceConfig,
+) error {
+
+	if err := repository.enclaveDb.Update(func(tx *bolt.Tx) error {
+		bucket := tx.Bucket(serviceRegistrationBucketName)
+
+		// get the object form db
+		serviceRegistration, err := getServiceRegistrationFromBucket(bucket, serviceName)
+		if err != nil {
+			return stacktrace.Propagate(err, "An error occurred getting service registration for service '%s' from bucket with name '%s'", serviceName, serviceRegistrationBucketName)
+		}
+
+		// update the object
+		serviceRegistration.SetStatus(newServiceStatus)
+		serviceRegistration.SetConfig(newServiceConfig)
+
+		// save the updated object
+		if err := saveServiceRegistrationIntoTheBucket(bucket, serviceName, serviceRegistration); err != nil {
+			return stacktrace.Propagate(err, "An error occurred saving service registration '%+v' for service '%s' in the service registration bucket", serviceRegistration, serviceName)
+		}
+
+		return nil
+	}); err != nil {
+		return stacktrace.Propagate(err, "An error occurred while updating the service status '%s' and service config '%+v' into the service registration repository for service '%s'", newServiceStatus, newServiceConfig, serviceName)
+	}
+	return nil
+}
+
+func (repository *ServiceRegistrationRepository) Delete(serviceName service.ServiceName) error {
+	if err := repository.enclaveDb.Update(func(tx *bolt.Tx) error {
+		bucket := tx.Bucket(serviceRegistrationBucketName)
+
+		serviceNameKey := getServiceNameKey(serviceName)
+		if err := bucket.Delete(serviceNameKey); err != nil {
+			return stacktrace.Propagate(err, "An error occurred deleting a service registration using with key '%v' from the service registration bucket", serviceNameKey)
+		}
+
+		return nil
+	}); err != nil {
+		return stacktrace.Propagate(err, "An error occurred while deleting the service registration for service '%s' from the service registration repository", serviceName)
+	}
+	return nil
+}
+
+func getServiceRegistrationFromBucket(bucket *bolt.Bucket, serviceName service.ServiceName) (*service.ServiceRegistration, error) {
+
+	serviceNameKey := getServiceNameKey(serviceName)
+
+	// first get the bytes
+	serviceRegistrationBytes := bucket.Get(serviceNameKey)
+
+	serviceRegistration, err := getServiceRegistrationFromBytes(serviceRegistrationBytes, serviceName)
+	if err != nil {
+		return nil, stacktrace.Propagate(err, "An error occurred getting service registrations for service '%s' from service registrations bytes", serviceName)
+	}
+
+	return serviceRegistration, nil
+}
+
+func getServiceRegistrationFromBytes(serviceRegistrationBytes []byte, serviceName service.ServiceName) (*service.ServiceRegistration, error) {
+	// check for existence
+	if serviceRegistrationBytes == nil {
+		return nil, stacktrace.NewError("Service registration for service '%s' does not exist on the service registration repository", serviceName)
+	}
+
+	serviceRegistration := &service.ServiceRegistration{}
+
+	if err := json.Unmarshal(serviceRegistrationBytes, serviceRegistration); err != nil {
+		return nil, stacktrace.Propagate(err, "An error occurred unmarshalling service registration")
+	}
+
+	return serviceRegistration, nil
+}
+
+func saveServiceRegistrationIntoTheBucket(
+	bucket *bolt.Bucket,
+	serviceName service.ServiceName,
+	serviceRegistration *service.ServiceRegistration,
+) error {
+	jsonBytes, err := json.Marshal(serviceRegistration)
+	if err != nil {
+		return stacktrace.Propagate(err, "An error occurred marshalling service registration '%+v'", serviceRegistration)
+	}
+
+	serviceNameKey := getServiceNameKey(serviceName)
+	// save it to disk
+	if err := bucket.Put(serviceNameKey, jsonBytes); err != nil {
+		return stacktrace.Propagate(err, "An error occurred while saving service registration '%+v' into the enclave db bucket", serviceRegistration)
+	}
+
+	return nil
+}
+
+func getServiceNameKey(serviceName service.ServiceName) []byte {
+	return []byte(serviceName)
+}
diff --git a/core/server/api_container/server/api_container_service.go b/core/server/api_container/server/api_container_service.go
index 47657cb3e..230533d37 100644
--- a/core/server/api_container/server/api_container_service.go
+++ b/core/server/api_container/server/api_container_service.go
@@ -298,7 +298,12 @@ func (apicService ApiContainerService) GetServices(ctx context.Context, args *ku
 	}
 
 	// otherwise we fetch everything
-	for serviceName := range apicService.serviceNetwork.GetServiceNames() {
+	allServiceNames, err := apicService.serviceNetwork.GetServiceNames()
+	if err != nil {
+		return nil, stacktrace.Propagate(err, "An error occurred getting all service names")
+	}
+
+	for serviceName := range allServiceNames {
 		serviceNameStr := string(serviceName)
 		serviceInfo, err := apicService.getServiceInfo(ctx, serviceNameStr)
 		if err != nil {
diff --git a/core/server/api_container/server/service_network/default_service_network.go b/core/server/api_container/server/service_network/default_service_network.go
index 2e4e635d2..4619ef469 100644
--- a/core/server/api_container/server/service_network/default_service_network.go
+++ b/core/server/api_container/server/service_network/default_service_network.go
@@ -12,6 +12,7 @@ import (
 	"fmt"
 	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/exec_result"
 	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/enclave_db"
+	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/enclave_db/service_registration"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/service_network/render_templates"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/service_network/service_identifiers"
 	"io"
@@ -77,9 +78,7 @@ type DefaultServiceNetwork struct {
 
 	enclaveDataDir *enclave_data_directory.EnclaveDataDirectory
 
-	// Technically we SHOULD query the backend rather than ever storing any of this information, but we're able to get away with
-	// this because the API container is the only client that modifies service state
-	registeredServiceInfo map[service.ServiceName]*service.ServiceRegistration
+	serviceRegistrationRepository *service_registration.ServiceRegistrationRepository
 
 	// This contains all service identifiers ever successfully created
 	serviceIdentifiersRepository *service_identifiers.ServiceIdentifiersRepository
@@ -96,6 +95,11 @@ func NewDefaultServiceNetwork(
 	if err != nil {
 		return nil, stacktrace.Propagate(err, "An error occurred while creating the service identifiers repository")
 	}
+	serviceRegistrationRepository, err := service_registration.GetOrCreateNewServiceRegistrationRepository(enclaveDb)
+	if err != nil {
+		return nil, stacktrace.Propagate(err, "An error occurred while creating the service registration repository")
+	}
+
 	return &DefaultServiceNetwork{
 		enclaveUuid:      enclaveUuid,
 		apiContainerInfo: apiContainerInfo,
@@ -104,8 +108,8 @@ func NewDefaultServiceNetwork(
 		kurtosisBackend: kurtosisBackend,
 		enclaveDataDir:  enclaveDataDir,
 
-		registeredServiceInfo:        map[service.ServiceName]*service.ServiceRegistration{},
-		serviceIdentifiersRepository: serviceIdentifiersRepository,
+		serviceRegistrationRepository: serviceRegistrationRepository,
+		serviceIdentifiersRepository:  serviceIdentifiersRepository,
 	}, nil
 }
 
@@ -166,7 +170,11 @@ func (network *DefaultServiceNetwork) AddServices(
 
 	// Save the services currently running in enclave for later
 	currentlyRunningServicesInEnclave := map[service.ServiceName]bool{}
-	for serviceName := range network.registeredServiceInfo {
+	allServiceNamesFromServiceRegistrations, err := network.serviceRegistrationRepository.GetAllServiceNames()
+	if err != nil {
+		return nil, nil, stacktrace.Propagate(err, "An error occurred getting all service names from service registration repository")
+	}
+	for serviceName := range allServiceNamesFromServiceRegistrations {
 		currentlyRunningServicesInEnclave[serviceName] = true
 	}
 
@@ -248,7 +256,11 @@ func (network *DefaultServiceNetwork) AddServices(
 		if err := network.serviceIdentifiersRepository.AddServiceIdentifier(serviceIdentifier); err != nil {
 			return nil, nil, stacktrace.Propagate(err, "An error occurred adding a new service identifier '%+v' into the repository", serviceIdentifier)
 		}
-		network.registeredServiceInfo[serviceRegistration.GetName()].SetStatus(service.ServiceStatus_Started)
+		serviceName := serviceRegistration.GetName()
+		serviceStatus := service.ServiceStatus_Started
+		if err := network.serviceRegistrationRepository.UpdateStatus(serviceName, serviceStatus); err != nil {
+			return nil, nil, stacktrace.Propagate(err, "An error occurred while updating service status to '%s' in service registration for service '%s' after the service was started", serviceStatus, serviceName)
+		}
 	}
 
 	batchSuccessfullyStarted = true
@@ -291,9 +303,9 @@ func (network *DefaultServiceNetwork) UpdateServices(ctx context.Context, update
 	serviceUuidToNameMap := map[service.ServiceUUID]service.ServiceName{}
 	serviceUuidsToRemove := map[service.ServiceUUID]bool{}
 	for serviceName := range updateServiceConfigs {
-		serviceRegistration, found := network.registeredServiceInfo[serviceName]
-		if !found {
-			failedServicesPool[serviceName] = stacktrace.NewError("Unable to update service that is not registered "+
+		serviceRegistration, err := network.serviceRegistrationRepository.Get(serviceName)
+		if err != nil {
+			failedServicesPool[serviceName] = stacktrace.Propagate(err, "Unable to update service that is not registered "+
 				"inside this enclave: '%s'", serviceName)
 		} else {
 			serviceUuid := serviceRegistration.GetUUID()
@@ -317,9 +329,12 @@ func (network *DefaultServiceNetwork) UpdateServices(ctx context.Context, update
 	successfullyRemovedServicesIncludingSidecars := map[service.ServiceUUID]bool{}
 	for serviceUuid := range successfullyRemovedServices {
 		if serviceName, found := serviceUuidToNameMap[serviceUuid]; found {
+			serviceStatus := service.ServiceStatus_Registered
+			if err := network.serviceRegistrationRepository.UpdateStatusAndConfig(serviceName, serviceStatus, nil); err != nil {
+				failedServicesPool[serviceName] = stacktrace.Propagate(err, "An error occurred while cleaning the configuration and updating service status to '%s' into service registration fro service '%s' after this service was removed successfully", serviceStatus, serviceName)
+				continue
+			}
 			successfullyRemovedServicesIncludingSidecars[serviceUuid] = true
-			network.registeredServiceInfo[serviceName].SetStatus(service.ServiceStatus_Registered)
-			network.registeredServiceInfo[serviceName].SetConfig(nil)
 		} else {
 			return nil, nil, stacktrace.NewError("Error mapping service UUID to service name. This is a bug in Kurtosis")
 		}
@@ -359,8 +374,12 @@ func (network *DefaultServiceNetwork) UpdateServices(ctx context.Context, update
 				"inside this enclave: '%s'", serviceName)
 			continue
 		}
+		serviceStatus := service.ServiceStatus_Started
+		if err := network.serviceRegistrationRepository.UpdateStatus(serviceName, serviceStatus); err != nil {
+			failedServicesPool[serviceName] = stacktrace.Propagate(err, "An error occurred while updating service status to '%s' in service registration for service '%s' after the service was updated", serviceStatus, serviceName)
+			continue
+		}
 		successfullyUpdatedService[serviceName] = newServiceObj
-		network.registeredServiceInfo[serviceName].SetStatus(service.ServiceStatus_Started)
 	}
 	return successfullyUpdatedService, failedServicesPool, nil
 }
@@ -377,14 +396,12 @@ func (network *DefaultServiceNetwork) RemoveService(
 		return "", stacktrace.Propagate(err, "An error occurred while fetching name for service identifier '%v'", serviceIdentifier)
 	}
 
-	serviceToRemove, found := network.registeredServiceInfo[serviceName]
-	if !found {
-		return "", stacktrace.NewError("No service found with ID '%v'", serviceName)
+	serviceToRemove, err := network.serviceRegistrationRepository.Get(serviceName)
+	if err != nil {
+		return "", stacktrace.Propagate(err, "An error occurred getting the service registration for service '%s'", serviceName)
 	}
 	serviceUuid := serviceToRemove.GetUUID()
 
-	network.cleanupInternalMapsUnlocked(serviceName)
-
 	// We stop the service, rather than destroying it, so that we can keep logs around
 	stopServiceFilters := &service.ServiceFilters{
 		Names: nil,
@@ -401,6 +418,10 @@ func (network *DefaultServiceNetwork) RemoveService(
 		return "", stacktrace.Propagate(err, "An error occurred stopping service '%v'", serviceUuid)
 	}
 
+	if err := network.serviceRegistrationRepository.Delete(serviceName); err != nil {
+		return "", stacktrace.Propagate(err, "An error occurred deleting the service registration for service '%v' from the repository", serviceName)
+	}
+
 	return serviceUuid, nil
 }
 
@@ -458,7 +479,12 @@ func (network *DefaultServiceNetwork) StartServices(
 	}
 
 	for successfulUuid, successfulService := range successfulServices {
-		serviceRegistrations[successfulService.GetRegistration().GetUUID()].SetStatus(service.ServiceStatus_Started)
+		serviceName := successfulService.GetRegistration().GetName()
+		serviceStatus := service.ServiceStatus_Started
+		if err := network.serviceRegistrationRepository.UpdateStatus(serviceName, serviceStatus); err != nil {
+			failedServices[successfulUuid] = stacktrace.Propagate(err, "An error occurred while updating status to '%v' for service '%v' after it was successfully started", serviceStatus, serviceName)
+			continue
+		}
 		successfulUuids[successfulUuid] = true
 	}
 
@@ -498,7 +524,7 @@ func (network *DefaultServiceNetwork) StopServices(
 	defer network.mutex.Unlock()
 
 	serviceUuids := map[service.ServiceUUID]bool{}
-	serviceRegistrations := map[service.ServiceUUID]*service.ServiceRegistration{}
+	serviceNamesByUuid := map[service.ServiceUUID]service.ServiceName{}
 
 	for _, serviceIdentifier := range serviceIdentifiers {
 		serviceRegistration, err := network.getServiceRegistrationForIdentifierUnlocked(serviceIdentifier)
@@ -509,7 +535,7 @@ func (network *DefaultServiceNetwork) StopServices(
 			return nil, nil, stacktrace.NewError("Service '%v' is already stopped", serviceRegistration.GetName())
 		}
 		serviceUuids[serviceRegistration.GetUUID()] = true
-		serviceRegistrations[serviceRegistration.GetUUID()] = serviceRegistration
+		serviceNamesByUuid[serviceRegistration.GetUUID()] = serviceRegistration.GetName()
 	}
 
 	stopServiceFilters := &service.ServiceFilters{
@@ -523,7 +549,18 @@ func (network *DefaultServiceNetwork) StopServices(
 	}
 
 	for successfulUuid := range successfulUuids {
-		serviceRegistrations[successfulUuid].SetStatus(service.ServiceStatus_Stopped)
+		serviceName, found := serviceNamesByUuid[successfulUuid]
+		if !found {
+			erroredUuids[successfulUuid] = stacktrace.NewError("Expected to find service UUID '%v' in map '%+v' after the service was successfully stopped, but it was not found; this is a bug in Kurtosis", successfulUuid, serviceNamesByUuid)
+			delete(successfulUuids, successfulUuid)
+			continue
+		}
+		serviceStatus := service.ServiceStatus_Stopped
+		if err := network.serviceRegistrationRepository.UpdateStatus(serviceName, serviceStatus); err != nil {
+			erroredUuids[successfulUuid] = stacktrace.Propagate(err, "An error occurred while updating status to '%v' for service '%v' after it was successfully stopped", serviceStatus, serviceName)
+			delete(successfulUuids, successfulUuid)
+			continue
+		}
 	}
 
 	return successfulUuids, erroredUuids, nil
@@ -664,16 +701,14 @@ func (network *DefaultServiceNetwork) GetService(ctx context.Context, serviceIde
 	return serviceObj, nil
 }
 
-func (network *DefaultServiceNetwork) GetServiceNames() map[service.ServiceName]bool {
-
-	serviceNames := make(map[service.ServiceName]bool, len(network.registeredServiceInfo))
+func (network *DefaultServiceNetwork) GetServiceNames() (map[service.ServiceName]bool, error) {
 
-	for serviceName := range network.registeredServiceInfo {
-		if _, ok := serviceNames[serviceName]; !ok {
-			serviceNames[serviceName] = true
-		}
+	serviceNames, err := network.serviceRegistrationRepository.GetAllServiceNames()
+	if err != nil {
+		return nil, stacktrace.Propagate(err, "An error occurred getting all service names from service registration repository")
 	}
-	return serviceNames
+
+	return serviceNames, nil
 }
 
 func (network *DefaultServiceNetwork) CopyFilesFromService(ctx context.Context, serviceIdentifier string, srcPath string, artifactName string) (enclave_data_directory.FilesArtifactUUID, error) {
@@ -689,14 +724,16 @@ func (network *DefaultServiceNetwork) CopyFilesFromService(ctx context.Context,
 	return filesArtifactUuid, nil
 }
 
-func (network *DefaultServiceNetwork) GetServiceRegistration(serviceName service.ServiceName) (*service.ServiceRegistration, bool) {
+func (network *DefaultServiceNetwork) ExistServiceRegistration(serviceName service.ServiceName) (bool, error) {
 	network.mutex.Lock()
 	defer network.mutex.Unlock()
-	registration, found := network.registeredServiceInfo[serviceName]
-	if !found {
-		return nil, false
+
+	exist, err := network.serviceRegistrationRepository.Exist(serviceName)
+	if err != nil {
+		return false, stacktrace.Propagate(err, "An error occurred getting service registration for service '%s'", serviceName)
 	}
-	return registration, true
+
+	return exist, nil
 }
 
 func (network *DefaultServiceNetwork) RenderTemplates(templatesAndDataByDestinationRelFilepath map[string]*render_templates.TemplateData, artifactName string) (enclave_data_directory.FilesArtifactUUID, error) {
@@ -822,13 +859,17 @@ func (network *DefaultServiceNetwork) registerService(
 		}
 	}()
 
-	network.registeredServiceInfo[serviceName] = serviceRegistration
-	// remove service from the registered service map is something fails downstream
+	if err := network.serviceRegistrationRepository.Save(serviceRegistration); err != nil {
+		return nil, stacktrace.Propagate(err, "An error occurred saving service registration '%+v' for service '%s'", serviceRegistration, serviceName)
+	}
+	// remove service from the registered service repository is something fails downstream
 	defer func() {
 		if serviceSuccessfullyRegistered {
 			return
 		}
-		network.cleanupInternalMapsUnlocked(serviceName)
+		if err := network.serviceRegistrationRepository.Delete(serviceName); err != nil {
+			logrus.Errorf("We tried to delete the service registration for service  '%s' we had stored but failed:\n%v", serviceName, err)
+		}
 	}()
 
 	serviceSuccessfullyRegistered = true
@@ -841,12 +882,14 @@ func (network *DefaultServiceNetwork) registerService(
 // half-registered, but it's worth calling out that this method with throw if called with such a service
 func (network *DefaultServiceNetwork) unregisterService(ctx context.Context, serviceName service.ServiceName) error {
 
-	serviceRegistration, registrationFound := network.registeredServiceInfo[serviceName]
-	if !registrationFound {
-		return stacktrace.NewError("Unregistering a service that has not been properly registered should not happen: '%s'. This is a Kurtosis internal bug", serviceName)
+	serviceRegistration, err := network.serviceRegistrationRepository.Get(serviceName)
+	if err != nil {
+		return stacktrace.Propagate(err, "An error occurred getting service registration for service '%s'", serviceName)
 	}
 
-	network.cleanupInternalMapsUnlocked(serviceName)
+	if err := network.serviceRegistrationRepository.Delete(serviceName); err != nil {
+		return stacktrace.Propagate(err, "An error occurred deleting the service registration for service '%v' from the repository", serviceName)
+	}
 	serviceUuid := serviceRegistration.GetUUID()
 	serviceToUnregister := map[service.ServiceUUID]bool{
 		serviceUuid: true,
@@ -940,7 +983,11 @@ func (network *DefaultServiceNetwork) startRegisteredService(
 	}
 
 	serviceStartedSuccessfully = true
-	network.registeredServiceInfo[startedService.GetRegistration().GetName()].SetConfig(serviceConfig)
+	serviceName := startedService.GetRegistration().GetName()
+	if err := network.serviceRegistrationRepository.UpdateConfig(serviceName, serviceConfig); err != nil {
+		return nil, stacktrace.Propagate(err, "An error occurred while updating service config to '%+v' in service registration for service '%s' after the service was started", serviceConfig, serviceName)
+	}
+
 	return startedService, nil
 }
 
@@ -1046,11 +1093,12 @@ func (network *DefaultServiceNetwork) startRegisteredServices(
 
 // This method is not thread safe. Only call this from a method where there is a mutex lock on the network.
 func (network *DefaultServiceNetwork) copyFilesFromServiceUnlocked(ctx context.Context, serviceName service.ServiceName, srcPath string, artifactName string) (enclave_data_directory.FilesArtifactUUID, error) {
-	serviceObj, found := network.registeredServiceInfo[serviceName]
-	if !found {
-		return "", stacktrace.NewError("Cannot copy files from service '%v' because it does not exist in the network", serviceName)
+
+	serviceRegistrationObj, err := network.serviceRegistrationRepository.Get(serviceName)
+	if err != nil {
+		return "", stacktrace.Propagate(err, "Cannot copy files from service '%v' because it does not exist in the network", serviceName)
 	}
-	serviceUuid := serviceObj.GetUUID()
+	serviceUuid := serviceRegistrationObj.GetUUID()
 
 	store, err := network.enclaveDataDir.GetFilesArtifactStore()
 	if err != nil {
@@ -1183,22 +1231,18 @@ func (network *DefaultServiceNetwork) renderTemplatesUnlocked(templatesAndDataBy
 	return filesArtifactUuid, nil
 }
 
-// This isn't thread safe and must be called from a thread safe context
-func (network *DefaultServiceNetwork) cleanupInternalMapsUnlocked(serviceName service.ServiceName) {
-	_, found := network.registeredServiceInfo[serviceName]
-	if !found {
-		return
-	}
-	delete(network.registeredServiceInfo, serviceName)
-}
-
 // This isn't thread safe and must be called from a thread safe context
 func (network *DefaultServiceNetwork) getServiceNameForIdentifierUnlocked(serviceIdentifier string) (service.ServiceName, error) {
 	maybeServiceUuid := service.ServiceUUID(serviceIdentifier)
 	serviceUuidToServiceName := map[service.ServiceUUID]service.ServiceName{}
 	serviceShortenedUuidToServiceName := map[string][]service.ServiceName{}
 
-	for serviceName, registration := range network.registeredServiceInfo {
+	allServiceRegistrationsByServiceName, err := network.serviceRegistrationRepository.GetAll()
+	if err != nil {
+		return "", stacktrace.Propagate(err, "An error occurred getting all service registrations from the repository")
+	}
+
+	for serviceName, registration := range allServiceRegistrationsByServiceName {
 		serviceUuid := registration.GetUUID()
 		serviceShortenedUuid := uuid_generator.ShortenedUUIDString(string(serviceUuid))
 		serviceUuidToServiceName[serviceUuid] = serviceName
@@ -1219,7 +1263,12 @@ func (network *DefaultServiceNetwork) getServiceNameForIdentifierUnlocked(servic
 	}
 
 	maybeServiceName := service.ServiceName(serviceIdentifier)
-	if _, found := network.registeredServiceInfo[maybeServiceName]; found {
+
+	maybeServiceNameExist, err := network.serviceRegistrationRepository.Exist(maybeServiceName)
+	if err != nil {
+		return "", stacktrace.Propagate(err, "An error occurred checking if service name '%s' exist in the service registration repository", maybeServiceName)
+	}
+	if maybeServiceNameExist {
 		return maybeServiceName, nil
 	}
 
@@ -1404,9 +1453,9 @@ func (network *DefaultServiceNetwork) getServiceRegistrationForIdentifierUnlocke
 		return nil, stacktrace.Propagate(err, "An error occurred while fetching name for service identifier '%v'", serviceIdentifier)
 	}
 
-	serviceRegistration, found := network.registeredServiceInfo[serviceName]
-	if !found {
-		return nil, stacktrace.NewError("No service found with ID '%v'", serviceName)
+	serviceRegistration, err := network.serviceRegistrationRepository.Get(serviceName)
+	if err != nil {
+		return nil, stacktrace.Propagate(err, "An error occurred getting the service registration for service '%s'", serviceName)
 	}
 
 	return serviceRegistration, nil
diff --git a/core/server/api_container/server/service_network/mock_service_network.go b/core/server/api_container/server/service_network/mock_service_network.go
index 4fdc66223..2a72a5561 100644
--- a/core/server/api_container/server/service_network/mock_service_network.go
+++ b/core/server/api_container/server/service_network/mock_service_network.go
@@ -210,6 +210,58 @@ func (_c *MockServiceNetwork_CopyFilesFromService_Call) RunAndReturn(run func(co
 	return _c
 }
 
+// ExistServiceRegistration provides a mock function with given fields: serviceName
+func (_m *MockServiceNetwork) ExistServiceRegistration(serviceName service.ServiceName) (bool, error) {
+	ret := _m.Called(serviceName)
+
+	var r0 bool
+	var r1 error
+	if rf, ok := ret.Get(0).(func(service.ServiceName) (bool, error)); ok {
+		return rf(serviceName)
+	}
+	if rf, ok := ret.Get(0).(func(service.ServiceName) bool); ok {
+		r0 = rf(serviceName)
+	} else {
+		r0 = ret.Get(0).(bool)
+	}
+
+	if rf, ok := ret.Get(1).(func(service.ServiceName) error); ok {
+		r1 = rf(serviceName)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// MockServiceNetwork_ExistServiceRegistration_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ExistServiceRegistration'
+type MockServiceNetwork_ExistServiceRegistration_Call struct {
+	*mock.Call
+}
+
+// ExistServiceRegistration is a helper method to define mock.On call
+//   - serviceName service.ServiceName
+func (_e *MockServiceNetwork_Expecter) ExistServiceRegistration(serviceName interface{}) *MockServiceNetwork_ExistServiceRegistration_Call {
+	return &MockServiceNetwork_ExistServiceRegistration_Call{Call: _e.mock.On("ExistServiceRegistration", serviceName)}
+}
+
+func (_c *MockServiceNetwork_ExistServiceRegistration_Call) Run(run func(serviceName service.ServiceName)) *MockServiceNetwork_ExistServiceRegistration_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run(args[0].(service.ServiceName))
+	})
+	return _c
+}
+
+func (_c *MockServiceNetwork_ExistServiceRegistration_Call) Return(_a0 bool, _a1 error) *MockServiceNetwork_ExistServiceRegistration_Call {
+	_c.Call.Return(_a0, _a1)
+	return _c
+}
+
+func (_c *MockServiceNetwork_ExistServiceRegistration_Call) RunAndReturn(run func(service.ServiceName) (bool, error)) *MockServiceNetwork_ExistServiceRegistration_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
 // GetApiContainerInfo provides a mock function with given fields:
 func (_m *MockServiceNetwork) GetApiContainerInfo() *ApiContainerInfo {
 	ret := _m.Called()
@@ -430,10 +482,14 @@ func (_c *MockServiceNetwork_GetService_Call) RunAndReturn(run func(context.Cont
 }
 
 // GetServiceNames provides a mock function with given fields:
-func (_m *MockServiceNetwork) GetServiceNames() map[service.ServiceName]bool {
+func (_m *MockServiceNetwork) GetServiceNames() (map[service.ServiceName]bool, error) {
 	ret := _m.Called()
 
 	var r0 map[service.ServiceName]bool
+	var r1 error
+	if rf, ok := ret.Get(0).(func() (map[service.ServiceName]bool, error)); ok {
+		return rf()
+	}
 	if rf, ok := ret.Get(0).(func() map[service.ServiceName]bool); ok {
 		r0 = rf()
 	} else {
@@ -442,7 +498,13 @@ func (_m *MockServiceNetwork) GetServiceNames() map[service.ServiceName]bool {
 		}
 	}
 
-	return r0
+	if rf, ok := ret.Get(1).(func() error); ok {
+		r1 = rf()
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
 }
 
 // MockServiceNetwork_GetServiceNames_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetServiceNames'
@@ -462,66 +524,12 @@ func (_c *MockServiceNetwork_GetServiceNames_Call) Run(run func()) *MockServiceN
 	return _c
 }
 
-func (_c *MockServiceNetwork_GetServiceNames_Call) Return(_a0 map[service.ServiceName]bool) *MockServiceNetwork_GetServiceNames_Call {
-	_c.Call.Return(_a0)
-	return _c
-}
-
-func (_c *MockServiceNetwork_GetServiceNames_Call) RunAndReturn(run func() map[service.ServiceName]bool) *MockServiceNetwork_GetServiceNames_Call {
-	_c.Call.Return(run)
-	return _c
-}
-
-// GetServiceRegistration provides a mock function with given fields: serviceName
-func (_m *MockServiceNetwork) GetServiceRegistration(serviceName service.ServiceName) (*service.ServiceRegistration, bool) {
-	ret := _m.Called(serviceName)
-
-	var r0 *service.ServiceRegistration
-	var r1 bool
-	if rf, ok := ret.Get(0).(func(service.ServiceName) (*service.ServiceRegistration, bool)); ok {
-		return rf(serviceName)
-	}
-	if rf, ok := ret.Get(0).(func(service.ServiceName) *service.ServiceRegistration); ok {
-		r0 = rf(serviceName)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*service.ServiceRegistration)
-		}
-	}
-
-	if rf, ok := ret.Get(1).(func(service.ServiceName) bool); ok {
-		r1 = rf(serviceName)
-	} else {
-		r1 = ret.Get(1).(bool)
-	}
-
-	return r0, r1
-}
-
-// MockServiceNetwork_GetServiceRegistration_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetServiceRegistration'
-type MockServiceNetwork_GetServiceRegistration_Call struct {
-	*mock.Call
-}
-
-// GetServiceRegistration is a helper method to define mock.On call
-//   - serviceName service.ServiceName
-func (_e *MockServiceNetwork_Expecter) GetServiceRegistration(serviceName interface{}) *MockServiceNetwork_GetServiceRegistration_Call {
-	return &MockServiceNetwork_GetServiceRegistration_Call{Call: _e.mock.On("GetServiceRegistration", serviceName)}
-}
-
-func (_c *MockServiceNetwork_GetServiceRegistration_Call) Run(run func(serviceName service.ServiceName)) *MockServiceNetwork_GetServiceRegistration_Call {
-	_c.Call.Run(func(args mock.Arguments) {
-		run(args[0].(service.ServiceName))
-	})
-	return _c
-}
-
-func (_c *MockServiceNetwork_GetServiceRegistration_Call) Return(_a0 *service.ServiceRegistration, _a1 bool) *MockServiceNetwork_GetServiceRegistration_Call {
+func (_c *MockServiceNetwork_GetServiceNames_Call) Return(_a0 map[service.ServiceName]bool, _a1 error) *MockServiceNetwork_GetServiceNames_Call {
 	_c.Call.Return(_a0, _a1)
 	return _c
 }
 
-func (_c *MockServiceNetwork_GetServiceRegistration_Call) RunAndReturn(run func(service.ServiceName) (*service.ServiceRegistration, bool)) *MockServiceNetwork_GetServiceRegistration_Call {
+func (_c *MockServiceNetwork_GetServiceNames_Call) RunAndReturn(run func() (map[service.ServiceName]bool, error)) *MockServiceNetwork_GetServiceNames_Call {
 	_c.Call.Return(run)
 	return _c
 }
diff --git a/core/server/api_container/server/service_network/service_network.go b/core/server/api_container/server/service_network/service_network.go
index 5133023e9..471c9892a 100644
--- a/core/server/api_container/server/service_network/service_network.go
+++ b/core/server/api_container/server/service_network/service_network.go
@@ -95,11 +95,11 @@ type ServiceNetwork interface {
 
 	CopyFilesFromService(ctx context.Context, serviceIdentifier string, srcPath string, artifactName string) (enclave_data_directory.FilesArtifactUUID, error)
 
-	GetServiceNames() map[service.ServiceName]bool
+	GetServiceNames() (map[service.ServiceName]bool, error)
 
 	GetExistingAndHistoricalServiceIdentifiers() (service_identifiers.ServiceIdentifiers, error)
 
-	GetServiceRegistration(serviceName service.ServiceName) (*service.ServiceRegistration, bool)
+	ExistServiceRegistration(serviceName service.ServiceName) (bool, error)
 
 	RenderTemplates(templatesAndDataByDestinationRelFilepath map[string]*render_templates.TemplateData, artifactName string) (enclave_data_directory.FilesArtifactUUID, error)
 
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_instruction/add_service/add_service.go b/core/server/api_container/server/startosis_engine/kurtosis_instruction/add_service/add_service.go
index 1beb9b541..27e23ab1e 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_instruction/add_service/add_service.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_instruction/add_service/add_service.go
@@ -129,7 +129,11 @@ func (builtin *AddServiceCapabilities) Execute(ctx context.Context, _ *builtin_a
 		return "", stacktrace.Propagate(err, "An error occurred replace a magic string in '%s' instruction arguments for service '%s'. Execution cannot proceed", AddServiceBuiltinName, builtin.serviceName)
 	}
 	var startedService *service.Service
-	if _, found := builtin.serviceNetwork.GetServiceRegistration(builtin.serviceName); found {
+	exist, err := builtin.serviceNetwork.ExistServiceRegistration(builtin.serviceName)
+	if err != nil {
+		return "", stacktrace.Propagate(err, "An error occurred getting service registration for service '%s'", builtin.serviceName)
+	}
+	if exist {
 		startedService, err = builtin.serviceNetwork.UpdateService(ctx, replacedServiceName, replacedServiceConfig)
 	} else {
 		startedService, err = builtin.serviceNetwork.AddService(ctx, replacedServiceName, replacedServiceConfig)
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_instruction/add_service/add_services.go b/core/server/api_container/server/startosis_engine/kurtosis_instruction/add_service/add_services.go
index 812511169..d06c3d157 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_instruction/add_service/add_services.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_instruction/add_service/add_services.go
@@ -127,7 +127,11 @@ func (builtin *AddServicesCapabilities) Execute(ctx context.Context, _ *builtin_
 	serviceToUpdate := map[service.ServiceName]*service.ServiceConfig{}
 	serviceToCreate := map[service.ServiceName]*service.ServiceConfig{}
 	for serviceName, serviceConfig := range renderedServiceConfigs {
-		if _, found := builtin.serviceNetwork.GetServiceRegistration(serviceName); found {
+		exist, err := builtin.serviceNetwork.ExistServiceRegistration(serviceName)
+		if err != nil {
+			return "", stacktrace.Propagate(err, "An error occurred getting service registration for service '%s'", serviceName)
+		}
+		if exist {
 			serviceToUpdate[serviceName] = serviceConfig
 		} else {
 			serviceToCreate[serviceName] = serviceConfig
diff --git a/core/server/api_container/server/startosis_engine/startosis_validator.go b/core/server/api_container/server/startosis_engine/startosis_validator.go
index 098c005bf..e2a77a9c3 100644
--- a/core/server/api_container/server/startosis_engine/startosis_validator.go
+++ b/core/server/api_container/server/startosis_engine/startosis_validator.go
@@ -48,7 +48,14 @@ func (validator *StartosisValidator) Validate(ctx context.Context, instructionsS
 		starlarkRunResponseLineStream <- binding_constructors.NewStarlarkRunResponseLineFromSinglelineProgressInfo(
 			validationInProgressMsg, defaultCurrentStepNumber, defaultTotalStepsNumber)
 
-		serviceNames := validator.serviceNetwork.GetServiceNames()
+		serviceNames, err := validator.serviceNetwork.GetServiceNames()
+		if err != nil {
+			wrappedValidationError := startosis_errors.WrapWithValidationError(err, "An error occurred getting all service names")
+			starlarkRunResponseLineStream <- binding_constructors.NewStarlarkRunResponseLineFromValidationError(wrappedValidationError.ToAPIType())
+			starlarkRunResponseLineStream <- binding_constructors.NewStarlarkRunResponseLineFromRunFailureEvent()
+			return
+		}
+
 		serviceNamePortIdMapping, err := getServiceNameToPortIDsMap(serviceNames, validator.serviceNetwork)
 		if err != nil {
 			wrappedValidationError := startosis_errors.WrapWithValidationError(err, "Couldn't create validator environment as we ran into errors fetching existing services and ports")


Test patch:
diff --git a/container-engine-lib/lib/backend_interface/objects/port_spec/port_spec_test.go b/container-engine-lib/lib/backend_interface/objects/port_spec/port_spec_test.go
index 6cef1d10f..2c0a66e3b 100644
--- a/container-engine-lib/lib/backend_interface/objects/port_spec/port_spec_test.go
+++ b/container-engine-lib/lib/backend_interface/objects/port_spec/port_spec_test.go
@@ -1,11 +1,16 @@
 package port_spec
 
 import (
+	"encoding/json"
 	"github.com/stretchr/testify/require"
 	"testing"
 	"time"
 )
 
+var (
+	httpAppProtocol = "https"
+)
+
 var portWaitForTest = NewWait(5 * time.Second)
 
 func TestConstructorErrorsOnUnrecognizedProtocol(t *testing.T) {
@@ -14,16 +19,19 @@ func TestConstructorErrorsOnUnrecognizedProtocol(t *testing.T) {
 }
 
 func TestNewPortSpec_WithApplicationProtocolPresent(t *testing.T) {
-	https := "https"
-	spec, err := NewPortSpec(123, TransportProtocol_TCP, https, portWaitForTest)
+	spec, err := NewPortSpec(123, TransportProtocol_TCP, httpAppProtocol, portWaitForTest)
 
-	specActual := &PortSpec{
+	privatePortSpec := &privatePortSpec{
 		123,
 		TransportProtocol_TCP,
-		&https,
+		&httpAppProtocol,
 		portWaitForTest,
 	}
 
+	specActual := &PortSpec{
+		privatePortSpec,
+	}
+
 	require.NoError(t, err)
 	require.Equal(t, spec, specActual)
 }
@@ -31,13 +39,35 @@ func TestNewPortSpec_WithApplicationProtocolPresent(t *testing.T) {
 func TestNewPortSpec_WithApplicationProtocolAbsent(t *testing.T) {
 	spec, err := NewPortSpec(123, TransportProtocol_TCP, "", portWaitForTest)
 
-	specActual := &PortSpec{
+	privatePortSpec := &privatePortSpec{
 		123,
 		TransportProtocol_TCP,
 		nil,
 		portWaitForTest,
 	}
 
+	specActual := &PortSpec{
+		privatePortSpec,
+	}
+
 	require.NoError(t, err)
 	require.Equal(t, spec, specActual)
 }
+
+func TestPortSpecMarshallers(t *testing.T) {
+	originalPortSpec, err := NewPortSpec(123, TransportProtocol_TCP, httpAppProtocol, portWaitForTest)
+	require.NoError(t, err)
+
+	marshaledPortSpec, err := json.Marshal(originalPortSpec)
+	require.NoError(t, err)
+	require.NotNil(t, marshaledPortSpec)
+
+	// Suppressing exhaustruct requirement because we want an object with zero values
+	// nolint: exhaustruct
+	newPortSpec := &PortSpec{}
+
+	err = json.Unmarshal(marshaledPortSpec, newPortSpec)
+	require.NoError(t, err)
+
+	require.EqualValues(t, originalPortSpec, newPortSpec)
+}
diff --git a/container-engine-lib/lib/backend_interface/objects/port_spec/wait_test.go b/container-engine-lib/lib/backend_interface/objects/port_spec/wait_test.go
new file mode 100644
index 000000000..97248cb57
--- /dev/null
+++ b/container-engine-lib/lib/backend_interface/objects/port_spec/wait_test.go
@@ -0,0 +1,25 @@
+package port_spec
+
+import (
+	"encoding/json"
+	"github.com/stretchr/testify/require"
+	"testing"
+	"time"
+)
+
+func TestWaitMarshallers(t *testing.T) {
+	originalWait := NewWait(4 * time.Minute)
+
+	marshaledWait, err := json.Marshal(originalWait)
+	require.NoError(t, err)
+	require.NotNil(t, marshaledWait)
+
+	// Suppressing exhaustruct requirement because we want an object with zero values
+	// nolint: exhaustruct
+	newWait := &Wait{}
+
+	err = json.Unmarshal(marshaledWait, newWait)
+	require.NoError(t, err)
+
+	require.EqualValues(t, originalWait, newWait)
+}
diff --git a/container-engine-lib/lib/backend_interface/objects/service/service_config_test.go b/container-engine-lib/lib/backend_interface/objects/service/service_config_test.go
new file mode 100644
index 000000000..952d72b73
--- /dev/null
+++ b/container-engine-lib/lib/backend_interface/objects/service/service_config_test.go
@@ -0,0 +1,158 @@
+package service
+
+import (
+	"encoding/json"
+	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/port_spec"
+	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service_directory"
+	"github.com/stretchr/testify/require"
+	"testing"
+	"time"
+)
+
+func TestServiceConfigMarshallers(t *testing.T) {
+
+	imageName := "imageNameTest"
+	originalServiceConfig := getServiceConfigForTest(t, imageName)
+
+	marshaledServiceConfig, err := json.Marshal(originalServiceConfig)
+	require.NoError(t, err)
+	require.NotNil(t, marshaledServiceConfig)
+
+	// Suppressing exhaustruct requirement because we want an object with zero values
+	// nolint: exhaustruct
+	newServiceConfig := &ServiceConfig{}
+
+	err = json.Unmarshal(marshaledServiceConfig, newServiceConfig)
+	require.NoError(t, err)
+
+	require.Equal(t, originalServiceConfig.GetContainerImageName(), newServiceConfig.GetContainerImageName())
+
+	originalServiceConfigPrivatePorts := originalServiceConfig.GetPrivatePorts()
+	for privatePortId, privatePortSpec := range newServiceConfig.GetPrivatePorts() {
+		originalPrivetPortSpec, found := originalServiceConfigPrivatePorts[privatePortId]
+		require.True(t, found)
+		require.EqualValues(t, privatePortSpec, originalPrivetPortSpec)
+	}
+
+	originalServiceConfigPublicPorts := originalServiceConfig.GetPublicPorts()
+	for privatePortId, publicPortSpec := range newServiceConfig.GetPublicPorts() {
+		originalPublicPortSpec, found := originalServiceConfigPublicPorts[privatePortId]
+		require.True(t, found)
+		require.EqualValues(t, publicPortSpec, originalPublicPortSpec)
+	}
+
+	require.Equal(t, originalServiceConfig.GetEnvVars(), newServiceConfig.GetEnvVars())
+	require.Equal(t, originalServiceConfig.GetCmdArgs(), newServiceConfig.GetCmdArgs())
+	require.Equal(t, originalServiceConfig.GetEnvVars(), newServiceConfig.GetEnvVars())
+	require.EqualValues(t, originalServiceConfig.GetPersistentDirectories(), newServiceConfig.GetPersistentDirectories())
+	require.EqualValues(t, originalServiceConfig.GetPersistentDirectories(), newServiceConfig.GetPersistentDirectories())
+	require.Equal(t, originalServiceConfig.GetCPUAllocationMillicpus(), newServiceConfig.GetCPUAllocationMillicpus())
+	require.Equal(t, originalServiceConfig.GetMemoryAllocationMegabytes(), newServiceConfig.GetMemoryAllocationMegabytes())
+	require.Equal(t, originalServiceConfig.GetPrivateIPAddrPlaceholder(), newServiceConfig.GetPrivateIPAddrPlaceholder())
+	require.Equal(t, originalServiceConfig.GetMinCPUAllocationMillicpus(), newServiceConfig.GetMinCPUAllocationMillicpus())
+	require.Equal(t, originalServiceConfig.GetMinMemoryAllocationMegabytes(), newServiceConfig.GetMinMemoryAllocationMegabytes())
+}
+
+func getServiceConfigForTest(t *testing.T, imageName string) *ServiceConfig {
+	return NewServiceConfig(
+		imageName,
+		testPrivatePorts(t),
+		testPublicPorts(t),
+		[]string{"bin", "bash", "ls"},
+		[]string{"-l", "-a"},
+		testEnvVars(),
+		testFilesArtifactExpansion(),
+		testPersistentDirectory(),
+		500,
+		1024,
+		"IP-ADDRESS",
+		100,
+		512,
+	)
+}
+
+func testPersistentDirectory() *service_directory.PersistentDirectories {
+	persistentDirectoriesMap := map[string]service_directory.DirectoryPersistentKey{
+		"dirpath1": service_directory.DirectoryPersistentKey("dirpath1_persistent_directory_key"),
+		"dirpath2": service_directory.DirectoryPersistentKey("dirpath2_persistent_directory_key"),
+	}
+
+	return service_directory.NewPersistentDirectories(persistentDirectoriesMap)
+}
+
+func testFilesArtifactExpansion() *service_directory.FilesArtifactsExpansion {
+	return &service_directory.FilesArtifactsExpansion{
+		ExpanderImage: "expander-image:tag-version",
+		ExpanderEnvVars: map[string]string{
+			"ENV_VAR1": "env_var1_value",
+			"ENV_VAR2": "env_var2_value",
+		},
+		ServiceDirpathsToArtifactIdentifiers: map[string]string{
+			"/pahth/number1": "first_identifier",
+			"/path/number2":  "second_idenfifier",
+		},
+		ExpanderDirpathsToServiceDirpaths: map[string]string{
+			"/expander/dir1": "/service/dir1",
+			"/expander/dir2": "/service/dir2",
+		},
+	}
+}
+
+func testPrivatePorts(t *testing.T) map[string]*port_spec.PortSpec {
+
+	port1Id := "port1"
+	port1Num := uint16(23)
+	port1Protocol := port_spec.TransportProtocol_TCP
+	appProtocol1 := "app-protocol1"
+	wait1 := port_spec.NewWait(5 * time.Minute)
+	port1Spec, err := port_spec.NewPortSpec(port1Num, port1Protocol, appProtocol1, wait1)
+	require.NoError(t, err, "An unexpected error occurred creating port 1 spec")
+
+	port2Id := "port2"
+	port2Num := uint16(45)
+	port2Protocol := port_spec.TransportProtocol_TCP
+	appProtocol2 := "app-protocol2"
+	wait2 := port_spec.NewWait(24 * time.Second)
+	port2Spec, err := port_spec.NewPortSpec(port2Num, port2Protocol, appProtocol2, wait2)
+	require.NoError(t, err, "An unexpected error occurred creating port 2 spec")
+
+	input := map[string]*port_spec.PortSpec{
+		port1Id: port1Spec,
+		port2Id: port2Spec,
+	}
+
+	return input
+}
+
+func testPublicPorts(t *testing.T) map[string]*port_spec.PortSpec {
+
+	port1Id := "port1"
+	port1Num := uint16(23)
+	port1Protocol := port_spec.TransportProtocol_TCP
+	appProtocol1 := "app-protocol1-public"
+	wait1 := port_spec.NewWait(5 * time.Minute)
+	port1Spec, err := port_spec.NewPortSpec(port1Num, port1Protocol, appProtocol1, wait1)
+	require.NoError(t, err, "An unexpected error occurred creating port 1 spec")
+
+	port2Id := "port2"
+	port2Num := uint16(45)
+	port2Protocol := port_spec.TransportProtocol_TCP
+	appProtocol2 := "app-protocol2-public"
+	wait2 := port_spec.NewWait(24 * time.Second)
+	port2Spec, err := port_spec.NewPortSpec(port2Num, port2Protocol, appProtocol2, wait2)
+	require.NoError(t, err, "An unexpected error occurred creating port 2 spec")
+
+	input := map[string]*port_spec.PortSpec{
+		port1Id: port1Spec,
+		port2Id: port2Spec,
+	}
+
+	return input
+}
+
+func testEnvVars() map[string]string {
+	return map[string]string{
+		"HTTP_PORT":  "80",
+		"HTTPS_PORT": "443",
+	}
+}
diff --git a/container-engine-lib/lib/backend_interface/objects/service/service_registration_test.go b/container-engine-lib/lib/backend_interface/objects/service/service_registration_test.go
new file mode 100644
index 000000000..adb1b590d
--- /dev/null
+++ b/container-engine-lib/lib/backend_interface/objects/service/service_registration_test.go
@@ -0,0 +1,38 @@
+package service
+
+import (
+	"encoding/json"
+	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/enclave"
+	"github.com/stretchr/testify/require"
+	"net"
+	"testing"
+)
+
+func TestServiceRegistrationMarshallers(t *testing.T) {
+	serviceName := ServiceName("service-name-test")
+	uuid := ServiceUUID("cddc2ea3948149d9afa2ef93abb4ec54")
+	enclaveUuid := enclave.EnclaveUUID("9e5c8bf2fbeb4de68f647280b1c79cbb")
+	privateIp := net.ParseIP("198.51.100.121")
+	hostname := "hostname-test"
+
+	originalServiceRegistration := NewServiceRegistration(serviceName, uuid, enclaveUuid, privateIp, hostname)
+
+	startedServiceStatus := ServiceStatus_Started
+	serviceConfig := getServiceConfigForTest(t, "image-name:tag-version")
+
+	originalServiceRegistration.SetStatus(startedServiceStatus)
+	originalServiceRegistration.SetConfig(serviceConfig)
+
+	marshaledServiceRegistration, err := json.Marshal(originalServiceRegistration)
+	require.NoError(t, err)
+	require.NotNil(t, marshaledServiceRegistration)
+
+	// Suppressing exhaustruct requirement because we want an object with zero values
+	// nolint: exhaustruct
+	newServiceRegistration := &ServiceRegistration{}
+
+	err = json.Unmarshal(marshaledServiceRegistration, newServiceRegistration)
+	require.NoError(t, err)
+
+	require.EqualValues(t, originalServiceRegistration, newServiceRegistration)
+}
diff --git a/container-engine-lib/lib/database_accessors/enclave_db/service_registration/repository_test.go b/container-engine-lib/lib/database_accessors/enclave_db/service_registration/repository_test.go
new file mode 100644
index 000000000..f899777ac
--- /dev/null
+++ b/container-engine-lib/lib/database_accessors/enclave_db/service_registration/repository_test.go
@@ -0,0 +1,406 @@
+package service_registration
+
+import (
+	"fmt"
+	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/enclave"
+	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/port_spec"
+	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service"
+	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service_directory"
+	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/enclave_db"
+	"github.com/stretchr/testify/require"
+	bolt "go.etcd.io/bbolt"
+	"math/rand"
+	"net"
+	"os"
+	"testing"
+	"time"
+)
+
+const (
+	serviceNameFormat  = "service-name-test-%v"
+	uuidFormat         = "cddc2ea3948149d9afa2ef93abb4ec5%v"
+	enclaveUuidFormat  = "%ve5c8bf2fbeb4de68f647280b1c79cbb"
+	hostnameFormat     = "hostname-test-%v"
+	privateIpStrFormat = "198.51.100.12%v"
+	imageNameFormat    = "image-name:version-%v"
+)
+
+type ServiceRegistrationData struct {
+	name        service.ServiceName
+	uuid        service.ServiceUUID
+	enclaveUuid enclave.EnclaveUUID
+	hostname    string
+	status      service.ServiceStatus
+	privateIp   net.IP
+	imageName   string
+}
+
+func TestSaveAndGetServiceRegistration_Success(t *testing.T) {
+	repository := getRepositoryForTest(t)
+
+	originalServiceRegistration := saveAndGetOneServiceRegistrationForTest(t, repository)
+
+	serviceRegistrationFromRepository, err := repository.Get(originalServiceRegistration.GetName())
+	require.NoError(t, err)
+
+	require.Equal(t, originalServiceRegistration, serviceRegistrationFromRepository)
+}
+
+func TestGetAll_Success(t *testing.T) {
+	repository := getRepositoryForTest(t)
+
+	amountOfRegistrations := 5
+
+	originalServiceRegistrations, _ := getServiceRegistrationsForTest(t, amountOfRegistrations)
+	require.NotNil(t, originalServiceRegistrations)
+	require.Equal(t, amountOfRegistrations, len(originalServiceRegistrations))
+
+	for _, serviceRegistration := range originalServiceRegistrations {
+		require.NotNil(t, serviceRegistration)
+		err := repository.Save(serviceRegistration)
+		require.NoError(t, err)
+	}
+
+	serviceRegistrationsFromRepository, err := repository.GetAll()
+	require.NoError(t, err)
+	require.Len(t, serviceRegistrationsFromRepository, len(originalServiceRegistrations))
+
+	require.EqualValues(t, originalServiceRegistrations, serviceRegistrationsFromRepository)
+}
+
+func TestExist_Success(t *testing.T) {
+	repository := getRepositoryForTest(t)
+
+	originalServiceRegistration := saveAndGetOneServiceRegistrationForTest(t, repository)
+
+	exist, err := repository.Exist(originalServiceRegistration.GetName())
+	require.NoError(t, err)
+	require.True(t, exist)
+}
+
+func TestDoesNotExist(t *testing.T) {
+	repository := getRepositoryForTest(t)
+
+	saveAndGetOneServiceRegistrationForTest(t, repository)
+
+	fakeServiceName := service.ServiceName("fake-service-name")
+
+	exist, err := repository.Exist(fakeServiceName)
+	require.NoError(t, err)
+	require.False(t, exist)
+}
+
+func TestGetAllServiceNames_Success(t *testing.T) {
+	repository := getRepositoryForTest(t)
+
+	amountOfRegistrations := 5
+
+	originalServiceRegistrations, originalServiceNames := getServiceRegistrationsForTest(t, amountOfRegistrations)
+	require.NotNil(t, originalServiceRegistrations)
+	require.Equal(t, amountOfRegistrations, len(originalServiceRegistrations))
+
+	for _, serviceRegistration := range originalServiceRegistrations {
+		require.NotNil(t, serviceRegistration)
+		err := repository.Save(serviceRegistration)
+		require.NoError(t, err)
+	}
+
+	allServiceNamesFromRepository, err := repository.GetAllServiceNames()
+	require.NoError(t, err)
+	require.Len(t, allServiceNamesFromRepository, len(originalServiceRegistrations))
+
+	require.EqualValues(t, originalServiceNames, allServiceNamesFromRepository)
+}
+
+func TestUpdateStatus_Success(t *testing.T) {
+	repository := getRepositoryForTest(t)
+
+	originalServiceRegistration := saveAndGetOneServiceRegistrationForTest(t, repository)
+
+	newStatus := service.ServiceStatus_Started
+	if originalServiceRegistration.GetStatus() == service.ServiceStatus_Started {
+		newStatus = service.ServiceStatus_Stopped
+	}
+
+	err := repository.UpdateStatus(originalServiceRegistration.GetName(), newStatus)
+	require.NoError(t, err)
+
+	serviceRegistrationFromRepository, err := repository.Get(originalServiceRegistration.GetName())
+	require.NoError(t, err)
+
+	require.Equal(t, newStatus, serviceRegistrationFromRepository.GetStatus())
+}
+
+func TestUpdateConfig_Success(t *testing.T) {
+	repository := getRepositoryForTest(t)
+
+	originalServiceRegistration := saveAndGetOneServiceRegistrationForTest(t, repository)
+
+	newStatus := service.ServiceStatus_Started
+	if originalServiceRegistration.GetStatus() == service.ServiceStatus_Started {
+		newStatus = service.ServiceStatus_Stopped
+	}
+
+	anotherImageName := "another-image-name"
+	newConfig := getServiceConfigForTest(t, anotherImageName)
+
+	err := repository.UpdateStatusAndConfig(originalServiceRegistration.GetName(), newStatus, newConfig)
+	require.NoError(t, err)
+
+	serviceRegistrationFromRepository, err := repository.Get(originalServiceRegistration.GetName())
+	require.NoError(t, err)
+
+	require.Equal(t, newStatus, serviceRegistrationFromRepository.GetStatus())
+	require.Equal(t, newConfig, serviceRegistrationFromRepository.GetConfig())
+}
+
+func TestUpdateStatusAndConfig_Success(t *testing.T) {
+	repository := getRepositoryForTest(t)
+
+	originalServiceRegistration := saveAndGetOneServiceRegistrationForTest(t, repository)
+
+	anotherImageName := "another-image-name"
+	newConfig := getServiceConfigForTest(t, anotherImageName)
+
+	err := repository.UpdateConfig(originalServiceRegistration.GetName(), newConfig)
+	require.NoError(t, err)
+
+	serviceRegistrationFromRepository, err := repository.Get(originalServiceRegistration.GetName())
+	require.NoError(t, err)
+
+	require.Equal(t, newConfig, serviceRegistrationFromRepository.GetConfig())
+}
+
+func TestDelete_Success(t *testing.T) {
+	repository := getRepositoryForTest(t)
+
+	originalServiceRegistration := saveAndGetOneServiceRegistrationForTest(t, repository)
+
+	err := repository.Delete(originalServiceRegistration.GetName())
+	require.NoError(t, err)
+
+	exist, err := repository.Exist(originalServiceRegistration.GetName())
+	require.NoError(t, err)
+	require.False(t, exist)
+}
+
+func saveAndGetOneServiceRegistrationForTest(
+	t *testing.T,
+	repository *ServiceRegistrationRepository,
+) *service.ServiceRegistration {
+	amountOfRegistrations := 1
+
+	serviceRegistrations, _ := getServiceRegistrationsForTest(t, amountOfRegistrations)
+	require.NotNil(t, serviceRegistrations)
+	require.Equal(t, amountOfRegistrations, len(serviceRegistrations))
+
+	firsServiceName := service.ServiceName(fmt.Sprintf(serviceNameFormat, 0))
+	originalServiceRegistration, found := serviceRegistrations[firsServiceName]
+	require.True(t, found)
+	require.NotNil(t, originalServiceRegistration)
+
+	err := repository.Save(originalServiceRegistration)
+	require.NoError(t, err)
+
+	return originalServiceRegistration
+}
+
+func getRepositoryForTest(t *testing.T) *ServiceRegistrationRepository {
+	file, err := os.CreateTemp("/tmp", "*.db")
+	defer func() {
+		err = os.Remove(file.Name())
+		require.NoError(t, err)
+	}()
+
+	require.NoError(t, err)
+	db, err := bolt.Open(file.Name(), 0666, nil)
+	require.NoError(t, err)
+	enclaveDb := &enclave_db.EnclaveDB{
+		DB: db,
+	}
+	repository, err := GetOrCreateNewServiceRegistrationRepository(enclaveDb)
+	require.NoError(t, err)
+
+	return repository
+}
+
+func getServiceRegistrationsForTest(t *testing.T, amount int) (map[service.ServiceName]*service.ServiceRegistration, map[service.ServiceName]bool) {
+	serviceRegistrations := map[service.ServiceName]*service.ServiceRegistration{}
+	serviceNames := map[service.ServiceName]bool{}
+
+	serviceRegistrationDataList := getServiceRegistrationData(amount)
+
+	for _, data := range serviceRegistrationDataList {
+		serviceRegistration := getServiceRegistrationWithDataForTest(
+			t,
+			data.name,
+			data.uuid,
+			data.enclaveUuid,
+			data.privateIp,
+			data.hostname,
+			data.status,
+			data.imageName,
+		)
+		serviceRegistrations[data.name] = serviceRegistration
+		serviceNames[data.name] = true
+	}
+
+	return serviceRegistrations, serviceNames
+}
+
+func getServiceRegistrationData(amount int) []*ServiceRegistrationData {
+	serviceRegistrationDataList := []*ServiceRegistrationData{}
+
+	serviceStatusNumber := len(service.ServiceStatusValues()) - 1
+
+	for i := 0; i < amount; i++ {
+		name := service.ServiceName(fmt.Sprintf(serviceNameFormat, i))
+		uuid := service.ServiceUUID(fmt.Sprintf(uuidFormat, i))
+		enclaveUuid := enclave.EnclaveUUID(fmt.Sprintf(enclaveUuidFormat, i))
+		hostname := fmt.Sprintf(hostnameFormat, i)
+		privateIp := net.ParseIP(fmt.Sprintf(privateIpStrFormat, i))
+		image := fmt.Sprintf(imageNameFormat, i)
+
+		randomStatus := rand.Intn(serviceStatusNumber)
+		status := service.ServiceStatus(randomStatus)
+
+		data := &ServiceRegistrationData{
+			name,
+			uuid,
+			enclaveUuid,
+			hostname,
+			status,
+			privateIp,
+			image,
+		}
+		serviceRegistrationDataList = append(serviceRegistrationDataList, data)
+	}
+
+	return serviceRegistrationDataList
+}
+
+func getServiceRegistrationWithDataForTest(
+	t *testing.T,
+	serviceName service.ServiceName,
+	uuid service.ServiceUUID,
+	enclaveUuid enclave.EnclaveUUID,
+	privateIp net.IP,
+	hostname string,
+	serviceStatus service.ServiceStatus,
+	image string,
+) *service.ServiceRegistration {
+
+	serviceRegistration := service.NewServiceRegistration(serviceName, uuid, enclaveUuid, privateIp, hostname)
+
+	serviceRegistration.SetStatus(serviceStatus)
+
+	serviceConfig := getServiceConfigForTest(t, image)
+
+	serviceRegistration.SetConfig(serviceConfig)
+
+	return serviceRegistration
+}
+
+func getServiceConfigForTest(t *testing.T, imageName string) *service.ServiceConfig {
+	return service.NewServiceConfig(
+		imageName,
+		testPrivatePorts(t),
+		testPublicPorts(t),
+		[]string{"bin", "bash", "ls"},
+		[]string{"-l", "-a"},
+		testEnvVars(),
+		testFilesArtifactExpansion(),
+		testPersistentDirectory(),
+		500,
+		1024,
+		"IP-ADDRESS",
+		100,
+		512,
+	)
+}
+
+func testPersistentDirectory() *service_directory.PersistentDirectories {
+	persistentDirectoriesMap := map[string]service_directory.DirectoryPersistentKey{
+		"dirpath1": service_directory.DirectoryPersistentKey("dirpath1_persistent_directory_key"),
+		"dirpath2": service_directory.DirectoryPersistentKey("dirpath2_persistent_directory_key"),
+	}
+
+	return service_directory.NewPersistentDirectories(persistentDirectoriesMap)
+}
+
+func testFilesArtifactExpansion() *service_directory.FilesArtifactsExpansion {
+	return &service_directory.FilesArtifactsExpansion{
+		ExpanderImage: "expander-image:tag-version",
+		ExpanderEnvVars: map[string]string{
+			"ENV_VAR1": "env_var1_value",
+			"ENV_VAR2": "env_var2_value",
+		},
+		ServiceDirpathsToArtifactIdentifiers: map[string]string{
+			"/pahth/number1": "first_identifier",
+			"/path/number2":  "second_idenfifier",
+		},
+		ExpanderDirpathsToServiceDirpaths: map[string]string{
+			"/expander/dir1": "/service/dir1",
+			"/expander/dir2": "/service/dir2",
+		},
+	}
+}
+
+func testPrivatePorts(t *testing.T) map[string]*port_spec.PortSpec {
+
+	port1Id := "port1"
+	port1Num := uint16(23)
+	port1Protocol := port_spec.TransportProtocol_TCP
+	appProtocol1 := "app-protocol1"
+	wait1 := port_spec.NewWait(5 * time.Minute)
+	port1Spec, err := port_spec.NewPortSpec(port1Num, port1Protocol, appProtocol1, wait1)
+	require.NoError(t, err, "An unexpected error occurred creating port 1 spec")
+
+	port2Id := "port2"
+	port2Num := uint16(45)
+	port2Protocol := port_spec.TransportProtocol_TCP
+	appProtocol2 := "app-protocol2"
+	wait2 := port_spec.NewWait(24 * time.Second)
+	port2Spec, err := port_spec.NewPortSpec(port2Num, port2Protocol, appProtocol2, wait2)
+	require.NoError(t, err, "An unexpected error occurred creating port 2 spec")
+
+	input := map[string]*port_spec.PortSpec{
+		port1Id: port1Spec,
+		port2Id: port2Spec,
+	}
+
+	return input
+}
+
+func testPublicPorts(t *testing.T) map[string]*port_spec.PortSpec {
+
+	port1Id := "port1"
+	port1Num := uint16(23)
+	port1Protocol := port_spec.TransportProtocol_TCP
+	appProtocol1 := "app-protocol1-public"
+	wait1 := port_spec.NewWait(5 * time.Minute)
+	port1Spec, err := port_spec.NewPortSpec(port1Num, port1Protocol, appProtocol1, wait1)
+	require.NoError(t, err, "An unexpected error occurred creating port 1 spec")
+
+	port2Id := "port2"
+	port2Num := uint16(45)
+	port2Protocol := port_spec.TransportProtocol_TCP
+	appProtocol2 := "app-protocol2-public"
+	wait2 := port_spec.NewWait(24 * time.Second)
+	port2Spec, err := port_spec.NewPortSpec(port2Num, port2Protocol, appProtocol2, wait2)
+	require.NoError(t, err, "An unexpected error occurred creating port 2 spec")
+
+	input := map[string]*port_spec.PortSpec{
+		port1Id: port1Spec,
+		port2Id: port2Spec,
+	}
+
+	return input
+}
+
+func testEnvVars() map[string]string {
+	return map[string]string{
+		"HTTP_PORT":  "80",
+		"HTTPS_PORT": "443",
+	}
+}
diff --git a/core/server/api_container/server/service_network/default_service_network_test.go b/core/server/api_container/server/service_network/default_service_network_test.go
index 4aaac97c1..a73d91d4c 100644
--- a/core/server/api_container/server/service_network/default_service_network_test.go
+++ b/core/server/api_container/server/service_network/default_service_network_test.go
@@ -128,8 +128,11 @@ func TestAddService_Successful(t *testing.T) {
 
 	require.Equal(t, serviceRegistration, startedService.GetRegistration())
 
-	require.Len(t, network.registeredServiceInfo, 1)
-	require.Contains(t, network.registeredServiceInfo, serviceName)
+	allServiceRegistration, err := network.serviceRegistrationRepository.GetAll()
+	require.NoError(t, err)
+
+	require.Len(t, allServiceRegistration, 1)
+	require.Contains(t, allServiceRegistration, serviceName)
 	allExistingAndHistoricalIdentifiers, err := network.GetExistingAndHistoricalServiceIdentifiers()
 	require.NoError(t, err)
 	require.Len(t, allExistingAndHistoricalIdentifiers, 1)
@@ -219,7 +222,9 @@ func TestAddService_FailedToStart(t *testing.T) {
 	require.NotNil(t, err)
 	require.Nil(t, startedService)
 
-	require.Empty(t, network.registeredServiceInfo)
+	allServiceRegistration, err := network.serviceRegistrationRepository.GetAll()
+	require.NoError(t, err)
+	require.Empty(t, allServiceRegistration)
 	allExistingAndHistoricalIdentifiers, err := network.GetExistingAndHistoricalServiceIdentifiers()
 	require.NoError(t, err)
 	require.Empty(t, allExistingAndHistoricalIdentifiers)
@@ -300,8 +305,10 @@ func TestAddServices_Success(t *testing.T) {
 	require.Contains(t, success, successfulServiceName)
 	require.Empty(t, failure)
 
-	require.Len(t, network.registeredServiceInfo, 1)
-	require.Contains(t, network.registeredServiceInfo, successfulServiceName)
+	allServiceRegistration, err := network.serviceRegistrationRepository.GetAll()
+	require.NoError(t, err)
+	require.Len(t, allServiceRegistration, 1)
+	require.Contains(t, allServiceRegistration, successfulServiceName)
 
 	allExistingAndHistoricalIdentifiers, err := network.GetExistingAndHistoricalServiceIdentifiers()
 	require.NoError(t, err)
@@ -463,7 +470,9 @@ func TestAddServices_FailureRollsBackTheEntireBatch(t *testing.T) {
 	require.Len(t, failure, 1)
 	require.Contains(t, failure, failedServiceName)
 
-	require.Empty(t, network.registeredServiceInfo)
+	allServiceRegistration, err := network.serviceRegistrationRepository.GetAll()
+	require.NoError(t, err)
+	require.Empty(t, allServiceRegistration)
 	allExistingAndHistoricalIdentifiers, err := network.GetExistingAndHistoricalServiceIdentifiers()
 	require.NoError(t, err)
 	require.Empty(t, allExistingAndHistoricalIdentifiers)
@@ -548,7 +557,9 @@ func TestStopService_Successful(t *testing.T) {
 		enclaveDb,
 	)
 	require.Nil(t, err)
-	network.registeredServiceInfo[serviceName] = serviceRegistration
+
+	err = network.serviceRegistrationRepository.Save(serviceRegistration)
+	require.NoError(t, err)
 
 	// The service is registered before being started
 	backend.EXPECT().StopUserServices(
@@ -571,7 +582,10 @@ func TestStopService_Successful(t *testing.T) {
 
 	err = network.StopService(ctx, string(serviceName))
 	require.Nil(t, err)
-	require.Equal(t, serviceRegistration.GetStatus(), service.ServiceStatus_Stopped)
+
+	serviceRegistrationAfterBeingStopped, err := network.serviceRegistrationRepository.Get(serviceName)
+	require.NoError(t, err)
+	require.Equal(t, serviceRegistrationAfterBeingStopped.GetStatus(), service.ServiceStatus_Stopped)
 }
 
 func TestStopService_StopUserServicesFailed(t *testing.T) {
@@ -601,7 +615,8 @@ func TestStopService_StopUserServicesFailed(t *testing.T) {
 		enclaveDb,
 	)
 	require.Nil(t, err)
-	network.registeredServiceInfo[serviceName] = serviceRegistration
+	err = network.serviceRegistrationRepository.Save(serviceRegistration)
+	require.NoError(t, err)
 
 	// The service is registered before being started
 	backend.EXPECT().StopUserServices(
@@ -655,7 +670,8 @@ func TestStopService_ServiceAlreadyStopped(t *testing.T) {
 		enclaveDb,
 	)
 	require.Nil(t, err)
-	network.registeredServiceInfo[serviceName] = serviceRegistration
+	err = network.serviceRegistrationRepository.Save(serviceRegistration)
+	require.NoError(t, err)
 
 	// The service is registered before being started
 	backend.EXPECT().StopUserServices(
@@ -707,7 +723,8 @@ func TestStartService_Successful(t *testing.T) {
 		enclaveDb,
 	)
 	require.Nil(t, err)
-	network.registeredServiceInfo[serviceName] = serviceRegistration
+	err = network.serviceRegistrationRepository.Save(serviceRegistration)
+	require.NoError(t, err)
 
 	// The service is registered before being started
 	backend.EXPECT().StartRegisteredUserServices(
@@ -726,7 +743,9 @@ func TestStartService_Successful(t *testing.T) {
 
 	err = network.StartService(ctx, string(serviceName))
 	require.Nil(t, err)
-	require.Equal(t, serviceRegistration.GetStatus(), service.ServiceStatus_Started)
+	serviceRegistrationAfterBeingStarted, err := network.serviceRegistrationRepository.Get(serviceName)
+	require.NoError(t, err)
+	require.Equal(t, serviceRegistrationAfterBeingStarted.GetStatus(), service.ServiceStatus_Started)
 }
 
 func TestStartService_StartRegisteredUserServicesFailed(t *testing.T) {
@@ -758,7 +777,8 @@ func TestStartService_StartRegisteredUserServicesFailed(t *testing.T) {
 		enclaveDb,
 	)
 	require.Nil(t, err)
-	network.registeredServiceInfo[serviceName] = serviceRegistration
+	err = network.serviceRegistrationRepository.Save(serviceRegistration)
+	require.NoError(t, err)
 
 	// The service is registered before being started
 	backend.EXPECT().StartRegisteredUserServices(
@@ -810,7 +830,8 @@ func TestStartService_ServiceAlreadyStarted(t *testing.T) {
 		enclaveDb,
 	)
 	require.Nil(t, err)
-	network.registeredServiceInfo[serviceName] = serviceRegistration
+	err = network.serviceRegistrationRepository.Save(serviceRegistration)
+	require.NoError(t, err)
 
 	// The service is registered before being started
 	backend.EXPECT().StartRegisteredUserServices(
@@ -863,7 +884,8 @@ func TestUpdateService(t *testing.T) {
 		testServiceHostnameFromInt(existingServiceIndex))
 	existingServiceRegistration.SetConfig(initialServiceConfig)
 	existingServiceRegistration.SetStatus(service.ServiceStatus_Started)
-	network.registeredServiceInfo[existingServiceRegistration.GetName()] = existingServiceRegistration
+	err = network.serviceRegistrationRepository.Save(existingServiceRegistration)
+	require.NoError(t, err)
 
 	// service that will fail because it's not registered in the enclave prior to update
 	unknownServiceIndex := 2
@@ -886,7 +908,8 @@ func TestUpdateService(t *testing.T) {
 		testServiceHostnameFromInt(failedToBeRemovedServiceIndex))
 	failedToBeRemovedServiceRegistration.SetConfig(initialServiceConfig)
 	failedToBeRemovedServiceRegistration.SetStatus(service.ServiceStatus_Started)
-	network.registeredServiceInfo[failedToBeRemovedServiceRegistration.GetName()] = failedToBeRemovedServiceRegistration
+	err = network.serviceRegistrationRepository.Save(failedToBeRemovedServiceRegistration)
+	require.NoError(t, err)
 
 	// service that will fail to be re-created once it has been removed
 	failedToBeRecreatedServiceIndex := 4
@@ -899,7 +922,8 @@ func TestUpdateService(t *testing.T) {
 		testServiceHostnameFromInt(failedToBeRecreatedServiceIndex))
 	failedToBeRecreatedServiceRegistration.SetConfig(initialServiceConfig)
 	failedToBeRecreatedServiceRegistration.SetStatus(service.ServiceStatus_Started)
-	network.registeredServiceInfo[failedToBeRecreatedServiceRegistration.GetName()] = failedToBeRecreatedServiceRegistration
+	err = network.serviceRegistrationRepository.Save(failedToBeRecreatedServiceRegistration)
+	require.NoError(t, err)
 
 	// The service will be removed first
 	backend.EXPECT().RemoveRegisteredUserServiceProcesses(
@@ -965,21 +989,26 @@ func TestUpdateService(t *testing.T) {
 	require.Contains(t, failure, failedToBeRemovedServiceRegistration.GetName())
 	require.Contains(t, failure, failedToBeRecreatedServiceRegistration.GetName())
 
-	newExistingServiceRegistration, found := network.registeredServiceInfo[existingServiceRegistration.GetName()]
-	require.True(t, found)
+	newExistingServiceRegistration, err := network.serviceRegistrationRepository.Get(existingServiceRegistration.GetName())
+	require.NoError(t, err)
+	require.NotNil(t, newExistingServiceRegistration)
+
 	require.Equal(t, newExistingServiceRegistration.GetStatus(), service.ServiceStatus_Started)
 	require.Equal(t, newExistingServiceRegistration.GetConfig(), updatedServiceConfig)
 
-	_, found = network.registeredServiceInfo[unknownServiceRegistration.GetName()]
-	require.False(t, found)
+	exist, err := network.serviceRegistrationRepository.Exist(unknownServiceRegistration.GetName())
+	require.NoError(t, err)
+	require.False(t, exist)
 
-	newFailedToBeRemovedServiceRegistration, found := network.registeredServiceInfo[failedToBeRemovedServiceRegistration.GetName()]
-	require.True(t, found)
+	newFailedToBeRemovedServiceRegistration, err := network.serviceRegistrationRepository.Get(failedToBeRemovedServiceRegistration.GetName())
+	require.NoError(t, err)
+	require.NotNil(t, newFailedToBeRemovedServiceRegistration)
 	require.Equal(t, newFailedToBeRemovedServiceRegistration.GetStatus(), service.ServiceStatus_Started)
 	require.Equal(t, newFailedToBeRemovedServiceRegistration.GetConfig(), initialServiceConfig)
 
-	newFailedToBeRecreatedServiceRegistration, found := network.registeredServiceInfo[failedToBeRecreatedServiceRegistration.GetName()]
-	require.True(t, found)
+	newFailedToBeRecreatedServiceRegistration, err := network.serviceRegistrationRepository.Get(failedToBeRecreatedServiceRegistration.GetName())
+	require.NoError(t, err)
+	require.NotNil(t, newFailedToBeRecreatedServiceRegistration)
 	require.Equal(t, newFailedToBeRecreatedServiceRegistration.GetStatus(), service.ServiceStatus_Registered)
 	require.Nil(t, newFailedToBeRecreatedServiceRegistration.GetConfig())
 }
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/add_service_framework_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/add_service_framework_test.go
index 362a0de30..497a4b9df 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/add_service_framework_test.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/add_service_framework_test.go
@@ -36,7 +36,7 @@ func (t *addServiceTestCase) GetInstruction() *kurtosis_plan_instruction.Kurtosi
 	serviceNetwork := service_network.NewMockServiceNetwork(t)
 	runtimeValueStore := runtime_value_store.NewRuntimeValueStore()
 
-	serviceNetwork.EXPECT().GetServiceRegistration(TestServiceName).Times(1).Return(nil, false)
+	serviceNetwork.EXPECT().ExistServiceRegistration(TestServiceName).Times(1).Return(false, nil)
 	serviceNetwork.EXPECT().AddService(
 		mock.Anything,
 		TestServiceName,
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/add_services_framework_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/add_services_framework_test.go
index 21cc3ed53..1eaef41d6 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/add_services_framework_test.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/add_services_framework_test.go
@@ -39,8 +39,8 @@ func (t *addServicesTestCase) GetInstruction() *kurtosis_plan_instruction.Kurtos
 	serviceNetwork := service_network.NewMockServiceNetwork(t)
 	runtimeValueStore := runtime_value_store.NewRuntimeValueStore()
 
-	serviceNetwork.EXPECT().GetServiceRegistration(TestServiceName).Times(1).Return(nil, false)
-	serviceNetwork.EXPECT().GetServiceRegistration(TestServiceName2).Times(1).Return(nil, false)
+	serviceNetwork.EXPECT().ExistServiceRegistration(TestServiceName).Times(1).Return(false, nil)
+	serviceNetwork.EXPECT().ExistServiceRegistration(TestServiceName2).Times(1).Return(false, nil)
 	serviceNetwork.EXPECT().UpdateServices(
 		mock.Anything,
 		map[service.ServiceName]*service.ServiceConfig{},
diff --git a/core/server/api_container/server/startosis_engine/startosis_interpreter_test.go b/core/server/api_container/server/startosis_engine/startosis_interpreter_test.go
index ea8cabaf3..b212d8b77 100644
--- a/core/server/api_container/server/startosis_engine/startosis_interpreter_test.go
+++ b/core/server/api_container/server/startosis_engine/startosis_interpreter_test.go
@@ -64,7 +64,7 @@ func (suite *StartosisInterpreterTestSuite) SetupTest() {
 
 	suite.interpreter = NewStartosisInterpreter(suite.serviceNetwork, suite.packageContentProvider, suite.runtimeValueStore)
 
-	mockedServiceRegistration := service.NewServiceRegistration(
+	service.NewServiceRegistration(
 		testServiceName,
 		service.ServiceUUID(fmt.Sprintf("%s-%s", testServiceName, serviceUuidSuffix)),
 		mockEnclaveUuid,
@@ -72,7 +72,7 @@ func (suite *StartosisInterpreterTestSuite) SetupTest() {
 		string(testServiceName),
 	)
 	suite.serviceNetwork.EXPECT().GetUniqueNameForFileArtifact().Maybe().Return(mockFileArtifactName, nil)
-	suite.serviceNetwork.EXPECT().GetServiceRegistration(testServiceName).Maybe().Return(&mockedServiceRegistration, nil)
+	suite.serviceNetwork.EXPECT().ExistServiceRegistration(testServiceName).Maybe().Return(true, nil)
 }
 
 func TestRunStartosisInterpreterTestSuite(t *testing.T) {