diff --git a/controller/controller.go b/controller/controller.go
index 7e2414e7664a96fe10b7f1911ddd0f7c5bdcef25..3eb2c153ffd24231834769eecf0d23788404f8be 100644
--- a/controller/controller.go
+++ b/controller/controller.go
@@ -146,7 +146,7 @@ func initialize() error {
 	}
 
 	c.networkElementWatcher = nucleus.NewNetworkElementWatcher(c.mneService, c.eventService)
-	c.networkElementWatcher.SubscribeToNetworkElements(config.GetGnmiSubscriptionPaths(), nil)
+	c.networkElementWatcher.SubscribeToNetworkElements(nil)
 
 	if err := ensureDefaultRoleExists(); err != nil {
 		return err
diff --git a/controller/northbound/server/networkElement.go b/controller/northbound/server/networkElement.go
index 7f33994dadbc8023dcea02616994030163952961..95816707b8982d46c0be75e6145e3d246e7146cb 100644
--- a/controller/northbound/server/networkElement.go
+++ b/controller/northbound/server/networkElement.go
@@ -9,7 +9,6 @@ import (
 	mnepb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/networkelement"
 	ppb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd"
 	tpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/transport"
-	"code.fbi.h-da.de/danet/gosdn/controller/config"
 	"code.fbi.h-da.de/danet/gosdn/controller/conflict"
 	"code.fbi.h-da.de/danet/gosdn/controller/customerrs"
 	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/change"
@@ -629,7 +628,7 @@ func (n *NetworkElementServer) addMne(ctx context.Context,
 			return uuid.Nil, err
 		}
 
-		n.networkElementWatchter.SubscribeToNetworkElement(mne, config.GetGnmiSubscriptionPaths(), nil)
+		n.networkElementWatchter.SubscribeToNetworkElement(mne, nil)
 	} else {
 		err = fmt.Errorf("invalid transport data provided")
 		return uuid.Nil, err
diff --git a/controller/nucleus/networkElementWatcher.go b/controller/nucleus/networkElementWatcher.go
index 48d6bc39567e1c570ffe213e5968b84346a5787b..21b910e977f91989ff09fdbc2a06f4d554c64fc4 100644
--- a/controller/nucleus/networkElementWatcher.go
+++ b/controller/nucleus/networkElementWatcher.go
@@ -3,8 +3,10 @@ package nucleus
 import (
 	"context"
 	"fmt"
+	"sort"
 	"strconv"
 
+	"code.fbi.h-da.de/danet/gosdn/controller/config"
 	"code.fbi.h-da.de/danet/gosdn/controller/customerrs"
 	"code.fbi.h-da.de/danet/gosdn/controller/event"
 	eventInterfaces "code.fbi.h-da.de/danet/gosdn/controller/interfaces/event"
@@ -14,6 +16,7 @@ import (
 	"code.fbi.h-da.de/danet/gosdn/forks/goarista/gnmi"
 	"github.com/google/uuid"
 	gpb "github.com/openconfig/gnmi/proto/gnmi"
+	ygotutil "github.com/openconfig/ygot/util"
 	"github.com/openconfig/ygot/ygot"
 	log "github.com/sirupsen/logrus"
 )
@@ -51,14 +54,12 @@ func NewNetworkElementWatcher(mneService networkelement.Service, eventService ev
 }
 
 // SubscribeToNetworkElements subscribes to every available network element in each network domain according to provided SubscribeOptions.
-// Paths should be provided in the following format [][]string{{"system", "config", "hostname"}}
 // SubscribeOptions can be nil. Use nil for a fixed, pre-defined set of gNMI subscription options (streaming in sample mode each second).
-func (n *NetworkElementWatcher) SubscribeToNetworkElements(paths [][]string, opts *gnmi.SubscribeOptions) {
+func (n *NetworkElementWatcher) SubscribeToNetworkElements(opts *gnmi.SubscribeOptions) {
 	if opts == nil {
 		opts = &gnmi.SubscribeOptions{
 			Mode:           gNMISubscribeMode,
 			StreamMode:     gNMIStreamMode,
-			Paths:          paths,
 			SampleInterval: subscribeSampleInterval,
 		}
 	}
@@ -75,14 +76,12 @@ func (n *NetworkElementWatcher) SubscribeToNetworkElements(paths [][]string, opt
 }
 
 // SubscribeToNetworkElement subscribes to the provided network element according to provided SubscribeOptions.
-// Paths should be provided in the following format [][]string{{"system", "config", "hostname"}}
 // SubscribeOptions can be nil. Use nil for a fixed, pre-defined set of gNMI subscription options (streaming in sample mode each second).
-func (n *NetworkElementWatcher) SubscribeToNetworkElement(mne networkelement.NetworkElement, paths [][]string, opts *gnmi.SubscribeOptions) {
+func (n *NetworkElementWatcher) SubscribeToNetworkElement(mne networkelement.NetworkElement, opts *gnmi.SubscribeOptions) {
 	if opts == nil {
 		opts = &gnmi.SubscribeOptions{
 			Mode:           gNMISubscribeMode,
 			StreamMode:     gNMIStreamMode,
-			Paths:          paths,
 			SampleInterval: subscribeSampleInterval,
 		}
 	}
@@ -98,14 +97,14 @@ func (n *NetworkElementWatcher) subscribeToNetworkElement(mne networkelement.Net
 		stopFunc:         cancel,
 	})
 
+	opts.Paths = n.mergeGnmiSubscriptions(mne.GetGnmiSubscriptionPaths(), config.GetGnmiSubscriptionPaths())
+
 	go n.callSubscribe(stopContext, mne, opts)
 }
 
 // callSubscribe spawns a worker pool to handle gNMI subscription updates for each individual subscription
 // and then sets up the gNMI subscription listener.
 func (n *NetworkElementWatcher) callSubscribe(stopContext context.Context, mne networkelement.NetworkElement, opts *gnmi.SubscribeOptions) {
-	opts.Paths = mne.GetGnmiSubscriptionPaths()
-
 	gNMIOptionsCtx := context.Background()
 	gNMIOptionsCtx = context.WithValue(gNMIOptionsCtx, types.CtxKeyOpts, opts)
 
@@ -212,21 +211,38 @@ func (n *NetworkElementWatcher) handleSubscribeResponseUpdate(resp *gpb.Subscrib
 	}
 }
 
-// TODO(faseid): implement path join!
-// func (n *NetworkElementWatcher) joinGnmiSubscriptions(gNMISusbcriptionPathsFromMne, gNMISusbcriptionPathsFromConfig [][]string) [][]string {
-// 	var joinedPaths = gNMISusbcriptionPathsFromMne
-
-//     for i, _ := range gNMISusbcriptionPathsFromMne {
+// mergeGnmiSubscriptions takes paths for gNMI Subscriptions from two sources (the MNE and a config file)
+// and merges them to one set of subscription paths without duplicates.
+// Paths should be provided in the following format [][]string{{"system", "config", "hostname"}}.
+func (n *NetworkElementWatcher) mergeGnmiSubscriptions(gNMISusbcriptionPathsFromMne, gNMISusbcriptionPathsFromConfig [][]string) [][]string {
+	// create slice with all elements
+	var tempJoinedPaths = gNMISusbcriptionPathsFromMne
 
-//     }
+	for _, configPath := range gNMISusbcriptionPathsFromConfig {
+		tempJoinedPaths = append(tempJoinedPaths, configPath)
+	}
 
-// 	for _, mnePath := range joinedPaths {
-// 		for _, configPath := range gNMISusbcriptionPathsFromConfig {
-//             if mnePath != configPath {
+	// sort slice
+	sort.Slice(tempJoinedPaths[:], func(i, j int) bool {
+		for elem := range tempJoinedPaths[i] {
+			if tempJoinedPaths[i][elem] == tempJoinedPaths[j][elem] {
+				continue
+			}
+			return tempJoinedPaths[i][elem] < tempJoinedPaths[j][elem]
+		}
+		return false
+	})
 
-//             }
-// 		}
-// 	}
+	// remove duplicates
+	inResult := make(map[string]bool)
+	var joinedPaths [][]string
+	for _, pathSlice := range tempJoinedPaths {
+		path := ygotutil.SlicePathToString(pathSlice)
+		if _, ok := inResult[path]; !ok {
+			inResult[path] = true
+			joinedPaths = append(joinedPaths, pathSlice)
+		}
+	}
 
-// 	return joinedPaths
-// }
+	return joinedPaths
+}