diff --git a/Dockerfile b/Dockerfile
index 685baba00cacc0280fa4e86aa10c0680a46f0859..dd077fc7c5b790e77d29ca9352c98bc4e59dd05c 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -19,6 +19,7 @@ COPY ./cmd ./cmd
 COPY ./interfaces ./interfaces
 COPY ./northbound ./northbound
 COPY ./nucleus ./nucleus
+COPY ./store ./store
 
 RUN GOOS=linux go build $BUILDARGS ./cmd/gosdn
 
diff --git a/api/api_test.toml b/api/api_test.toml
new file mode 100644
index 0000000000000000000000000000000000000000..fb66a37541a7332465914a8f0f5102e5ba4a49a4
--- /dev/null
+++ b/api/api_test.toml
@@ -0,0 +1 @@
+cli_pnd = "2043519e-46d1-4963-9a8e-d99007e104b8"
diff --git a/api/initialise_test.go b/api/initialise_test.go
index bbac6dad0f48872079d548671b9a52e8bbe5ed0a..7a7429a96db3b2997f70b4ef3e4bddcfcb336ea9 100644
--- a/api/initialise_test.go
+++ b/api/initialise_test.go
@@ -14,6 +14,7 @@ import (
 	nbi "code.fbi.h-da.de/danet/gosdn/northbound/server"
 	"code.fbi.h-da.de/danet/gosdn/nucleus"
 	"code.fbi.h-da.de/danet/gosdn/nucleus/util/proto"
+	"code.fbi.h-da.de/danet/gosdn/store"
 	"code.fbi.h-da.de/danet/yang-models/generated/openconfig"
 	"github.com/google/uuid"
 	log "github.com/sirupsen/logrus"
@@ -36,8 +37,8 @@ const changeID = "0992d600-f7d4-4906-9559-409b04d59a5f"
 const sbiID = "f6fd4b35-f039-4111-9156-5e4501bb8a5a"
 const ondID = "7e0ed8cc-ebf5-46fa-9794-741494914883"
 
-var pndStore *nucleus.PndStore
-var sbiStore *nucleus.SbiStore
+var pndStore *store.PndStore
+var sbiStore *store.SbiStore
 var lis *bufconn.Listener
 var pndUUID uuid.UUID
 var sbiUUID uuid.UUID
@@ -49,8 +50,8 @@ func bootstrapUnitTest() {
 	}
 	lis = bufconn.Listen(bufSize)
 	s := grpc.NewServer()
-	pndStore = nucleus.NewPndStore()
-	sbiStore = nucleus.NewSbiStore()
+	pndStore = store.NewPndStore()
+	sbiStore = store.NewSbiStore()
 
 	changeUUID, err := uuid.Parse(changeID)
 	if err != nil {
diff --git a/controller.go b/controller.go
index a4c1b4f77ab098a7d1377a2233765dd03a4a2632..a9bfa2493040ddb4f4b06fbe84e33ebdad308903 100644
--- a/controller.go
+++ b/controller.go
@@ -20,6 +20,7 @@ import (
 	spb "code.fbi.h-da.de/danet/api/go/gosdn/southbound"
 	"code.fbi.h-da.de/danet/gosdn/interfaces/southbound"
 	nbi "code.fbi.h-da.de/danet/gosdn/northbound/server"
+	"code.fbi.h-da.de/danet/gosdn/store"
 
 	"code.fbi.h-da.de/danet/gosdn/nucleus"
 )
@@ -29,7 +30,7 @@ var coreOnce sync.Once
 
 // Core is the representation of the controller's core
 type Core struct {
-	pndc       *nucleus.PndStore
+	pndc       *store.PndStore
 	httpServer *http.Server
 	grpcServer *grpc.Server
 	nbi        *nbi.NorthboundInterface
@@ -42,7 +43,7 @@ var c *Core
 
 func init() {
 	c = &Core{
-		pndc:     nucleus.NewPndStore(),
+		pndc:     store.NewPndStore(),
 		stopChan: make(chan os.Signal, 1),
 	}
 
@@ -141,7 +142,7 @@ func shutdown() error {
 	return stopHttpServer()
 }
 
-func callback(id uuid.UUID, ch chan nucleus.DeviceDetails) {
+func callback(id uuid.UUID, ch chan store.DeviceDetails) {
 	if ch != nil {
 		c.pndc.AddPendingChannel(id, ch)
 		log.Infof("pending channel %v added", id)
diff --git a/northbound/server/csbi.go b/northbound/server/csbi.go
index 975e3ea225fa6c9c699ac7664a64b050b40d0b9d..00f0fa47bbc0acf7f4fb826ff1794d5c57b829a0 100644
--- a/northbound/server/csbi.go
+++ b/northbound/server/csbi.go
@@ -7,7 +7,7 @@ import (
 	log "github.com/sirupsen/logrus"
 
 	cpb "code.fbi.h-da.de/danet/api/go/gosdn/csbi"
-	"code.fbi.h-da.de/danet/gosdn/nucleus"
+	"code.fbi.h-da.de/danet/gosdn/store"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
 )
@@ -17,12 +17,12 @@ type csbi struct {
 }
 
 func (s csbi) Hello(ctx context.Context, syn *cpb.Syn) (*cpb.Ack, error) {
-	ch, err := pndc.PendingChannels(nucleus.FromString(syn.Id))
+	ch, err := pndc.PendingChannels(store.FromString(syn.Id))
 	if err != nil {
 		log.Error(err)
 		return nil, status.Errorf(codes.Aborted, "pending channel %v", err)
 	}
-	ch <- nucleus.DeviceDetails{
+	ch <- store.DeviceDetails{
 		ID:      syn.Id,
 		Address: syn.Address,
 	}
diff --git a/northbound/server/nbi.go b/northbound/server/nbi.go
index e99888d64cf7bd7dc74dc3e2109711544d0b89fb..e110d68bcabcb099756ac219a021c6e35ec5f45f 100644
--- a/northbound/server/nbi.go
+++ b/northbound/server/nbi.go
@@ -1,10 +1,10 @@
 package server
 
 import (
-	"code.fbi.h-da.de/danet/gosdn/nucleus"
+	"code.fbi.h-da.de/danet/gosdn/store"
 )
 
-var pndc *nucleus.PndStore
+var pndc *store.PndStore
 
 // NorthboundInterface is the representation of the
 // gRPC services used provided.
@@ -15,7 +15,7 @@ type NorthboundInterface struct {
 }
 
 // NewNBI receives a PndStore and returns a new gRPC *NorthboundInterface
-func NewNBI(pnds *nucleus.PndStore) *NorthboundInterface {
+func NewNBI(pnds *store.PndStore) *NorthboundInterface {
 	pndc = pnds
 	return &NorthboundInterface{
 		Pnd:  &pndServer{},
diff --git a/northbound/server/pnd.go b/northbound/server/pnd.go
index 46f4505e5ceefab4c9df7730d40f713e3435cca4..3e06a57809cf9f0306d8b54372fb665d1aae4db3 100644
--- a/northbound/server/pnd.go
+++ b/northbound/server/pnd.go
@@ -11,7 +11,6 @@ import (
 	ppb "code.fbi.h-da.de/danet/api/go/gosdn/pnd"
 	spb "code.fbi.h-da.de/danet/api/go/gosdn/southbound"
 	"code.fbi.h-da.de/danet/gosdn/interfaces/networkdomain"
-	"code.fbi.h-da.de/danet/gosdn/nucleus"
 	"code.fbi.h-da.de/danet/gosdn/nucleus/errors"
 	"github.com/google/uuid"
 	"github.com/openconfig/ygot/ygot"
@@ -174,7 +173,7 @@ func handleGetPath(pid uuid.UUID, req *ppb.GetRequest_Path) (*ppb.GetResponse, e
 func fillSbis(pnd networkdomain.NetworkDomain, all bool, sid ...string) ([]*spb.SouthboundInterface, error) {
 	var sbiList []uuid.UUID
 
-	sbiStore := pnd.GetSBIs().(*nucleus.SbiStore)
+	sbiStore := pnd.GetSBIs()
 	switch all {
 	case true:
 		sbiList = sbiStore.UUIDs()
@@ -194,14 +193,13 @@ func fillSbis(pnd networkdomain.NetworkDomain, all bool, sid ...string) ([]*spb.
 	}
 	sbis := make([]*spb.SouthboundInterface, len(sbiList))
 	for i, id := range sbiList {
-		sbi, err := sbiStore.GetSBI(id)
+		_, err := sbiStore.Get(id)
 		if err != nil {
 			log.Error(err)
 			return nil, status.Errorf(codes.Aborted, "%v", err)
 		}
 		sbis[i] = &spb.SouthboundInterface{
-			Id:   id.String(),
-			Type: sbi.Type(),
+			Id: id.String(),
 		}
 	}
 	return sbis, nil
diff --git a/northbound/server/pnd_test.go b/northbound/server/pnd_test.go
index 541f29260cccfe81b6c4c4786da5c0e1e5322af5..8fa00231d05a455079263b8d9ff8d60213621cb2 100644
--- a/northbound/server/pnd_test.go
+++ b/northbound/server/pnd_test.go
@@ -13,6 +13,7 @@ import (
 	"code.fbi.h-da.de/danet/gosdn/interfaces/device"
 	"code.fbi.h-da.de/danet/gosdn/mocks"
 	"code.fbi.h-da.de/danet/gosdn/nucleus"
+	"code.fbi.h-da.de/danet/gosdn/store"
 	"code.fbi.h-da.de/danet/yang-models/generated/openconfig"
 	"github.com/google/uuid"
 	log "github.com/sirupsen/logrus"
@@ -32,7 +33,7 @@ var committedChangeUUID uuid.UUID
 var deviceUUID uuid.UUID
 var mockPnd *mocks.NetworkDomain
 var mockDevice device.Device
-var sbiStore *nucleus.SbiStore
+var sbiStore *store.SbiStore
 
 func TestMain(m *testing.M) {
 	log.SetReportCaller(true)
@@ -71,7 +72,7 @@ func TestMain(m *testing.M) {
 	mockDevice.(*nucleus.CommonDevice).SetSBI(nucleus.NewSBI(spb.Type_OPENCONFIG))
 	mockDevice.(*nucleus.CommonDevice).SetTransport(&mocks.Transport{})
 	mockDevice.(*nucleus.CommonDevice).SetName(hostname)
-	sbiStore = nucleus.NewSbiStore()
+	sbiStore = store.NewSbiStore()
 	if err := sbiStore.Add(mockDevice.SBI()); err != nil {
 		log.Fatal(err)
 	}
@@ -95,7 +96,7 @@ func TestMain(m *testing.M) {
 	mockPnd.On("Confirm", mock.Anything).Return(nil)
 	mockPnd.On("ChangeOND", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(uuid.Nil, nil)
 
-	pndc = nucleus.NewPndStore()
+	pndc = store.NewPndStore()
 	if err := pndc.Add(mockPnd); err != nil {
 		log.Fatal(err)
 	}
diff --git a/nucleus/initialise_test.go b/nucleus/initialise_test.go
index 093d08b716ddb974d2e4e96c635b58fda07a8afc..36c205ac052a1f20ca06580c63a4f933d0cf73e0 100644
--- a/nucleus/initialise_test.go
+++ b/nucleus/initialise_test.go
@@ -6,6 +6,7 @@ import (
 	"testing"
 
 	"code.fbi.h-da.de/danet/gosdn/interfaces/device"
+	"code.fbi.h-da.de/danet/gosdn/store"
 
 	tpb "code.fbi.h-da.de/danet/api/go/gosdn/transport"
 
@@ -151,9 +152,9 @@ func newPnd() pndImplementation {
 	return pndImplementation{
 		name:        "default",
 		description: "default test pnd",
-		sbic:        SbiStore{genericStore{}},
-		devices:     NewDeviceStore(),
-		changes:     ChangeStore{genericStore{}},
+		sbic:        store.NewSbiStore(),
+		devices:     store.NewDeviceStore(),
+		changes:     store.NewChangeStore(),
 		id:          defaultPndID,
 	}
 }
diff --git a/nucleus/principalNetworkDomain.go b/nucleus/principalNetworkDomain.go
index b01b663f6a9d041792664f4d2955182fb91a0f6f..b0238a095dfb2766e9712b7974614229f560a314 100644
--- a/nucleus/principalNetworkDomain.go
+++ b/nucleus/principalNetworkDomain.go
@@ -17,9 +17,11 @@ import (
 	"code.fbi.h-da.de/danet/gosdn/interfaces/device"
 	"code.fbi.h-da.de/danet/gosdn/interfaces/networkdomain"
 	"code.fbi.h-da.de/danet/gosdn/interfaces/southbound"
-	"code.fbi.h-da.de/danet/gosdn/interfaces/store"
+	si "code.fbi.h-da.de/danet/gosdn/interfaces/store"
 	"code.fbi.h-da.de/danet/gosdn/nucleus/errors"
 
+	"code.fbi.h-da.de/danet/gosdn/store"
+
 	"github.com/google/uuid"
 	"github.com/openconfig/ygot/ygot"
 	"github.com/openconfig/ygot/ytypes"
@@ -27,18 +29,19 @@ import (
 )
 
 // NewPND creates a Principle Network Domain
-func NewPND(name, description string, id uuid.UUID, sbi southbound.SouthboundInterface, c cpb.CsbiClient, callback func(uuid.UUID, chan DeviceDetails)) (networkdomain.NetworkDomain, error) {
+func NewPND(name, description string, id uuid.UUID, sbi southbound.SouthboundInterface, c cpb.CsbiClient, callback func(uuid.UUID, chan store.DeviceDetails)) (networkdomain.NetworkDomain, error) {
 	pnd := &pndImplementation{
 		name:        name,
 		description: description,
-		sbic:        SbiStore{genericStore{}},
-		devices:     NewDeviceStore(),
-		changes:     ChangeStore{genericStore{}},
+		sbic:        store.NewSbiStore(),
+		devices:     store.NewDeviceStore(),
+		changes:     store.NewChangeStore(),
 		id:          id,
 
 		csbiClient: c,
 		callback:   callback,
 	}
+
 	if err := pnd.sbic.Add(sbi); err != nil {
 		return nil, err
 	}
@@ -48,13 +51,13 @@ func NewPND(name, description string, id uuid.UUID, sbi southbound.SouthboundInt
 type pndImplementation struct {
 	name        string
 	description string
-	sbic        SbiStore
-	devices     *DeviceStore
-	changes     ChangeStore
+	sbic        *store.SbiStore
+	devices     *store.DeviceStore
+	changes     *store.ChangeStore
 	id          uuid.UUID
 
 	csbiClient cpb.CsbiClient
-	callback   func(uuid.UUID, chan DeviceDetails)
+	callback   func(uuid.UUID, chan store.DeviceDetails)
 }
 
 func (pnd *pndImplementation) PendingChanges() []uuid.UUID {
@@ -113,8 +116,8 @@ func (pnd *pndImplementation) GetDescription() string {
 }
 
 // GetSBIs returns the registered SBIs
-func (pnd *pndImplementation) GetSBIs() store.Store {
-	return &pnd.sbic
+func (pnd *pndImplementation) GetSBIs() si.Store {
+	return pnd.sbic
 }
 
 // Destroy destroys the PND
@@ -154,7 +157,7 @@ func (pnd *pndImplementation) AddDevice(name string, opt *tpb.TransportOption, s
 }
 
 func (pnd *pndImplementation) GetDevice(identifier string) (device.Device, error) {
-	d, err := pnd.devices.GetDevice(FromString(identifier))
+	d, err := pnd.devices.GetDevice(store.FromString(identifier))
 	if err != nil {
 		return nil, err
 	}
@@ -211,7 +214,7 @@ func (pnd *pndImplementation) removeDevice(id uuid.UUID) error {
 }
 
 func (pnd *pndImplementation) MarshalDevice(identifier string) (string, error) {
-	foundDevice, err := pnd.devices.GetDevice(FromString(identifier))
+	foundDevice, err := pnd.devices.GetDevice(store.FromString(identifier))
 	if err != nil {
 		return "", err
 	}
@@ -231,7 +234,7 @@ func (pnd *pndImplementation) MarshalDevice(identifier string) (string, error) {
 
 // Request sends a get request to a specific device
 func (pnd *pndImplementation) Request(uuid uuid.UUID, path string) (proto.Message, error) {
-	d, err := pnd.devices.GetDevice(FromString(uuid.String()))
+	d, err := pnd.devices.GetDevice(store.FromString(uuid.String()))
 	if err != nil {
 		return nil, err
 	}
@@ -360,13 +363,6 @@ func (pnd *pndImplementation) handleCsbiEnrolment(name string, opt *tpb.Transpor
 	return nil
 }
 
-// DeviceDetails contains details of a device used by the cSBI mechanism
-type DeviceDetails struct {
-	ID              string
-	Address         string
-	TransportOption *tpb.TransportOption
-}
-
 func (pnd *pndImplementation) createCsbiDevice(name string, d *cpb.Deployment, opt *tpb.TransportOption) error {
 	defer func() {
 		if r := recover(); r != nil {
@@ -377,7 +373,7 @@ func (pnd *pndImplementation) createCsbiDevice(name string, d *cpb.Deployment, o
 	if err != nil {
 		return err
 	}
-	ch := make(chan DeviceDetails, 1)
+	ch := make(chan store.DeviceDetails, 1)
 	pnd.callback(id, ch)
 	go func() {
 		deviceDetails := <-ch
@@ -393,7 +389,7 @@ func (pnd *pndImplementation) createCsbiDevice(name string, d *cpb.Deployment, o
 			panic(err)
 		}
 		d.(*CsbiDevice).UUID = id
-		ch <- DeviceDetails{TransportOption: opt}
+		ch <- store.DeviceDetails{TransportOption: opt}
 		if err := pnd.devices.Add(d, d.Name()); err != nil {
 			panic(err)
 		}
diff --git a/nucleus/principalNetworkDomain_test.go b/nucleus/principalNetworkDomain_test.go
index 2c01bf1b917a53e7cf13492a7a03c90e5cb37154..d14fd7f76b3a18f26e0d6134401ac47512768b6d 100644
--- a/nucleus/principalNetworkDomain_test.go
+++ b/nucleus/principalNetworkDomain_test.go
@@ -12,6 +12,7 @@ import (
 	"code.fbi.h-da.de/danet/gosdn/interfaces/networkdomain"
 	"code.fbi.h-da.de/danet/gosdn/interfaces/southbound"
 	"code.fbi.h-da.de/danet/gosdn/mocks"
+	"code.fbi.h-da.de/danet/gosdn/store"
 	"code.fbi.h-da.de/danet/yang-models/generated/openconfig"
 	"github.com/google/uuid"
 	gpb "github.com/openconfig/gnmi/proto/gnmi"
@@ -110,7 +111,7 @@ func Test_pndImplementation_AddDevice(t *testing.T) {
 				t.Error(err)
 			}
 			if tt.name == "already exists" {
-				pnd.devices.genericStore[did] = tt.args.device.(device.Device)
+				pnd.devices.Store[did] = tt.args.device.(device.Device)
 			}
 			err := pnd.AddDevice(tt.args.name, tt.args.opts, defaultSbiID)
 			if (err != nil) != tt.wantErr {
@@ -118,7 +119,7 @@ func Test_pndImplementation_AddDevice(t *testing.T) {
 			}
 			if tt.name != "fails wrong type" {
 				if err == nil {
-					d, err := pnd.devices.GetDevice(FromString(tt.args.name))
+					d, err := pnd.devices.GetDevice(store.FromString(tt.args.name))
 					if err != nil {
 						t.Errorf("AddDevice() error = %v", err)
 						return
@@ -135,6 +136,7 @@ func Test_pndImplementation_AddDevice(t *testing.T) {
 	}
 }
 
+// TODO: refactor test to use store interface instead if direct access.
 func Test_pndImplementation_AddSbi(t *testing.T) {
 	type args struct {
 		sbi southbound.SouthboundInterface
@@ -167,7 +169,7 @@ func Test_pndImplementation_AddSbi(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			pnd := newPnd()
 			if tt.name == "already exists" {
-				pnd.sbic.genericStore[defaultSbiID] = tt.args.sbi
+				pnd.sbic.Store[defaultSbiID] = tt.args.sbi
 			}
 			err := pnd.AddSbi(tt.args.sbi)
 			if (err != nil) != tt.wantErr {
@@ -175,7 +177,7 @@ func Test_pndImplementation_AddSbi(t *testing.T) {
 			}
 			if tt.name != "fails wrong type" {
 				if err == nil {
-					_, ok := pnd.sbic.genericStore[defaultSbiID]
+					_, ok := pnd.sbic.Store[defaultSbiID]
 					if !ok {
 						t.Errorf("AddSbi() SBI %v not in device store %v",
 							tt.args.sbi, pnd.GetSBIs())
@@ -234,8 +236,8 @@ func Test_pndImplementation_Destroy(t *testing.T) {
 	type fields struct {
 		name        string
 		description string
-		sbi         SbiStore
-		devices     *DeviceStore
+		sbi         *store.SbiStore
+		devices     *store.DeviceStore
 	}
 	tests := []struct {
 		name    string
@@ -297,9 +299,9 @@ func Test_pndImplementation_GetSBIs(t *testing.T) {
 	pnd := newPnd()
 	tests := []struct {
 		name string
-		want *SbiStore
+		want *store.SbiStore
 	}{
-		{name: "default", want: &pnd.sbic},
+		{name: "default", want: pnd.sbic},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
@@ -404,8 +406,8 @@ func Test_pndImplementation_RemoveSbi(t *testing.T) {
 			pnd := &pndImplementation{
 				name:        "test-remove-sbi",
 				description: "test-remove-sbi",
-				sbic:        SbiStore{genericStore{}},
-				devices:     NewDeviceStore(),
+				sbic:        store.NewSbiStore(),
+				devices:     store.NewDeviceStore(),
 				id:          defaultPndID,
 			}
 			if tt.name != "fails empty" {
@@ -624,7 +626,7 @@ func Test_pndImplementation_ChangeOND(t *testing.T) {
 				return
 			}
 
-			did, ok := pnd.devices.deviceNameToUUIDLookup["testdevice"]
+			did, ok := pnd.devices.DeviceNameToUUIDLookup["testdevice"]
 			if !ok {
 				err := errors.New("error fetching device")
 				t.Error(err)
@@ -637,8 +639,8 @@ func Test_pndImplementation_ChangeOND(t *testing.T) {
 				return
 			}
 			if !tt.wantErr {
-				if len(pnd.changes.genericStore) != 1 {
-					t.Errorf("ChangeOND() unexpected change count. got %v, want 1", len(pnd.changes.genericStore))
+				if len(pnd.changes.Store) != 1 {
+					t.Errorf("ChangeOND() unexpected change count. got %v, want 1", len(pnd.changes.Store))
 				}
 			}
 		})
@@ -797,7 +799,7 @@ func Test_pndImplementation_PendingChanges(t *testing.T) {
 		return nil
 	}
 
-	store := NewChangeStore()
+	store := store.NewChangeStore()
 	pending := NewChange(did, &openconfig.Device{}, &openconfig.Device{}, callback)
 	if err := store.Add(pending); err != nil {
 		t.Error(err)
@@ -815,7 +817,7 @@ func Test_pndImplementation_PendingChanges(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			pnd := newPnd()
-			pnd.changes = *store
+			pnd.changes = store
 			if got := pnd.PendingChanges(); !reflect.DeepEqual(got, tt.want) {
 				t.Errorf("pndImplementation.PendingChanges() = %v, want %v", got, tt.want)
 			}
@@ -830,7 +832,7 @@ func Test_pndImplementation_CommittedChanges(t *testing.T) {
 		return nil
 	}
 
-	store := NewChangeStore()
+	store := store.NewChangeStore()
 	committed := NewChange(did, &openconfig.Device{}, &openconfig.Device{}, callback)
 	if err := committed.Commit(); err != nil {
 		t.Error(err)
@@ -852,7 +854,7 @@ func Test_pndImplementation_CommittedChanges(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			pnd := newPnd()
-			pnd.changes = *store
+			pnd.changes = store
 			if got := pnd.CommittedChanges(); !reflect.DeepEqual(got, tt.want) {
 				t.Errorf("pndImplementation.CommittedChanges() = %v, want %v", got, tt.want)
 			}
@@ -866,7 +868,7 @@ func Test_pndImplementation_ConfirmedChanges(t *testing.T) {
 		log.Infof("callback in test %v", testName)
 		return nil
 	}
-	store := NewChangeStore()
+	store := store.NewChangeStore()
 	confirmed := NewChange(did, &openconfig.Device{}, &openconfig.Device{}, callback)
 	if err := confirmed.Commit(); err != nil {
 		t.Error(err)
@@ -892,7 +894,7 @@ func Test_pndImplementation_ConfirmedChanges(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			pnd := newPnd()
-			pnd.changes = *store
+			pnd.changes = store
 			if got := pnd.ConfirmedChanges(); !reflect.DeepEqual(got, tt.want) {
 				t.Errorf("pndImplementation.ConfirmedChanges() = %v, want %v", got, tt.want)
 			}
diff --git a/nucleus/store.go b/nucleus/store.go
deleted file mode 100644
index 1d37668d72ca9e080609c3d840d2efc1150bbda5..0000000000000000000000000000000000000000
--- a/nucleus/store.go
+++ /dev/null
@@ -1,345 +0,0 @@
-package nucleus
-
-import (
-	"fmt"
-	"reflect"
-	"sync"
-
-	ppb "code.fbi.h-da.de/danet/api/go/gosdn/pnd"
-
-	"code.fbi.h-da.de/danet/gosdn/interfaces/device"
-	"code.fbi.h-da.de/danet/gosdn/interfaces/networkdomain"
-	"code.fbi.h-da.de/danet/gosdn/interfaces/southbound"
-	"code.fbi.h-da.de/danet/gosdn/interfaces/store"
-	"code.fbi.h-da.de/danet/gosdn/nucleus/errors"
-
-	"github.com/google/uuid"
-	log "github.com/sirupsen/logrus"
-)
-
-var storeLock sync.RWMutex
-
-// NewStore returns a generic Store
-func NewStore() store.Store {
-	return genericStore{}
-}
-
-// NewPndStore returns a PndStore
-func NewPndStore() *PndStore {
-	return &PndStore{
-		genericStore:    genericStore{},
-		pendingChannels: make(map[uuid.UUID]chan DeviceDetails, 0),
-	}
-}
-
-// NewSbiStore returns a SbiStore
-func NewSbiStore() *SbiStore {
-	return &SbiStore{genericStore{}}
-}
-
-// NewDeviceStore returns a DeviceStore
-func NewDeviceStore() *DeviceStore {
-	return &DeviceStore{genericStore: genericStore{}, deviceNameToUUIDLookup: make(map[string]uuid.UUID)}
-}
-
-// NewChangeStore returns a ChangeStore
-func NewChangeStore() *ChangeStore {
-	return &ChangeStore{genericStore{}}
-}
-
-type genericStore map[uuid.UUID]store.Storable
-
-// Exists takes a Storable's UUID and checks its existence in the store.
-func (s genericStore) Exists(id uuid.UUID) bool {
-	storeLock.RLock()
-	defer storeLock.RUnlock()
-	_, ok := s[id]
-	return ok
-}
-
-// Add adds a Storable to the Store
-func (s genericStore) Add(item store.Storable) error {
-	if s.Exists(item.ID()) {
-		return &errors.ErrAlreadyExists{Item: item}
-	}
-	storeLock.Lock()
-	s[item.ID()] = item
-	storeLock.Unlock()
-	log.WithFields(log.Fields{
-		"type": reflect.TypeOf(item),
-		"uuid": item.ID(),
-	}).Debug("storable was added")
-	return nil
-}
-
-// Get takes a Storable's UUID and returns the Storable. If the requested
-// Storable does not exist an error is returned. Get is only type safe for
-// this Storable interface. For type safe get operations on specialised stores
-// use GetDevice, GetPND, GetSBI, or GetChange respectively.
-func (s genericStore) Get(id uuid.UUID) (store.Storable, error) {
-	if !s.Exists(id) {
-		return nil, &errors.ErrNotFound{ID: id}
-	}
-	storeLock.RLock()
-	defer storeLock.RUnlock()
-	return s[id], nil
-}
-
-// Delete takes a Storable's UUID and deletes it. If the specified UUID does not
-// exist in the Store an error is returned.
-func (s genericStore) Delete(id uuid.UUID) error {
-	if !s.Exists(id) {
-		return &errors.ErrNotFound{ID: id}
-	}
-	storeLock.Lock()
-	delete(s, id)
-	storeLock.Unlock()
-	log.WithFields(log.Fields{
-		"uuid": id,
-	}).Debug("storable was deleted")
-	return nil
-}
-
-// UUIDs returns all UUIDs in the store.
-func (s genericStore) UUIDs() []uuid.UUID {
-	storeLock.RLock()
-	defer storeLock.RUnlock()
-	keys := make([]uuid.UUID, len(s))
-	i := 0
-	for k := range s {
-		keys[i] = k
-		i++
-	}
-	return keys
-}
-
-// SbiStore is used to store SouthboundInterfaces
-type SbiStore struct {
-	genericStore
-}
-
-// GetSBI takes a SouthboundInterface's UUID and returns the SouthboundInterface. If the requested
-// SouthboundInterface does not exist an error is returned.
-func (s SbiStore) GetSBI(id uuid.UUID) (southbound.SouthboundInterface, error) {
-	item, err := s.genericStore.Get(id)
-	if err != nil {
-		return nil, err
-	}
-	sbi, ok := item.(southbound.SouthboundInterface)
-	if !ok {
-		return nil, &errors.ErrInvalidTypeAssertion{
-			Value: sbi,
-			Type:  "SouthboundInterface",
-		}
-	}
-	log.WithFields(log.Fields{
-		"uuid": id,
-	}).Debug("southbound interface was accessed")
-	return sbi, nil
-}
-
-// PndStore is used to store PrincipalNetworkDomains
-type PndStore struct {
-	genericStore
-	pendingChannels map[uuid.UUID]chan DeviceDetails
-}
-
-// GetPND takes a PrincipalNetworkDomain's UUID and returns the PrincipalNetworkDomain. If the requested
-// PrincipalNetworkDomain does not exist an error is returned.
-func (s PndStore) GetPND(id uuid.UUID) (networkdomain.NetworkDomain, error) {
-	item, err := s.genericStore.Get(id)
-	if err != nil {
-		return nil, err
-	}
-	pnd, ok := item.(networkdomain.NetworkDomain)
-	if !ok {
-		return nil, &errors.ErrInvalidTypeAssertion{
-			Value: pnd,
-			Type:  "PrincipalNetworkDomain",
-		}
-	}
-	log.WithFields(log.Fields{
-		"uuid": id,
-	}).Debug("principal network domain was accessed")
-	return pnd, nil
-}
-
-// PendingChannels holds channels used communicate with pending
-// cSBI deployments
-func (s PndStore) PendingChannels(id uuid.UUID, parseErrors ...error) (chan DeviceDetails, error) {
-	ch, ok := s.pendingChannels[id]
-	if !ok {
-		return nil, &errors.ErrNotFound{ID: id}
-	}
-	return ch, nil
-}
-
-// AddPendingChannel adds a pending channel to the map
-func (s PndStore) AddPendingChannel(id uuid.UUID, ch chan DeviceDetails) {
-	s.pendingChannels[id] = ch
-}
-
-// RemovePendingChannel removes a pending channel from the map
-func (s PndStore) RemovePendingChannel(id uuid.UUID) {
-	delete(s.pendingChannels, id)
-}
-
-// DeviceStore is used to store Devices
-type DeviceStore struct {
-	deviceNameToUUIDLookup map[string]uuid.UUID
-	genericStore
-}
-
-// GetDevice takes a Device's UUID and returns the Device. If the requested
-// Device does not exist an error is returned.
-func (s DeviceStore) GetDevice(id uuid.UUID, parseErrors ...error) (device.Device, error) {
-	var foundID uuid.UUID
-
-	foundID = id
-
-	for _, parseErrs := range parseErrors {
-		if parseErrs != nil {
-			switch e := parseErrs.(type) {
-			case *errors.ErrInvalidUUID:
-				myID, ok := s.deviceNameToUUIDLookup[e.DeviceName]
-				if !ok {
-					log.Debug(fmt.Sprintf("no device named %s found", foundID))
-					return nil, &errors.ErrNotFound{}
-				}
-
-				foundID = myID
-			}
-		}
-	}
-
-	item, err := s.genericStore.Get(foundID)
-	if err != nil {
-		return nil, err
-	}
-	d, ok := item.(device.Device)
-	if !ok {
-		return nil, &errors.ErrInvalidTypeAssertion{
-			Value: d,
-			Type:  reflect.TypeOf((device.Device)(nil)),
-		}
-	}
-	log.WithFields(log.Fields{
-		"uuid": foundID,
-		"name": d.Name(),
-	}).Debug("device was accessed")
-
-	return d, nil
-}
-
-// FromString is a helper to check if a provided string as a valid UUID or a name.
-func FromString(id string) (uuid.UUID, error) {
-	idAsUUID, err := uuid.Parse(id)
-
-	// id is no UUID therefore it could be a device name.
-	// The name will be returned within the error.
-	if err != nil {
-		log.WithFields(log.Fields{
-			"identifier": id,
-		}).Debug(err)
-		return uuid.Nil, &errors.ErrInvalidUUID{DeviceName: id}
-	}
-
-	return idAsUUID, nil
-}
-
-// Add adds a device to the device store.
-// It also adds the name of the device to the lookup table.
-func (s DeviceStore) Add(item store.Storable, name string) error {
-	if s.Exists(item.ID()) {
-		return &errors.ErrAlreadyExists{Item: item}
-	}
-
-	s.deviceNameToUUIDLookup[name] = item.ID()
-
-	storeLock.Lock()
-	s.genericStore[item.ID()] = item
-	storeLock.Unlock()
-
-	log.WithFields(log.Fields{
-		"type": reflect.TypeOf(item),
-		"uuid": item.ID(),
-	}).Debug("storable was added")
-
-	return nil
-}
-
-// Delete deletes a device from the device store.
-func (s DeviceStore) Delete(id uuid.UUID) error {
-	if !s.Exists(id) {
-		return &errors.ErrNotFound{ID: id}
-	}
-
-	storeLock.Lock()
-	delete(s.genericStore, id)
-	storeLock.Unlock()
-
-	for key, value := range s.deviceNameToUUIDLookup {
-		if value == id {
-			delete(s.deviceNameToUUIDLookup, key)
-		}
-	}
-
-	log.WithFields(log.Fields{
-		"uuid": id,
-	}).Debug("storable was deleted")
-
-	return nil
-}
-
-// ChangeStore is used to store Changes
-type ChangeStore struct {
-	genericStore
-}
-
-// GetChange takes a Change's UUID and returns the Change. If the requested
-// Change does not exist an error is returned.
-func (s ChangeStore) GetChange(id uuid.UUID) (*Change, error) {
-	item, err := s.genericStore.Get(id)
-	if err != nil {
-		return nil, err
-	}
-	change, ok := item.(*Change)
-	if !ok {
-		return nil, &errors.ErrInvalidTypeAssertion{
-			Value: change,
-			Type:  reflect.TypeOf(&Change{}),
-		}
-	}
-	log.WithFields(log.Fields{
-		"uuid": id,
-	}).Debug("change was accessed")
-	return change, nil
-}
-
-// Pending returns the UUIDs of all pending changes
-func (s ChangeStore) Pending() []uuid.UUID {
-	return filterChanges(s, ppb.Change_PENDING)
-}
-
-// Committed returns the UUIDs of all pending changes
-func (s ChangeStore) Committed() []uuid.UUID {
-	return filterChanges(s, ppb.Change_COMMITTED)
-}
-
-// Confirmed returns the UUIDs of all pending changes
-func (s ChangeStore) Confirmed() []uuid.UUID {
-	return filterChanges(s, ppb.Change_CONFIRMED)
-}
-
-func filterChanges(store ChangeStore, state ppb.Change_State) []uuid.UUID {
-	changes := make([]uuid.UUID, 0)
-	for _, ch := range store.genericStore {
-		switch change := ch.(type) {
-		case *Change:
-			if change.State() == state {
-				changes = append(changes, change.cuid)
-			}
-		}
-	}
-	return changes
-}
diff --git a/nucleus/store_test.go b/nucleus/store_test.go
deleted file mode 100644
index bc22db429bdf3b54da943b1ef5a1e66b24069a7d..0000000000000000000000000000000000000000
--- a/nucleus/store_test.go
+++ /dev/null
@@ -1,613 +0,0 @@
-package nucleus
-
-import (
-	"reflect"
-	"sort"
-	"testing"
-
-	ppb "code.fbi.h-da.de/danet/api/go/gosdn/pnd"
-	"code.fbi.h-da.de/danet/yang-models/generated/openconfig"
-
-	"code.fbi.h-da.de/danet/gosdn/interfaces/device"
-	"code.fbi.h-da.de/danet/gosdn/interfaces/networkdomain"
-	"code.fbi.h-da.de/danet/gosdn/interfaces/southbound"
-	"code.fbi.h-da.de/danet/gosdn/interfaces/store"
-
-	"code.fbi.h-da.de/danet/gosdn/mocks"
-	"github.com/google/uuid"
-	"github.com/openconfig/ygot/ygot"
-	log "github.com/sirupsen/logrus"
-)
-
-func Test_Store_add(t *testing.T) {
-	type args struct {
-		item store.Storable
-	}
-	tests := []struct {
-		name    string
-		s       genericStore
-		args    args
-		wantErr bool
-	}{
-		{
-			name: "default",
-			s:    genericStore{},
-			args: args{
-				item: &mocks.Storable{},
-			},
-		},
-		{
-			name: "already exists",
-			s: genericStore{
-				iid: &mocks.Storable{},
-			},
-			args: args{
-				item: &mocks.Storable{},
-			},
-			wantErr: true,
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			tt.args.item.(*mocks.Storable).On("ID").Return(iid)
-			switch tt.name {
-			case "already exixts":
-				_ = tt.s.Add(tt.args.item)
-			default:
-			}
-			if err := tt.s.Add(tt.args.item); (err != nil) != tt.wantErr {
-				t.Errorf("Add() error = %v, wantErr %v", err, tt.wantErr)
-			}
-		})
-	}
-}
-
-func Test_Store_delete(t *testing.T) {
-	type args struct {
-		id uuid.UUID
-	}
-	tests := []struct {
-		name    string
-		s       genericStore
-		args    args
-		wantErr bool
-	}{
-		{
-			name: "default",
-			s: genericStore{
-				iid: &mocks.Storable{},
-			},
-			args:    args{id: iid},
-			wantErr: false,
-		},
-		{
-			name:    "not found empty",
-			s:       genericStore{},
-			args:    args{id: iid},
-			wantErr: true,
-		},
-		{
-			name: "not found",
-			s: genericStore{
-				iid: &mocks.Storable{},
-			},
-			args:    args{id: altIid},
-			wantErr: true,
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			if err := tt.s.Delete(tt.args.id); (err != nil) != tt.wantErr {
-				t.Errorf("delete() error = %v, wantErr %v", err, tt.wantErr)
-			}
-			if tt.name == "default" {
-				item, ok := tt.s[iid]
-				if ok {
-					t.Errorf("delete() item %v still in genericStore %v", item, tt.s)
-				}
-			}
-		})
-	}
-}
-
-func Test_Store_exists(t *testing.T) {
-	type args struct {
-		id uuid.UUID
-	}
-	tests := []struct {
-		name string
-		s    genericStore
-		args args
-		want bool
-	}{
-		{
-			name: "default",
-			s: genericStore{
-				iid: &mocks.Storable{},
-			},
-			args: args{id: iid},
-			want: true,
-		},
-		{
-			name: "not found empty",
-			s:    genericStore{},
-			args: args{id: iid},
-			want: false,
-		},
-		{
-			name: "not found",
-			s: genericStore{
-				iid: &mocks.Storable{},
-			},
-			args: args{id: altIid},
-			want: false,
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			if got := tt.s.Exists(tt.args.id); got != tt.want {
-				t.Errorf("exists() = %v, want %v", got, tt.want)
-			}
-		})
-	}
-}
-
-func Test_Store_get(t *testing.T) {
-	type args struct {
-		id uuid.UUID
-	}
-	tests := []struct {
-		name    string
-		s       genericStore
-		args    args
-		want    store.Storable
-		wantErr bool
-	}{
-		{
-			name: "exists",
-			s: genericStore{
-				iid: &mocks.Storable{},
-			},
-			args:    args{id: iid},
-			want:    &mocks.Storable{},
-			wantErr: false,
-		},
-		{
-			name: "not found",
-			s: genericStore{
-				iid: &mocks.Storable{},
-			},
-			args:    args{id: altIid},
-			want:    nil,
-			wantErr: true,
-		},
-		{
-			name:    "not found empty",
-			s:       genericStore{},
-			args:    args{id: iid},
-			want:    nil,
-			wantErr: true,
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			got, err := tt.s.Get(tt.args.id)
-			if (err != nil) != tt.wantErr {
-				t.Errorf("get() error = %v, wantErr %v", err, tt.wantErr)
-				return
-			}
-			if !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("get() got = %v, want %v", got, tt.want)
-			}
-		})
-	}
-}
-
-func Test_Store_UUIDs(t *testing.T) {
-	tests := []struct {
-		name string
-		s    genericStore
-		want []uuid.UUID
-	}{
-		{
-			name: "default",
-			s: genericStore{
-				iid:    &mocks.Storable{},
-				altIid: &mocks.Storable{},
-			},
-			want: []uuid.UUID{iid, altIid},
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			sort.Slice(tt.want, func(i, j int) bool {
-				return tt.want[i].String() < tt.want[j].String()
-			})
-			got := tt.s.UUIDs()
-			sort.Slice(got, func(i, j int) bool {
-				return got[i].String() < got[j].String()
-			})
-			if !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("UUIDs() = %v, want %v", got, tt.want)
-			}
-		})
-	}
-}
-
-func Test_sbiStore_get(t *testing.T) {
-	type fields struct {
-		genericStore genericStore
-	}
-	type args struct {
-		id uuid.UUID
-	}
-	tests := []struct {
-		name    string
-		fields  fields
-		args    args
-		want    southbound.SouthboundInterface
-		wantErr bool
-	}{
-		{
-			name: "exists",
-			fields: fields{
-				genericStore: genericStore{
-					defaultSbiID: &OpenConfig{id: defaultSbiID},
-				},
-			},
-			args:    args{id: defaultSbiID},
-			want:    &OpenConfig{id: defaultSbiID},
-			wantErr: false,
-		},
-		{
-			name: "fails",
-			fields: fields{
-				genericStore: genericStore{
-					defaultSbiID: &OpenConfig{id: defaultSbiID},
-				},
-			},
-			args:    args{id: iid},
-			wantErr: true,
-		},
-		{
-			name: "fails empty",
-			fields: fields{
-				genericStore: genericStore{},
-			},
-			args:    args{id: defaultSbiID},
-			wantErr: true,
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			s := SbiStore{
-				genericStore: tt.fields.genericStore,
-			}
-			got, err := s.Get(tt.args.id)
-			if (err != nil) != tt.wantErr {
-				t.Errorf("get() error = %v, wantErr %v", err, tt.wantErr)
-				return
-			}
-			if !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("get() got = %v, want %v", got, tt.want)
-			}
-		})
-	}
-}
-
-func Test_pndStore_get(t *testing.T) {
-	type fields struct {
-		genericStore genericStore
-	}
-	type args struct {
-		id uuid.UUID
-	}
-	tests := []struct {
-		name    string
-		fields  fields
-		args    args
-		want    networkdomain.NetworkDomain
-		wantErr bool
-	}{
-		{
-			name: "exists",
-			fields: fields{
-				genericStore: genericStore{
-					defaultPndID: &pndImplementation{id: defaultPndID},
-				},
-			},
-			args:    args{id: defaultPndID},
-			want:    &pndImplementation{id: defaultPndID},
-			wantErr: false,
-		},
-		{
-			name: "fails",
-			fields: fields{
-				genericStore: genericStore{
-					defaultPndID: &pndImplementation{id: defaultPndID},
-				},
-			},
-			args:    args{id: iid},
-			wantErr: true,
-		},
-		{
-			name: "fails empty",
-			fields: fields{
-				genericStore: genericStore{},
-			},
-			args:    args{id: defaultPndID},
-			wantErr: true,
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			s := PndStore{
-				genericStore: tt.fields.genericStore,
-			}
-			got, err := s.Get(tt.args.id)
-			if (err != nil) != tt.wantErr {
-				t.Errorf("get() error = %v, wantErr %v", err, tt.wantErr)
-				return
-			}
-			if !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("get() got = %v, want %v", got, tt.want)
-			}
-		})
-	}
-}
-
-func Test_deviceStore_get(t *testing.T) {
-	type fields struct {
-		genericStore genericStore
-	}
-	type args struct {
-		id uuid.UUID
-	}
-	tests := []struct {
-		name    string
-		fields  fields
-		args    args
-		want    device.Device
-		wantErr bool
-	}{
-		{
-			name: "exists",
-			fields: fields{
-				genericStore: genericStore{
-					defaultPndID: &CommonDevice{UUID: did}}},
-			args: args{id: defaultPndID},
-			want: &CommonDevice{
-				UUID: did,
-			},
-			wantErr: false,
-		},
-		{
-			name: "fails",
-			fields: fields{
-				genericStore: genericStore{
-					defaultPndID: &CommonDevice{UUID: did}}},
-			args:    args{id: iid},
-			wantErr: true,
-		},
-		{
-			name: "fails empty",
-			fields: fields{
-				genericStore: genericStore{},
-			},
-			args:    args{id: defaultPndID},
-			wantErr: true,
-		},
-		{
-			name: "fails wrong type",
-			fields: fields{
-				genericStore: genericStore{
-					defaultPndID: &pndImplementation{id: defaultPndID}}},
-			args:    args{id: defaultPndID},
-			wantErr: true,
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			s := DeviceStore{
-				genericStore:           tt.fields.genericStore,
-				deviceNameToUUIDLookup: make(map[string]uuid.UUID),
-			}
-
-			got, err := s.GetDevice(FromString(tt.args.id.String()))
-			if (err != nil) != tt.wantErr {
-				t.Errorf("get() error = %v, wantErr %v", err, tt.wantErr)
-				return
-			}
-			if !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("get() got = %v, want %v", got, tt.want)
-			}
-		})
-	}
-}
-
-func TestChangeStore_Pending(t *testing.T) {
-	testName := t.Name()
-	callback := func(first ygot.GoStruct, second ygot.GoStruct) error {
-		log.Infof("callback in test %v", testName)
-		return nil
-	}
-
-	store := NewChangeStore()
-	pending := NewChange(did, &openconfig.Device{}, &openconfig.Device{}, callback)
-	if err := store.Add(pending); err != nil {
-		t.Error(err)
-		return
-	}
-	tests := []struct {
-		name string
-		want []uuid.UUID
-	}{
-		{
-			name: "default",
-			want: []uuid.UUID{pending.cuid},
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			s := store
-			if got := s.Pending(); !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("Pending() = %v, want %v", got, tt.want)
-			}
-		})
-	}
-}
-
-func TestChangeStore_Committed(t *testing.T) {
-	testName := t.Name()
-	callback := func(first ygot.GoStruct, second ygot.GoStruct) error {
-		log.Infof("callback in test %v", testName)
-		return nil
-	}
-
-	store := NewChangeStore()
-	committed := NewChange(did, &openconfig.Device{}, &openconfig.Device{}, callback)
-	if err := committed.Commit(); err != nil {
-		t.Error(err)
-		return
-	}
-	if err := store.Add(committed); err != nil {
-		t.Error(err)
-		return
-	}
-	tests := []struct {
-		name string
-		want []uuid.UUID
-	}{
-		{
-			name: "default",
-			want: []uuid.UUID{committed.cuid},
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			s := store
-			if got := s.Committed(); !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("Committed() = %v, want %v", got, tt.want)
-			}
-		})
-	}
-}
-
-func TestChangeStore_Confirmed(t *testing.T) {
-	testName := t.Name()
-	callback := func(first ygot.GoStruct, second ygot.GoStruct) error {
-		log.Infof("callback in test %v", testName)
-		return nil
-	}
-
-	store := NewChangeStore()
-	confirmed := NewChange(did, &openconfig.Device{}, &openconfig.Device{}, callback)
-	if err := confirmed.Commit(); err != nil {
-		t.Error(err)
-		return
-	}
-	if err := confirmed.Confirm(); err != nil {
-		t.Error(err)
-		return
-	}
-	if err := store.Add(confirmed); err != nil {
-		t.Error(err)
-		return
-	}
-
-	tests := []struct {
-		name string
-		want []uuid.UUID
-	}{
-		{
-			name: "default",
-			want: []uuid.UUID{confirmed.cuid},
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			s := store
-			if got := s.Confirmed(); !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("Confirmed() = %v, want %v", got, tt.want)
-			}
-		})
-	}
-}
-
-func Test_filterChanges(t *testing.T) {
-	testName := t.Name()
-	callback := func(first ygot.GoStruct, second ygot.GoStruct) error {
-		log.Infof("callback in test %v", testName)
-		return nil
-	}
-
-	store := NewChangeStore()
-	pending := NewChange(did, &openconfig.Device{}, &openconfig.Device{}, callback)
-	committed := NewChange(did, &openconfig.Device{}, &openconfig.Device{}, callback)
-	if err := committed.Commit(); err != nil {
-		t.Error(err)
-		return
-	}
-	confirmed := NewChange(did, &openconfig.Device{}, &openconfig.Device{}, callback)
-	if err := confirmed.Commit(); err != nil {
-		t.Error(err)
-		return
-	}
-	if err := confirmed.Confirm(); err != nil {
-		t.Error(err)
-		return
-	}
-	if err := store.Add(pending); err != nil {
-		t.Error(err)
-		return
-	}
-	if err := store.Add(committed); err != nil {
-		t.Error(err)
-		return
-	}
-	if err := store.Add(confirmed); err != nil {
-		t.Error(err)
-		return
-	}
-	type args struct {
-		store ChangeStore
-		state ppb.Change_State
-	}
-	tests := []struct {
-		name string
-		args args
-		want []uuid.UUID
-	}{
-		{
-			name: "pending",
-			args: args{
-				store: *store,
-				state: ppb.Change_PENDING,
-			},
-			want: []uuid.UUID{pending.cuid},
-		},
-		{
-			name: "committed",
-			args: args{
-				store: *store,
-				state: ppb.Change_COMMITTED,
-			},
-			want: []uuid.UUID{committed.cuid},
-		},
-		{
-			name: "confirmed",
-			args: args{
-				store: *store,
-				state: ppb.Change_CONFIRMED,
-			},
-			want: []uuid.UUID{confirmed.cuid},
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			if got := filterChanges(tt.args.store, tt.args.state); !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("filterChanges() = %v, want %v", got, tt.want)
-			}
-		})
-	}
-}
diff --git a/store/changeStores.go b/store/changeStores.go
new file mode 100644
index 0000000000000000000000000000000000000000..974c6f13eff8e453ee9d05e85639d3d6f7b8e7b0
--- /dev/null
+++ b/store/changeStores.go
@@ -0,0 +1,68 @@
+package store
+
+import (
+	"code.fbi.h-da.de/danet/gosdn/interfaces/change"
+	"code.fbi.h-da.de/danet/gosdn/nucleus/errors"
+	"github.com/google/uuid"
+	log "github.com/sirupsen/logrus"
+
+	ppb "code.fbi.h-da.de/danet/api/go/gosdn/pnd"
+)
+
+// ChangeStore is used to store Changes
+type ChangeStore struct {
+	*genericStore
+}
+
+// NewChangeStore returns a ChangeStore
+func NewChangeStore() *ChangeStore {
+	return &ChangeStore{genericStore: newGenericStore()}
+}
+
+// GetChange takes a Change's UUID and returns the Change. If the requested
+// Change does not exist an error is returned.
+func (s *ChangeStore) GetChange(id uuid.UUID) (change.Change, error) {
+	item, err := s.genericStore.Get(id)
+	if err != nil {
+		return nil, err
+	}
+	change, ok := item.(change.Change)
+	if !ok {
+		return nil, &errors.ErrInvalidTypeAssertion{
+			Value: change,
+			Type:  "change",
+		}
+	}
+	log.WithFields(log.Fields{
+		"uuid": id,
+	}).Debug("change was accessed")
+	return change, nil
+}
+
+// Pending returns the UUIDs of all pending changes
+func (s *ChangeStore) Pending() []uuid.UUID {
+	return filterChanges(s, ppb.Change_PENDING)
+}
+
+// Committed returns the UUIDs of all pending changes
+func (s *ChangeStore) Committed() []uuid.UUID {
+	return filterChanges(s, ppb.Change_COMMITTED)
+}
+
+// Confirmed returns the UUIDs of all pending changes
+func (s *ChangeStore) Confirmed() []uuid.UUID {
+	return filterChanges(s, ppb.Change_CONFIRMED)
+}
+
+func filterChanges(store *ChangeStore, state ppb.Change_State) []uuid.UUID {
+	changes := make([]uuid.UUID, 0)
+	for _, ch := range store.Store {
+		switch change := ch.(type) {
+		case change.Change:
+			if change.State() == state {
+				changes = append(changes, change.ID())
+			}
+		}
+	}
+	return changes
+}
diff --git a/store/change_store_test.go b/store/change_store_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..fee6c99bd07c75114c41eac9648ef77396dc6256
--- /dev/null
+++ b/store/change_store_test.go
@@ -0,0 +1,226 @@
+package store
+
+import (
+	"log"
+	"reflect"
+	"testing"
+
+	"code.fbi.h-da.de/danet/api/go/gosdn/pnd"
+	ppb "code.fbi.h-da.de/danet/api/go/gosdn/pnd"
+	"code.fbi.h-da.de/danet/gosdn/mocks"
+	"github.com/google/uuid"
+)
+
+func TestChangeStore_Pending(t *testing.T) {
+	changeMock := &mocks.Change{}
+	changeMock.On("ID").Return(cuid)
+	changeMock.On("State").Return(pnd.Change_PENDING)
+
+	store := NewChangeStore()
+	pending := changeMock
+	if err := store.Add(pending); err != nil {
+		t.Error(err)
+		return
+	}
+	tests := []struct {
+		name string
+		want []uuid.UUID
+	}{
+		{
+			name: "default",
+			want: []uuid.UUID{cuid},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			s := store
+			if got := s.Pending(); !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("Pending() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestChangeStore_Committed(t *testing.T) {
+	changeMock := &mocks.Change{}
+	changeMock.On("ID").Return(cuid)
+	changeMock.On("State").Return(pnd.Change_COMMITTED)
+	changeMock.On("Commit").Return(nil)
+
+	store := NewChangeStore()
+	committed := changeMock
+	if err := committed.Commit(); err != nil {
+		t.Error(err)
+		return
+	}
+	if err := store.Add(committed); err != nil {
+		t.Error(err)
+		return
+	}
+	tests := []struct {
+		name string
+		want []uuid.UUID
+	}{
+		{
+			name: "default",
+			want: []uuid.UUID{cuid},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			s := store
+			if got := s.Committed(); !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("Committed() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestChangeStore_Confirmed(t *testing.T) {
+	changeMock := &mocks.Change{}
+	changeMock.On("ID").Return(cuid)
+	changeMock.On("State").Return(pnd.Change_CONFIRMED)
+	changeMock.On("Commit").Return(nil)
+	changeMock.On("Confirm").Return(nil)
+
+	store := NewChangeStore()
+	confirmed := changeMock
+	if err := confirmed.Commit(); err != nil {
+		t.Error(err)
+		return
+	}
+	if err := confirmed.Confirm(); err != nil {
+		t.Error(err)
+		return
+	}
+	if err := store.Add(confirmed); err != nil {
+		t.Error(err)
+		return
+	}
+
+	tests := []struct {
+		name string
+		want []uuid.UUID
+	}{
+		{
+			name: "default",
+			want: []uuid.UUID{cuid},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			s := store
+			if got := s.Confirmed(); !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("Confirmed() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func Test_filterChanges(t *testing.T) {
+	var pendingCUID uuid.UUID
+	var committedCUID uuid.UUID
+	var confirmedCUID uuid.UUID
+	var err error
+
+	pendingCUID, err = uuid.Parse("3e8219b0-e926-400d-8660-217f2a25a7c7")
+	if err != nil {
+		log.Fatal(err)
+	}
+	committedCUID, err = uuid.Parse("3e8219b0-e926-400d-8660-217f2a25a7c8")
+	if err != nil {
+		log.Fatal(err)
+	}
+	confirmedCUID, err = uuid.Parse("3e8219b0-e926-400d-8660-217f2a25a7c9")
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	changeMockPending := &mocks.Change{}
+	changeMockPending.On("ID").Return(pendingCUID)
+	changeMockPending.On("State").Return(pnd.Change_PENDING)
+	changeMockPending.On("Commit").Return(nil)
+	changeMockPending.On("Confirm").Return(nil)
+
+	changeMockCommited := &mocks.Change{}
+	changeMockCommited.On("ID").Return(committedCUID)
+	changeMockCommited.On("State").Return(pnd.Change_COMMITTED)
+	changeMockCommited.On("Commit").Return(nil)
+	changeMockCommited.On("Confirm").Return(nil)
+
+	changeMockConfirmed := &mocks.Change{}
+	changeMockConfirmed.On("ID").Return(confirmedCUID)
+	changeMockConfirmed.On("State").Return(pnd.Change_CONFIRMED)
+	changeMockConfirmed.On("Commit").Return(nil)
+	changeMockConfirmed.On("Confirm").Return(nil)
+
+	store := NewChangeStore()
+	pending := changeMockPending
+	committed := changeMockCommited
+	if err := committed.Commit(); err != nil {
+		t.Error(err)
+		return
+	}
+	confirmed := changeMockConfirmed
+	if err := confirmed.Commit(); err != nil {
+		t.Error(err)
+		return
+	}
+	if err := confirmed.Confirm(); err != nil {
+		t.Error(err)
+		return
+	}
+	if err := store.Add(pending); err != nil {
+		t.Error(err)
+		return
+	}
+	if err := store.Add(committed); err != nil {
+		t.Error(err)
+		return
+	}
+	if err := store.Add(confirmed); err != nil {
+		t.Error(err)
+		return
+	}
+	type args struct {
+		store *ChangeStore
+		state ppb.Change_State
+	}
+	tests := []struct {
+		name string
+		args args
+		want []uuid.UUID
+	}{
+		{
+			name: "pending",
+			args: args{
+				store: store,
+				state: ppb.Change_PENDING,
+			},
+			want: []uuid.UUID{pendingCUID},
+		},
+		{
+			name: "committed",
+			args: args{
+				store: store,
+				state: ppb.Change_COMMITTED,
+			},
+			want: []uuid.UUID{committedCUID},
+		},
+		{
+			name: "confirmed",
+			args: args{
+				store: store,
+				state: ppb.Change_CONFIRMED,
+			},
+			want: []uuid.UUID{confirmedCUID},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if got := filterChanges(tt.args.store, tt.args.state); !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("filterChanges() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
diff --git a/store/deviceStore.go b/store/deviceStore.go
new file mode 100644
index 0000000000000000000000000000000000000000..e4bf0e419b193be57b3cc786c1f4c69721f5d9cf
--- /dev/null
+++ b/store/deviceStore.go
@@ -0,0 +1,109 @@
+package store
+
+import (
+	"fmt"
+	"reflect"
+
+	"code.fbi.h-da.de/danet/gosdn/interfaces/device"
+	"code.fbi.h-da.de/danet/gosdn/interfaces/store"
+	"code.fbi.h-da.de/danet/gosdn/nucleus/errors"
+
+	"github.com/google/uuid"
+	log "github.com/sirupsen/logrus"
+)
+
+// DeviceStore is used to store Devices
+type DeviceStore struct {
+	DeviceNameToUUIDLookup map[string]uuid.UUID
+	*genericStore
+}
+
+// NewDeviceStore returns a DeviceStore
+func NewDeviceStore() *DeviceStore {
+	return &DeviceStore{genericStore: newGenericStore(), DeviceNameToUUIDLookup: make(map[string]uuid.UUID)}
+}
+
+// GetDevice takes a Device's UUID and returns the Device. If the requested
+// Device does not exist an error is returned.
+func (s *DeviceStore) GetDevice(id uuid.UUID, parseErrors ...error) (device.Device, error) {
+	var foundID uuid.UUID
+
+	foundID = id
+
+	for _, parseErrs := range parseErrors {
+		if parseErrs != nil {
+			switch e := parseErrs.(type) {
+			case *errors.ErrInvalidUUID:
+				myID, ok := s.DeviceNameToUUIDLookup[e.DeviceName]
+				if !ok {
+					log.Debug(fmt.Sprintf("no device named %s found", foundID))
+					return nil, &errors.ErrNotFound{}
+				}
+
+				foundID = myID
+			}
+		}
+	}
+
+	item, err := s.genericStore.Get(foundID)
+	if err != nil {
+		return nil, err
+	}
+	d, ok := item.(device.Device)
+	if !ok {
+		return nil, &errors.ErrInvalidTypeAssertion{
+			Value: d,
+			Type:  reflect.TypeOf((device.Device)(nil)),
+		}
+	}
+	log.WithFields(log.Fields{
+		"uuid": foundID,
+		"name": d.Name(),
+	}).Debug("device was accessed")
+
+	return d, nil
+}
+
+// Add adds a device to the device store.
+// It also adds the name of the device to the lookup table.
+func (s *DeviceStore) Add(item store.Storable, name string) error {
+	if s.Exists(item.ID()) {
+		return &errors.ErrAlreadyExists{Item: item}
+	}
+
+	s.DeviceNameToUUIDLookup[name] = item.ID()
+
+	s.storeLock.Lock()
+	s.genericStore.Store[item.ID()] = item
+	s.storeLock.Unlock()
+
+	log.WithFields(log.Fields{
+		"type": reflect.TypeOf(item),
+		"uuid": item.ID(),
+	}).Debug("storable was added")
+
+	return nil
+}
+
+// Delete deletes a device from the device store.
+func (s *DeviceStore) Delete(id uuid.UUID) error {
+	if !s.Exists(id) {
+		return &errors.ErrNotFound{ID: id}
+	}
+
+	s.storeLock.Lock()
+	delete(s.genericStore.Store, id)
+	s.storeLock.Unlock()
+
+	for key, value := range s.DeviceNameToUUIDLookup {
+		if value == id {
+			delete(s.DeviceNameToUUIDLookup, key)
+		}
+	}
+
+	log.WithFields(log.Fields{
+		"uuid": id,
+	}).Debug("storable was deleted")
+
+	return nil
+}
diff --git a/store/device_store_test.go b/store/device_store_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..ad2257632b5f1570d4985307a0ec237506c61252
--- /dev/null
+++ b/store/device_store_test.go
@@ -0,0 +1,97 @@
+package store
+
+import (
+	"reflect"
+	"sync"
+	"testing"
+
+	"code.fbi.h-da.de/danet/gosdn/interfaces/device"
+	"code.fbi.h-da.de/danet/gosdn/interfaces/store"
+	"code.fbi.h-da.de/danet/gosdn/mocks"
+	"github.com/google/uuid"
+)
+
+func Test_deviceStore_get(t *testing.T) {
+	deviceMock := &mocks.Device{}
+	deviceMock.On("ID").Return(did)
+	deviceMock.On("Name").Return("did")
+	pndMock := &mocks.NetworkDomain{}
+	pndMock.On("ID").Return(did)
+
+	type fields struct {
+		genericStore *genericStore
+	}
+	type args struct {
+		id uuid.UUID
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		want    device.Device
+		wantErr bool
+	}{
+		{
+			name: "exists",
+			fields: fields{
+				&genericStore{
+					Store: map[uuid.UUID]store.Storable{
+						defaultPndID: deviceMock,
+					},
+					storeLock: sync.RWMutex{},
+				},
+			},
+			args:    args{id: defaultPndID},
+			want:    deviceMock,
+			wantErr: false,
+		},
+		{
+			name: "fails",
+			fields: fields{
+				&genericStore{
+					Store: map[uuid.UUID]store.Storable{
+						defaultPndID: deviceMock,
+					},
+					storeLock: sync.RWMutex{},
+				},
+			},
+			args:    args{id: iid},
+			wantErr: true,
+		},
+		{
+			name: "fails empty",
+			fields: fields{
+				genericStore: &genericStore{},
+			},
+			args:    args{id: defaultPndID},
+			wantErr: true,
+		},
+		{
+			name: "fails wrong type",
+			fields: fields{
+				&genericStore{
+					Store: map[uuid.UUID]store.Storable{
+						defaultPndID: pndMock,
+					},
+					storeLock: sync.RWMutex{},
+				},
+			},
+			args:    args{id: defaultPndID},
+			wantErr: true,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			s := DeviceStore{genericStore: tt.fields.genericStore}
+
+			got, err := s.GetDevice(FromString(tt.args.id.String()))
+			if (err != nil) != tt.wantErr {
+				t.Errorf("get() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("get() got = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
diff --git a/store/genericStore.go b/store/genericStore.go
new file mode 100644
index 0000000000000000000000000000000000000000..83d6bb9333403bc868611c17c29d70c271bfd337
--- /dev/null
+++ b/store/genericStore.go
@@ -0,0 +1,89 @@
+package store
+
+import (
+	"reflect"
+	"sync"
+
+	"code.fbi.h-da.de/danet/gosdn/interfaces/store"
+	"code.fbi.h-da.de/danet/gosdn/nucleus/errors"
+
+	"github.com/google/uuid"
+	log "github.com/sirupsen/logrus"
+)
+
+// newGenericStore returns a genericStore
+func newGenericStore() *genericStore {
+	return &genericStore{Store: make(map[uuid.UUID]store.Storable), storeLock: sync.RWMutex{}}
+}
+
+type genericStore struct {
+	Store     map[uuid.UUID]store.Storable
+	storeLock sync.RWMutex
+}
+
+// Exists takes a Storable's UUID and checks its existence in the store.
+func (s *genericStore) Exists(id uuid.UUID) bool {
+	s.storeLock.RLock()
+	defer s.storeLock.RUnlock()
+	_, ok := s.Store[id]
+	return ok
+}
+
+// Add adds a Storable to the Store
+func (s *genericStore) Add(item store.Storable) error {
+	if s.Exists(item.ID()) {
+		return &errors.ErrAlreadyExists{Item: item}
+	}
+	s.storeLock.Lock()
+	s.Store[item.ID()] = item
+	s.storeLock.Unlock()
+	log.WithFields(log.Fields{
+		"type": reflect.TypeOf(item),
+		"uuid": item.ID(),
+	}).Debug("storable was added")
+	return nil
+}
+
+// Get takes a Storable's UUID and returns the Storable. If the requested
+// Storable does not exist an error is returned. Get is only type safe for
+// this Storable interface. For type safe get operations on specialised stores
+// use GetDevice, GetPND, GetSBI, or GetChange respectively.
+func (s *genericStore) Get(id uuid.UUID) (store.Storable, error) {
+	if !s.Exists(id) {
+		return nil, &errors.ErrNotFound{ID: id}
+	}
+	log.WithFields(log.Fields{
+		"uuid": id,
+	}).Debug("storable was accessed")
+	s.storeLock.RLock()
+	defer s.storeLock.RUnlock()
+	return s.Store[id], nil
+}
+
+// Delete takes a Storable's UUID and deletes it. If the specified UUID does not
+// exist in the Store an error is returned.
+func (s *genericStore) Delete(id uuid.UUID) error {
+	if !s.Exists(id) {
+		return &errors.ErrNotFound{ID: id}
+	}
+	s.storeLock.Lock()
+	delete(s.Store, id)
+	s.storeLock.Unlock()
+	log.WithFields(log.Fields{
+		"uuid": id,
+	}).Debug("storable was deleted")
+	return nil
+}
+
+// UUIDs returns all UUIDs in the store.
+func (s *genericStore) UUIDs() []uuid.UUID {
+	s.storeLock.RLock()
+	defer s.storeLock.RUnlock()
+	keys := make([]uuid.UUID, len(s.Store))
+	i := 0
+	for k := range s.Store {
+		keys[i] = k
+		i++
+	}
+	return keys
+}
diff --git a/store/generic_store_test.go b/store/generic_store_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..feb55d5b1dd68fbc48fc4e54648601253ff42e66
--- /dev/null
+++ b/store/generic_store_test.go
@@ -0,0 +1,242 @@
+package store
+
+import (
+	"reflect"
+	"sort"
+	"testing"
+
+	"code.fbi.h-da.de/danet/gosdn/interfaces/store"
+	"code.fbi.h-da.de/danet/gosdn/mocks"
+	"github.com/google/uuid"
+)
+
+func Test_Store_add(t *testing.T) {
+	type args struct {
+		item store.Storable
+	}
+	tests := []struct {
+		name    string
+		s       *genericStore
+		args    args
+		wantErr bool
+	}{
+		{
+			name: "default",
+			s:    newGenericStore(),
+			args: args{
+				item: &mocks.Storable{},
+			},
+		},
+		{
+			name: "already exists",
+			s: &genericStore{
+				Store: map[uuid.UUID]store.Storable{
+					iid: &mocks.Storable{},
+				},
+			},
+			args: args{
+				item: &mocks.Storable{},
+			},
+			wantErr: true,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			tt.args.item.(*mocks.Storable).On("ID").Return(iid)
+			switch tt.name {
+			case "already exixts":
+				_ = tt.s.Add(tt.args.item)
+			default:
+			}
+			if err := tt.s.Add(tt.args.item); (err != nil) != tt.wantErr {
+				t.Errorf("Add() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+}
+
+func Test_Store_delete(t *testing.T) {
+	type args struct {
+		id uuid.UUID
+	}
+	tests := []struct {
+		name    string
+		s       *genericStore
+		args    args
+		wantErr bool
+	}{
+		{
+			name: "default",
+			s: &genericStore{
+				Store: map[uuid.UUID]store.Storable{
+					iid: &mocks.Storable{},
+				},
+			},
+			args:    args{id: iid},
+			wantErr: false,
+		},
+		{
+			name:    "not found empty",
+			s:       newGenericStore(),
+			args:    args{id: iid},
+			wantErr: true,
+		},
+		{
+			name: "not found",
+			s: &genericStore{
+				Store: map[uuid.UUID]store.Storable{
+					iid: &mocks.Storable{},
+				},
+			},
+			args:    args{id: altIid},
+			wantErr: true,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if err := tt.s.Delete(tt.args.id); (err != nil) != tt.wantErr {
+				t.Errorf("delete() error = %v, wantErr %v", err, tt.wantErr)
+			}
+			if tt.name == "default" {
+				item, ok := tt.s.Store[iid]
+				if ok {
+					t.Errorf("delete() item %v still in genericStore %v", item, tt.s)
+				}
+			}
+		})
+	}
+}
+
+func Test_Store_exists(t *testing.T) {
+	type args struct {
+		id uuid.UUID
+	}
+	tests := []struct {
+		name string
+		s    *genericStore
+		args args
+		want bool
+	}{
+		{
+			name: "default",
+			s: &genericStore{
+				Store: map[uuid.UUID]store.Storable{
+					iid: &mocks.Storable{},
+				},
+			},
+			args: args{id: iid},
+			want: true,
+		},
+		{
+			name: "not found empty",
+			s:    newGenericStore(),
+			args: args{id: iid},
+			want: false,
+		},
+		{
+			name: "not found",
+			s: &genericStore{
+				Store: map[uuid.UUID]store.Storable{
+					iid: &mocks.Storable{},
+				},
+			},
+			args: args{id: altIid},
+			want: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if got := tt.s.Exists(tt.args.id); got != tt.want {
+				t.Errorf("exists() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func Test_Store_get(t *testing.T) {
+	type args struct {
+		id uuid.UUID
+	}
+	tests := []struct {
+		name    string
+		s       *genericStore
+		args    args
+		want    store.Storable
+		wantErr bool
+	}{
+		{
+			name: "exists",
+			s: &genericStore{
+				Store: map[uuid.UUID]store.Storable{
+					iid: &mocks.Storable{},
+				},
+			},
+			args:    args{id: iid},
+			want:    &mocks.Storable{},
+			wantErr: false,
+		},
+		{
+			name: "not found",
+			s: &genericStore{
+				Store: map[uuid.UUID]store.Storable{
+					iid: &mocks.Storable{},
+				},
+			},
+			args:    args{id: altIid},
+			want:    nil,
+			wantErr: true,
+		},
+		{
+			name:    "not found empty",
+			s:       newGenericStore(),
+			args:    args{id: iid},
+			want:    nil,
+			wantErr: true,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got, err := tt.s.Get(tt.args.id)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("get() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("get() got = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func Test_Store_UUIDs(t *testing.T) {
+	tests := []struct {
+		name string
+		s    *genericStore
+		want []uuid.UUID
+	}{
+		{
+			name: "default",
+			s: &genericStore{
+				Store: map[uuid.UUID]store.Storable{
+					iid:    &mocks.Storable{},
+					altIid: &mocks.Storable{},
+				},
+			},
+			want: []uuid.UUID{iid, altIid},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			sort.Slice(tt.want, func(i, j int) bool {
+				return tt.want[i].String() < tt.want[j].String()
+			})
+			got := tt.s.UUIDs()
+			sort.Slice(got, func(i, j int) bool {
+				return got[i].String() < got[j].String()
+			})
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("UUIDs() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
diff --git a/store/initialise_test.go b/store/initialise_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..732bad161a89a0fe8a7d9b7e92bf261a027e6031
--- /dev/null
+++ b/store/initialise_test.go
@@ -0,0 +1,60 @@
+package store
+
+import (
+	"os"
+	"testing"
+
+	"github.com/google/uuid"
+	log "github.com/sirupsen/logrus"
+)
+
+// UUIDs for test cases
+var mdid uuid.UUID
+var defaultPndID uuid.UUID
+var cuid uuid.UUID
+var did uuid.UUID
+var iid uuid.UUID
+var altIid uuid.UUID
+var defaultSbiID uuid.UUID
+
+func TestMain(m *testing.M) {
+	log.SetReportCaller(true)
+
+	if os.Getenv("GOSDN_LOG") == "nolog" {
+		log.SetLevel(log.PanicLevel)
+	}
+	readTestUUIDs()
+	os.Exit(m.Run())
+}
+
+func readTestUUIDs() {
+	var err error
+	mdid, err = uuid.Parse("688a264e-5f85-40f8-bd13-afc42fcd5c7a")
+	if err != nil {
+		log.Fatal(err)
+	}
+	defaultPndID, err = uuid.Parse("b4016412-eec5-45a1-aa29-f59915357bad")
+	if err != nil {
+		log.Fatal(err)
+	}
+	cuid, err = uuid.Parse("3e8219b0-e926-400d-8660-217f2a25a7c6")
+	if err != nil {
+		log.Fatal(err)
+	}
+	did, err = uuid.Parse("4d8246f8-e884-41d6-87f5-c2c784df9e44")
+	if err != nil {
+		log.Fatal(err)
+	}
+	iid, err = uuid.Parse("8495a8ac-a1e8-418e-b787-10f5878b2690")
+	if err != nil {
+		log.Fatal(err)
+	}
+	altIid, err = uuid.Parse("edc5de93-2d15-4586-b2a7-fb1bc770986b")
+	if err != nil {
+		log.Fatal(err)
+	}
+	defaultSbiID, err = uuid.Parse("b70c8425-68c7-4d4b-bb5e-5586572bd64b")
+	if err != nil {
+		log.Fatal(err)
+	}
+}
diff --git a/store/pndStore.go b/store/pndStore.go
new file mode 100644
index 0000000000000000000000000000000000000000..32aa935413896a409e6a8287248fa8b85e7bb549
--- /dev/null
+++ b/store/pndStore.go
@@ -0,0 +1,67 @@
+package store
+
+import (
+	tpb "code.fbi.h-da.de/danet/api/go/gosdn/transport"
+	"code.fbi.h-da.de/danet/gosdn/interfaces/networkdomain"
+	"code.fbi.h-da.de/danet/gosdn/nucleus/errors"
+	"github.com/google/uuid"
+	log "github.com/sirupsen/logrus"
+)
+
+// DeviceDetails contains details of a device used by the cSBI mechanism
+type DeviceDetails struct {
+	ID              string
+	Address         string
+	TransportOption *tpb.TransportOption
+}
+
+// PndStore is used to store PrincipalNetworkDomains
+type PndStore struct {
+	pendingChannels map[uuid.UUID]chan DeviceDetails
+	*genericStore
+}
+
+// NewPndStore returns a PndStore
+func NewPndStore() *PndStore {
+	return &PndStore{genericStore: newGenericStore()}
+}
+
+// GetPND takes a PrincipalNetworkDomain's UUID and returns the PrincipalNetworkDomain. If the requested
+// PrincipalNetworkDomain does not exist an error is returned.
+func (s *PndStore) GetPND(id uuid.UUID) (networkdomain.NetworkDomain, error) {
+	item, err := s.genericStore.Get(id)
+	if err != nil {
+		return nil, err
+	}
+	pnd, ok := item.(networkdomain.NetworkDomain)
+	if !ok {
+		return nil, &errors.ErrInvalidTypeAssertion{
+			Value: pnd,
+			Type:  "PrincipalNetworkDomain",
+		}
+	}
+	log.WithFields(log.Fields{
+		"uuid": id,
+	}).Debug("principal network domain was accessed")
+	return pnd, nil
+}
+
+// PendingChannels holds channels used communicate with pending
+// cSBI deployments
+func (s *PndStore) PendingChannels(id uuid.UUID, parseErrors ...error) (chan DeviceDetails, error) {
+	ch, ok := s.pendingChannels[id]
+	if !ok {
+		return nil, &errors.ErrNotFound{ID: id}
+	}
+	return ch, nil
+}
+
+// AddPendingChannel adds a pending channel to the map
+func (s *PndStore) AddPendingChannel(id uuid.UUID, ch chan DeviceDetails) {
+	s.pendingChannels[id] = ch
+}
+
+// RemovePendingChannel removes a pending channel from the map
+func (s *PndStore) RemovePendingChannel(id uuid.UUID) {
+	delete(s.pendingChannels, id)
+}
diff --git a/store/pnd_store_test.go b/store/pnd_store_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..5cd8bbbbfa42bb2aa4c44c2812bf1bf22abd73d7
--- /dev/null
+++ b/store/pnd_store_test.go
@@ -0,0 +1,82 @@
+package store
+
+import (
+	"reflect"
+	"sync"
+	"testing"
+
+	"code.fbi.h-da.de/danet/gosdn/interfaces/networkdomain"
+	"code.fbi.h-da.de/danet/gosdn/interfaces/store"
+	"code.fbi.h-da.de/danet/gosdn/mocks"
+	"github.com/google/uuid"
+)
+
+func Test_pndStore_get(t *testing.T) {
+	pndMock := &mocks.NetworkDomain{}
+	pndMock.On("ID").Return(defaultPndID)
+
+	type fields struct {
+		genericStore *genericStore
+	}
+	type args struct {
+		id uuid.UUID
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		want    networkdomain.NetworkDomain
+		wantErr bool
+	}{
+		{
+			name: "exists",
+			fields: fields{
+				&genericStore{
+					Store: map[uuid.UUID]store.Storable{
+						defaultPndID: pndMock,
+					},
+					storeLock: sync.RWMutex{},
+				},
+			},
+			args:    args{id: defaultPndID},
+			want:    pndMock,
+			wantErr: false,
+		},
+		{
+			name: "fails",
+			fields: fields{
+				&genericStore{
+					Store: map[uuid.UUID]store.Storable{
+						defaultPndID: pndMock,
+					},
+					storeLock: sync.RWMutex{},
+				},
+			},
+			args:    args{id: iid},
+			wantErr: true,
+		},
+		{
+			name: "fails empty",
+			fields: fields{
+				genericStore: &genericStore{},
+			},
+			args:    args{id: defaultPndID},
+			wantErr: true,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			s := PndStore{
+				genericStore: tt.fields.genericStore,
+			}
+			got, err := s.Get(tt.args.id)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("get() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("get() got = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
diff --git a/store/sbiStore.go b/store/sbiStore.go
new file mode 100644
index 0000000000000000000000000000000000000000..fd8310bfd64577c822748afdbb14b2744a6028de
--- /dev/null
+++ b/store/sbiStore.go
@@ -0,0 +1,39 @@
+package store
+
+import (
+	"code.fbi.h-da.de/danet/gosdn/interfaces/southbound"
+	"code.fbi.h-da.de/danet/gosdn/nucleus/errors"
+
+	"github.com/google/uuid"
+	log "github.com/sirupsen/logrus"
+)
+
+// SbiStore is used to store SouthboundInterfaces
+type SbiStore struct {
+	*genericStore
+}
+
+// NewSbiStore returns a SbiStore
+func NewSbiStore() *SbiStore {
+	return &SbiStore{genericStore: newGenericStore()}
+}
+
+// GetSBI takes a SouthboundInterface's UUID and returns the SouthboundInterface. If the requested
+// SouthboundInterface does not exist an error is returned.
+func (s *SbiStore) GetSBI(id uuid.UUID) (southbound.SouthboundInterface, error) {
+	item, err := s.Get(id)
+	if err != nil {
+		return nil, err
+	}
+	sbi, ok := item.(southbound.SouthboundInterface)
+	if !ok {
+		return nil, &errors.ErrInvalidTypeAssertion{
+			Value: sbi,
+			Type:  "SouthboundInterface",
+		}
+	}
+	log.WithFields(log.Fields{
+		"uuid": id,
+	}).Debug("southbound interface was accessed")
+	return sbi, nil
+}
diff --git a/store/sbi_store_test.go b/store/sbi_store_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..2dc294639a6947f6c31374a97b75034297647027
--- /dev/null
+++ b/store/sbi_store_test.go
@@ -0,0 +1,82 @@
+package store
+
+import (
+	"reflect"
+	"sync"
+	"testing"
+
+	"code.fbi.h-da.de/danet/gosdn/interfaces/southbound"
+	"code.fbi.h-da.de/danet/gosdn/interfaces/store"
+	"code.fbi.h-da.de/danet/gosdn/mocks"
+
+	"github.com/google/uuid"
+)
+
+func Test_sbiStore_get(t *testing.T) {
+	openConfig := &mocks.SouthboundInterface{}
+	openConfig.On("ID").Return(defaultSbiID)
+
+	type fields struct {
+		genericStore *genericStore
+	}
+	type args struct {
+		id uuid.UUID
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		want    southbound.SouthboundInterface
+		wantErr bool
+	}{
+		{
+			name: "exists",
+			fields: fields{
+				&genericStore{
+					Store: map[uuid.UUID]store.Storable{
+						defaultSbiID: openConfig,
+					},
+					storeLock: sync.RWMutex{},
+				},
+			},
+			args:    args{id: defaultSbiID},
+			want:    openConfig,
+			wantErr: false,
+		},
+		{
+			name: "fails",
+			fields: fields{
+				&genericStore{
+					Store: map[uuid.UUID]store.Storable{
+						defaultSbiID: openConfig,
+					},
+					storeLock: sync.RWMutex{},
+				},
+			},
+			args:    args{id: iid},
+			wantErr: true,
+		},
+		{
+			name: "fails empty",
+			fields: fields{
+				genericStore: &genericStore{},
+			},
+			args:    args{id: defaultSbiID},
+			wantErr: true,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			s := SbiStore{genericStore: tt.fields.genericStore}
+
+			got, err := s.Get(tt.args.id)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("get() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("get() got = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
diff --git a/store/utils.go b/store/utils.go
new file mode 100644
index 0000000000000000000000000000000000000000..8478836672cb1c450bf083c2246e97c294bfcf1c
--- /dev/null
+++ b/store/utils.go
@@ -0,0 +1,23 @@
+package store
+
+import (
+	"code.fbi.h-da.de/danet/gosdn/nucleus/errors"
+	"github.com/google/uuid"
+	log "github.com/sirupsen/logrus"
+)
+
+// FromString is a helper to check if a provided string as a valid UUID or a name.
+func FromString(id string) (uuid.UUID, error) {
+	idAsUUID, err := uuid.Parse(id)
+
+	// id is no UUID therefore it could be a device name.
+	// The name will be returned within the error.
+	if err != nil {
+		log.WithFields(log.Fields{
+			"identifier": id,
+		}).Debug(err)
+		return uuid.Nil, &errors.ErrInvalidUUID{DeviceName: id}
+	}
+
+	return idAsUUID, nil
+}