diff --git a/go.mod b/go.mod
index dbc8944ba25b6372d35c43ba39d7bd8184effb76..094fad6678d5b4f509352d45e740fb669f42bba8 100644
--- a/go.mod
+++ b/go.mod
@@ -8,6 +8,7 @@ require (
 	code.fbi.h-da.de/danet/forks/google v0.0.0-20210709163519-47ee8958ef40
 	code.fbi.h-da.de/danet/yang-models v0.1.0
 	github.com/docker/docker v20.10.11+incompatible
+	github.com/google/go-cmp v0.5.6
 	github.com/google/uuid v1.2.0
 	github.com/openconfig/gnmi v0.0.0-20210914185457-51254b657b7d
 	github.com/openconfig/goyang v0.3.1
@@ -29,7 +30,6 @@ require (
 	github.com/fsnotify/fsnotify v1.5.1 // indirect
 	github.com/golang/glog v1.0.0 // indirect
 	github.com/golang/protobuf v1.5.2 // indirect
-	github.com/google/go-cmp v0.5.6 // indirect
 	github.com/hashicorp/hcl v1.0.0 // indirect
 	github.com/inconshreveable/mousetrap v1.0.0 // indirect
 	github.com/kylelemons/godebug v1.1.0 // indirect
@@ -49,6 +49,7 @@ require (
 	golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 // indirect
 	golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab // indirect
 	golang.org/x/text v0.3.7 // indirect
+	golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
 	google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect
 	gopkg.in/ini.v1 v1.64.0 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
diff --git a/nucleus/principalNetworkDomain.go b/nucleus/principalNetworkDomain.go
index 94a3143622f6d2d11a07fed5bef7f727788922aa..2c7d845514419c74322e3381b71e4855a72f4ac6 100644
--- a/nucleus/principalNetworkDomain.go
+++ b/nucleus/principalNetworkDomain.go
@@ -142,11 +142,18 @@ func (pnd *pndImplementation) AddSbi(s southbound.SouthboundInterface) error {
 	return pnd.addSbi(s)
 }
 
-// RemoveSbi removes a SBI from the PND
-// TODO: this should to recursively through
-// devices and remove the devices using
-// this SBI
+// RemoveSbi removes a SBI and all the associated devices from the PND
 func (pnd *pndImplementation) RemoveSbi(id uuid.UUID) error {
+	associatedDevices, err := pnd.devices.GetDevicesAssociatedWithSbi(id)
+	if err != nil {
+		return err
+	}
+	// range over associated devices and remove each one of them
+	for _, d := range associatedDevices {
+		if err := pnd.removeDevice(d.ID()); err != nil {
+			return err
+		}
+	}
 	return pnd.removeSbi(id)
 }
 
diff --git a/nucleus/principalNetworkDomain_test.go b/nucleus/principalNetworkDomain_test.go
index 93c91f400a794f74700b33bcba8238c9ba098f32..2aabcd29814271b38539dfbef5def11827ff348e 100644
--- a/nucleus/principalNetworkDomain_test.go
+++ b/nucleus/principalNetworkDomain_test.go
@@ -409,6 +409,11 @@ func Test_pndImplementation_RemoveDevice(t *testing.T) {
 }
 
 func Test_pndImplementation_RemoveSbi(t *testing.T) {
+	opts := &tpb.TransportOption{
+		TransportOption: &tpb.TransportOption_GnmiTransportOption{
+			GnmiTransportOption: &tpb.GnmiTransportOption{},
+		},
+	}
 	type args struct {
 		id uuid.UUID
 	}
@@ -420,6 +425,7 @@ func Test_pndImplementation_RemoveSbi(t *testing.T) {
 		{name: "default", args: args{id: defaultSbiID}, wantErr: false},
 		{name: "fails", args: args{id: uuid.New()}, wantErr: true},
 		{name: "fails empty", args: args{id: defaultSbiID}, wantErr: true},
+		{name: "exclusively remove associated devices", args: args{id: defaultSbiID}, wantErr: false},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
@@ -430,16 +436,42 @@ func Test_pndImplementation_RemoveSbi(t *testing.T) {
 				devices:     store.NewDeviceStore(defaultPndID),
 				Id:          defaultPndID,
 			}
-			if tt.name != "fails empty" {
+			if tt.name != "fails empty" && tt.name != "fails" {
 				if err := pnd.addSbi(&OpenConfig{id: defaultSbiID}); err != nil {
 					t.Error(err)
 				}
+				if err := pnd.AddDevice("associatedDevice", opts, tt.args.id); err != nil {
+					t.Error(err)
+				}
+				if err := pnd.AddDevice("associatedDevice2", opts, tt.args.id); err != nil {
+					t.Error(err)
+				}
+				if tt.name == "exclusively remove associated devices" {
+					newID := uuid.New()
+					if err := pnd.addSbi(&OpenConfig{id: newID}); err != nil {
+						t.Error(err)
+					}
+					if err := pnd.AddDevice("associatedDevice2", opts, newID); err != nil {
+						t.Error(err)
+					}
+				}
 			}
+
 			if err := pnd.RemoveSbi(tt.args.id); (err != nil) != tt.wantErr {
 				t.Errorf("RemoveSbi() error = %v, wantErr %v", err, tt.wantErr)
 			}
 			if pnd.sbic.Exists(tt.args.id) {
-				t.Errorf("RemoveDevice() SBI still in SBI store %v", pnd.sbic)
+				t.Errorf("RemoveSbi() SBI still in SBI store %v", pnd.sbic)
+			}
+
+			if tt.name == "exclusively remove associated devices" {
+				if len(pnd.devices.Store) != 1 {
+					t.Errorf("RemoveSbi() non associated devices should remain in the storage %v", pnd.devices)
+				}
+			} else {
+				if len(pnd.devices.Store) != 0 {
+					t.Errorf("RemoveSbi() associated devices have not been removed correctly %v", len(pnd.devices.Store))
+				}
 			}
 		})
 	}
diff --git a/store/deviceStore.go b/store/deviceStore.go
index 871c096f816f301d27174463d4b8122f7374947c..df0a9ba85b8fdb266e16dc11148ed03eec8d7e75 100644
--- a/store/deviceStore.go
+++ b/store/deviceStore.go
@@ -37,16 +37,15 @@ func (s *DeviceStore) GetDevice(id uuid.UUID, parseErrors ...error) (device.Devi
 
 	foundID = id
 
-	for _, parseErrs := range parseErrors {
-		if parseErrs != nil {
-			switch e := parseErrs.(type) {
+	for _, parseErr := range parseErrors {
+		if parseErr != nil {
+			switch e := parseErr.(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{ID: foundID}
 				}
-
 				foundID = myID
 			}
 		}
@@ -71,6 +70,30 @@ func (s *DeviceStore) GetDevice(id uuid.UUID, parseErrors ...error) (device.Devi
 	return d, nil
 }
 
+// GetDevicesAssociatedWithSbi ranges over devices within the device store and
+// checks if they are associated with the provided SBI. Returns a slice of
+// device.Device with all associated devices.
+func (s *DeviceStore) GetDevicesAssociatedWithSbi(sid uuid.UUID) ([]device.Device, error) {
+	var devices []device.Device
+	// range over all storable items within the device store
+	for _, item := range s.Store {
+		d, ok := item.(device.Device)
+		if !ok {
+			return nil, &errors.ErrInvalidTypeAssertion{
+				Value: d,
+				Type:  reflect.TypeOf((*device.Device)(nil)),
+			}
+		}
+		// check if the device uses the provided SBI and add it to the devices
+		// slice.
+		if d.SBI().ID() == sid {
+			devices = append(devices, d)
+		}
+	}
+
+	return devices, 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 {
diff --git a/store/device_store_test.go b/store/device_store_test.go
index ad2257632b5f1570d4985307a0ec237506c61252..69deb7c67b48376ebf55ceffb534005bdec3b413 100644
--- a/store/device_store_test.go
+++ b/store/device_store_test.go
@@ -8,6 +8,8 @@ import (
 	"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/go-cmp/cmp"
+	"github.com/google/go-cmp/cmp/cmpopts"
 	"github.com/google/uuid"
 )
 
@@ -95,3 +97,146 @@ func Test_deviceStore_get(t *testing.T) {
 		})
 	}
 }
+
+func Test_deviceStore_GetDevicesAsssociatedWithSbi(t *testing.T) {
+	mockSBI := &mocks.SouthboundInterface{}
+	mockSBI.On("ID").Return(defaultSbiID)
+
+	createDeviceMock := func(name string, sid uuid.UUID) *mocks.Device {
+		dm := &mocks.Device{}
+		dm.On("ID").Return(uuid.New())
+		dm.On("Name").Return("did")
+		dm.On("SBI").Return(mockSBI)
+		return dm
+	}
+
+	associatedDevices := []device.Device{
+		createDeviceMock("mockDevice1", defaultSbiID),
+		createDeviceMock("mockDevice2", defaultSbiID),
+		createDeviceMock("mockDevice3", defaultSbiID),
+	}
+
+	nonAssociatedDevice := createDeviceMock("mockDevice4", uuid.New())
+
+	pndMock := &mocks.NetworkDomain{}
+	pndMock.On("ID").Return(did)
+
+	// options to apply to cmp.Equal
+	opts := []cmp.Option{
+		// create custom comparer that simply checks if the device ID's are the
+		// same.
+		cmp.Comparer(func(x, y device.Device) bool {
+			return x.ID() == y.ID()
+		}),
+		// compare option to treat slices of length zero as equal
+		cmpopts.EquateEmpty(),
+		// sort the slices based on the ID
+		cmpopts.SortSlices(func(x, y device.Device) bool {
+			return x.ID().ID() < y.ID().ID()
+		}),
+	}
+
+	type fields struct {
+		genericStore *genericStore
+	}
+	type args struct {
+		sid uuid.UUID
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		want    []device.Device
+		wantErr bool
+	}{
+		{
+			name: "return devices associated with SBI",
+			fields: fields{
+				&genericStore{
+					Store: map[uuid.UUID]store.Storable{
+						associatedDevices[0].ID(): associatedDevices[0],
+						associatedDevices[1].ID(): associatedDevices[1],
+						associatedDevices[2].ID(): associatedDevices[2],
+					},
+					storeLock: sync.RWMutex{},
+				},
+			},
+			args: args{
+				sid: defaultSbiID,
+			},
+			want:    associatedDevices,
+			wantErr: false,
+		},
+		{
+			name: "non associated devices should not be part of the returned slice",
+			fields: fields{
+				&genericStore{
+					Store: map[uuid.UUID]store.Storable{
+						associatedDevices[0].ID(): associatedDevices[0],
+						associatedDevices[1].ID(): associatedDevices[1],
+						associatedDevices[2].ID(): associatedDevices[2],
+						nonAssociatedDevice.ID():  nonAssociatedDevice,
+					},
+					storeLock: sync.RWMutex{},
+				},
+			},
+			args: args{
+				sid: defaultSbiID,
+			},
+			want:    append(associatedDevices, nonAssociatedDevice),
+			wantErr: false,
+		},
+		{
+			name: "empty",
+			fields: fields{
+				&genericStore{
+					Store:     map[uuid.UUID]store.Storable{},
+					storeLock: sync.RWMutex{},
+				},
+			},
+			want:    []device.Device{},
+			wantErr: false,
+		},
+		{
+			name: "no device associated",
+			fields: fields{
+				&genericStore{
+					Store: map[uuid.UUID]store.Storable{
+						nonAssociatedDevice.ID(): nonAssociatedDevice,
+					},
+					storeLock: sync.RWMutex{},
+				},
+			},
+			want:    []device.Device{},
+			wantErr: false,
+		},
+		{
+			name: "fails wrong type",
+			fields: fields{
+				&genericStore{
+					Store: map[uuid.UUID]store.Storable{
+						defaultPndID: pndMock,
+					},
+					storeLock: sync.RWMutex{},
+				},
+			},
+			args:    args{sid: defaultSbiID},
+			want:    nil,
+			wantErr: true,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			s := DeviceStore{genericStore: tt.fields.genericStore}
+
+			got, err := s.GetDevicesAssociatedWithSbi(tt.args.sid)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("GetDevicesAssociatedWithSbi() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !cmp.Equal(got, tt.want, opts...) {
+				t.Errorf("GetDevicesAssociatedWithSbi() got = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}