diff --git a/dapps/networkdelay/dapp.go b/dapps/networkdelay/dapp.go
index 36611d18db9398465168fe0d19358021db196b9f..9e45e4a8f39b916e41ba0653cb2568ee9d366643 100644
--- a/dapps/networkdelay/dapp.go
+++ b/dapps/networkdelay/dapp.go
@@ -2,6 +2,7 @@ package networkdelay
 
 import (
 	"fmt"
+	"sync"
 	"time"
 
 	"github.com/iotaledger/goshimmer/packages/binary/messagelayer/message"
@@ -29,7 +30,8 @@ const (
 
 var (
 	// App is the "plugin" instance of the network delay application.
-	App = node.NewPlugin(PluginName, node.Disabled, configure)
+	app *node.Plugin
+	once sync.Once
 
 	// log holds a reference to the logger used by this app.
 	log *logger.Logger
@@ -41,6 +43,14 @@ var (
 	originPublicKey ed25519.PublicKey
 )
 
+// App gets the plugin instance.
+func App() *node.Plugin {
+	once.Do(func () {
+		app =  node.NewPlugin(PluginName, node.Disabled, configure)
+	})
+	return app
+}
+
 func configure(_ *node.Plugin) {
 	// configure logger
 	log = logger.NewLogger(PluginName)
@@ -53,7 +63,7 @@ func configure(_ *node.Plugin) {
 	}
 
 	// get origin public key from config
-	bytes, err := base58.Decode(config.Node.GetString(CfgNetworkDelayOriginPublicKey))
+	bytes, err := base58.Decode(config.Node().GetString(CfgNetworkDelayOriginPublicKey))
 	if err != nil {
 		log.Fatalf("could not parse %s config entry as base58. %v", CfgNetworkDelayOriginPublicKey, err)
 	}
@@ -65,7 +75,7 @@ func configure(_ *node.Plugin) {
 	configureWebAPI()
 
 	// subscribe to message-layer
-	messagelayer.Tangle.Events.MessageSolid.Attach(events.NewClosure(onReceiveMessageFromMessageLayer))
+	messagelayer.Tangle().Events.MessageSolid.Attach(events.NewClosure(onReceiveMessageFromMessageLayer))
 }
 
 func onReceiveMessageFromMessageLayer(cachedMessage *message.CachedMessage, cachedMessageMetadata *messageTangle.CachedMessageMetadata) {
diff --git a/dapps/networkdelay/webapi.go b/dapps/networkdelay/webapi.go
index b7ecf54f5fbf20c0e81e33c3e7dd0a5473f00727..53f72ea6f2da3336e2bc5f3153ab95fff80fbab0 100644
--- a/dapps/networkdelay/webapi.go
+++ b/dapps/networkdelay/webapi.go
@@ -11,7 +11,7 @@ import (
 )
 
 func configureWebAPI() {
-	webapi.Server.POST("networkdelay", broadcastNetworkDelayObject)
+	webapi.Server().POST("networkdelay", broadcastNetworkDelayObject)
 }
 
 // broadcastNetworkDelayObject creates a message with a network delay object and
diff --git a/dapps/valuetransfers/dapp.go b/dapps/valuetransfers/dapp.go
index 9015d18aff916c08e2ce82c343c449a6b2e507ba..88be707b0de3b23eedca4c5840c8716b7634edd9 100644
--- a/dapps/valuetransfers/dapp.go
+++ b/dapps/valuetransfers/dapp.go
@@ -44,17 +44,19 @@ func init() {
 }
 
 var (
-	// App is the "plugin" instance of the value-transfers application.
-	App = node.NewPlugin(PluginName, node.Enabled, configure, run)
+	// app is the "plugin" instance of the value-transfers application.
+	app     *node.Plugin
+	appOnce sync.Once
 
-	// Tangle represents the value tangle that is used to express votes on value transactions.
-	Tangle *tangle.Tangle
+	// _tangle represents the value tangle that is used to express votes on value transactions.
+	_tangle    *tangle.Tangle
+	tangleOnce sync.Once
 
-	// FCOB contains the fcob consensus logic.
-	FCOB *consensus.FCOB
+	// fcob contains the fcob consensus logic.
+	fcob *consensus.FCOB
 
-	// LedgerState represents the ledger state, that keeps track of the liked branches and offers an API to access funds.
-	LedgerState *tangle.LedgerState
+	// ledgerState represents the ledger state, that keeps track of the liked branches and offers an API to access funds.
+	ledgerState *tangle.LedgerState
 
 	// log holds a reference to the logger used by this app.
 	log *logger.Logger
@@ -66,15 +68,44 @@ var (
 	valueObjectFactoryOnce sync.Once
 )
 
+// App gets the plugin instance.
+func App() *node.Plugin {
+	appOnce.Do(func() {
+		app = node.NewPlugin(PluginName, node.Enabled, configure, run)
+	})
+	return app
+}
+
+// Tangle gets the tangle instance.
+// tangle represents the value tangle that is used to express votes on value transactions.
+func Tangle() *tangle.Tangle {
+	tangleOnce.Do(func() {
+		_tangle = tangle.New(database.Store())
+	})
+	return _tangle
+}
+
+// FCOB gets the fcob instance.
+// fcob contains the fcob consensus logic.
+func FCOB() *consensus.FCOB {
+	return fcob
+}
+
+// LedgerState gets the ledgerState instance.
+// ledgerState represents the ledger state, that keeps track of the liked branches and offers an API to access funds.
+func LedgerState() *tangle.LedgerState {
+	return ledgerState
+}
+
 func configure(_ *node.Plugin) {
 	// configure logger
 	log = logger.NewLogger(PluginName)
 
 	// configure Tangle
-	Tangle = tangle.New(database.Store())
+	_tangle = Tangle()
 
 	// read snapshot file
-	snapshotFilePath := config.Node.GetString(CfgValueLayerSnapshotFile)
+	snapshotFilePath := config.Node().GetString(CfgValueLayerSnapshotFile)
 	if len(snapshotFilePath) != 0 {
 		snapshot := tangle.Snapshot{}
 		f, err := os.Open(snapshotFilePath)
@@ -84,11 +115,11 @@ func configure(_ *node.Plugin) {
 		if _, err := snapshot.ReadFrom(f); err != nil {
 			log.Panic("could not read snapshot file:", err)
 		}
-		Tangle.LoadSnapshot(snapshot)
+		_tangle.LoadSnapshot(snapshot)
 		log.Infof("read snapshot from %s", snapshotFilePath)
 	}
 
-	Tangle.Events.Error.Attach(events.NewClosure(func(err error) {
+	_tangle.Events.Error.Attach(events.NewClosure(func(err error) {
 		log.Error(err)
 	}))
 
@@ -96,31 +127,31 @@ func configure(_ *node.Plugin) {
 	tipManager = TipManager()
 	valueObjectFactory = ValueObjectFactory()
 
-	Tangle.Events.PayloadLiked.Attach(events.NewClosure(func(cachedPayload *payload.CachedPayload, cachedMetadata *tangle.CachedPayloadMetadata) {
+	_tangle.Events.PayloadLiked.Attach(events.NewClosure(func(cachedPayload *payload.CachedPayload, cachedMetadata *tangle.CachedPayloadMetadata) {
 		cachedMetadata.Release()
 		cachedPayload.Consume(tipManager.AddTip)
 	}))
-	Tangle.Events.PayloadDisliked.Attach(events.NewClosure(func(cachedPayload *payload.CachedPayload, cachedMetadata *tangle.CachedPayloadMetadata) {
+	_tangle.Events.PayloadDisliked.Attach(events.NewClosure(func(cachedPayload *payload.CachedPayload, cachedMetadata *tangle.CachedPayloadMetadata) {
 		cachedMetadata.Release()
 		cachedPayload.Consume(tipManager.RemoveTip)
 	}))
 
 	// configure FCOB consensus rules
-	cfgAvgNetworkDelay := config.Node.GetInt(CfgValueLayerFCOBAverageNetworkDelay)
+	cfgAvgNetworkDelay := config.Node().GetInt(CfgValueLayerFCOBAverageNetworkDelay)
 	log.Infof("avg. network delay configured to %d seconds", cfgAvgNetworkDelay)
-	FCOB = consensus.NewFCOB(Tangle, time.Duration(cfgAvgNetworkDelay)*time.Second)
-	FCOB.Events.Vote.Attach(events.NewClosure(func(id string, initOpn vote.Opinion) {
+	fcob = consensus.NewFCOB(_tangle, time.Duration(cfgAvgNetworkDelay)*time.Second)
+	fcob.Events.Vote.Attach(events.NewClosure(func(id string, initOpn vote.Opinion) {
 		if err := voter.Vote(id, initOpn); err != nil {
 			log.Warnf("FPC vote: %s", err)
 		}
 	}))
-	FCOB.Events.Error.Attach(events.NewClosure(func(err error) {
+	fcob.Events.Error.Attach(events.NewClosure(func(err error) {
 		log.Errorf("FCOB error: %s", err)
 	}))
 
 	// configure FPC + link to consensus
 	configureFPC()
-	voter.Events().Finalized.Attach(events.NewClosure(FCOB.ProcessVoteResult))
+	voter.Events().Finalized.Attach(events.NewClosure(fcob.ProcessVoteResult))
 	voter.Events().Finalized.Attach(events.NewClosure(func(ev *vote.OpinionEvent) {
 		log.Infof("FPC finalized for transaction with id '%s' - final opinion: '%s'", ev.ID, ev.Opinion)
 	}))
@@ -129,16 +160,16 @@ func configure(_ *node.Plugin) {
 	}))
 
 	// register SignatureFilter in Parser
-	messagelayer.MessageParser.AddMessageFilter(tangle.NewSignatureFilter())
+	messagelayer.MessageParser().AddMessageFilter(tangle.NewSignatureFilter())
 
 	// subscribe to message-layer
-	messagelayer.Tangle.Events.MessageSolid.Attach(events.NewClosure(onReceiveMessageFromMessageLayer))
+	messagelayer.Tangle().Events.MessageSolid.Attach(events.NewClosure(onReceiveMessageFromMessageLayer))
 }
 
 func run(*node.Plugin) {
 	if err := daemon.BackgroundWorker("ValueTangle", func(shutdownSignal <-chan struct{}) {
 		<-shutdownSignal
-		Tangle.Shutdown()
+		_tangle.Shutdown()
 	}, shutdown.PriorityTangle); err != nil {
 		log.Panicf("Failed to start as daemon: %s", err)
 	}
@@ -169,7 +200,7 @@ func onReceiveMessageFromMessageLayer(cachedMessage *message.CachedMessage, cach
 		return
 	}
 
-	Tangle.AttachPayload(valuePayload)
+	_tangle.AttachPayload(valuePayload)
 }
 
 // TipManager returns the TipManager singleton.
diff --git a/dapps/valuetransfers/fpc.go b/dapps/valuetransfers/fpc.go
index 4f975b213327b30c3af696fee81f47cafd5e3bf6..23d271f79a08f2ba7cb29c76df3eb40b15cb15b2 100644
--- a/dapps/valuetransfers/fpc.go
+++ b/dapps/valuetransfers/fpc.go
@@ -79,7 +79,7 @@ func configureFPC() {
 	log = logger.NewLogger(FpcPluginName)
 	lPeer := local.GetInstance()
 
-	bindAddr := config.Node.GetString(CfgFPCBindAddress)
+	bindAddr := config.Node().GetString(CfgFPCBindAddress)
 	_, portStr, err := net.SplitHostPort(bindAddr)
 	if err != nil {
 		log.Fatalf("FPC bind address '%s' is invalid: %s", bindAddr, err)
@@ -104,7 +104,7 @@ func runFPC() {
 	const ServerWorkerName = "FPCVoterServer"
 	if err := daemon.BackgroundWorker(ServerWorkerName, func(shutdownSignal <-chan struct{}) {
 		stopped := make(chan struct{})
-		bindAddr := config.Node.GetString(CfgFPCBindAddress)
+		bindAddr := config.Node().GetString(CfgFPCBindAddress)
 		voterServer = votenet.New(Voter(), func(id string) vote.Opinion {
 			branchID, err := branchmanager.BranchIDFromBase58(id)
 			if err != nil {
@@ -113,7 +113,7 @@ func runFPC() {
 				return vote.Unknown
 			}
 
-			cachedBranch := Tangle.BranchManager().Branch(branchID)
+			cachedBranch := _tangle.BranchManager().Branch(branchID)
 			defer cachedBranch.Release()
 
 			branch := cachedBranch.Unwrap()
diff --git a/pluginmgr/core/plugins.go b/pluginmgr/core/plugins.go
index 7bdae01c301a5d6f8945a630cd98dd18c57c0fbf..13e028867a30dda7a6867aecf7d5042315dad238 100644
--- a/pluginmgr/core/plugins.go
+++ b/pluginmgr/core/plugins.go
@@ -24,22 +24,22 @@ import (
 )
 
 var PLUGINS = node.Plugins(
-	banner.Plugin,
-	config.Plugin,
-	logger.Plugin,
-	cli.Plugin,
-	portcheck.Plugin,
-	profiling.Plugin,
-	database.Plugin,
-	autopeering.Plugin,
+	banner.Plugin(),
+	config.Plugin(),
+	logger.Plugin(),
+	cli.Plugin(),
+	portcheck.Plugin(),
+	profiling.Plugin(),
+	database.Plugin(),
+	autopeering.Plugin(),
 	pow.Plugin,
-	messagelayer.Plugin,
-	gossip.Plugin,
-	issuer.Plugin,
-	bootstrap.Plugin,
-	sync.Plugin,
-	gracefulshutdown.Plugin,
-	metrics.Plugin,
-	drng.Plugin,
-	valuetransfers.App,
+	messagelayer.Plugin(),
+	gossip.Plugin(),
+	issuer.Plugin(),
+	bootstrap.Plugin(),
+	sync.Plugin(),
+	gracefulshutdown.Plugin(),
+	metrics.Plugin(),
+	drng.Plugin(),
+	valuetransfers.App(),
 )
diff --git a/pluginmgr/research/plugins.go b/pluginmgr/research/plugins.go
index 1275898c7d35401f7db62d3c804f88b50e8bd019..66e4037f1494e4443988c35e824e20376e4b8ca1 100644
--- a/pluginmgr/research/plugins.go
+++ b/pluginmgr/research/plugins.go
@@ -11,10 +11,10 @@ import (
 )
 
 var PLUGINS = node.Plugins(
-	remotelog.Plugin,
-	analysisserver.Plugin,
-	analysisclient.Plugin,
-	analysisdashboard.Plugin,
+	remotelog.Plugin(),
+	analysisserver.Plugin(),
+	analysisclient.Plugin(),
+	analysisdashboard.Plugin(),
 	prometheus.Plugin,
-	networkdelay.App,
+	networkdelay.App(),
 )
diff --git a/pluginmgr/ui/plugins.go b/pluginmgr/ui/plugins.go
index 0cb1418a869694682102adac11fa348d95722a32..e3a2dc1a71c2b565e34b1eb8e9ec545e95872863 100644
--- a/pluginmgr/ui/plugins.go
+++ b/pluginmgr/ui/plugins.go
@@ -6,5 +6,5 @@ import (
 )
 
 var PLUGINS = node.Plugins(
-	dashboard.Plugin,
+	dashboard.Plugin(),
 )
diff --git a/pluginmgr/webapi/plugins.go b/pluginmgr/webapi/plugins.go
index 11df33b279241384ec2669b08f688b43ff2ea6f1..807a01e7a9beb2502b6071e53b9a2fff62834ac9 100644
--- a/pluginmgr/webapi/plugins.go
+++ b/pluginmgr/webapi/plugins.go
@@ -15,14 +15,14 @@ import (
 )
 
 var PLUGINS = node.Plugins(
-	webapi.Plugin,
-	webauth.Plugin,
-	spammer.Plugin,
-	data.Plugin,
-	drng.Plugin,
-	healthz.Plugin,
-	message.Plugin,
-	autopeering.Plugin,
-	info.Plugin,
-	value.Plugin,
+	webapi.Plugin(),
+	webauth.Plugin(),
+	spammer.Plugin(),
+	data.Plugin(),
+	drng.Plugin(),
+	healthz.Plugin(),
+	message.Plugin(),
+	autopeering.Plugin(),
+	info.Plugin(),
+	value.Plugin(),
 )
diff --git a/plugins/analysis/client/plugin.go b/plugins/analysis/client/plugin.go
index 7108fd4b44fa39464e03db3c62eda509dc3df1e3..734e3507fe7d6e8db04e0899f8e5d536758c93e3 100644
--- a/plugins/analysis/client/plugin.go
+++ b/plugins/analysis/client/plugin.go
@@ -1,6 +1,7 @@
 package client
 
 import (
+	"sync"
 	"time"
 
 	"github.com/iotaledger/goshimmer/dapps/valuetransfers"
@@ -30,16 +31,26 @@ func init() {
 }
 
 var (
-	// Plugin is the plugin instance of the analysis client plugin.
-	Plugin = node.NewPlugin(PluginName, node.Enabled, run)
-	conn   *Connector
-	log    *logger.Logger
+	// plugin is the plugin instance of the analysis client plugin.
+	plugin   *node.Plugin
+	once     sync.Once
+	log      *logger.Logger
+	conn     *Connector
+	connLock sync.Mutex
 )
 
+// Plugin gets the plugin instance
+func Plugin() *node.Plugin {
+	once.Do(func() {
+		plugin = node.NewPlugin(PluginName, node.Enabled, run)
+	})
+	return plugin
+}
+
 func run(_ *node.Plugin) {
 	finalized = make(map[string]vote.Opinion)
 	log = logger.NewLogger(PluginName)
-	conn = NewConnector("tcp", config.Node.GetString(CfgServerAddress))
+	conn = NewConnector("tcp", config.Node().GetString(CfgServerAddress))
 
 	if err := daemon.BackgroundWorker(PluginName, func(shutdownSignal <-chan struct{}) {
 		conn.Start()
diff --git a/plugins/analysis/dashboard/fpc_livefeed.go b/plugins/analysis/dashboard/fpc_livefeed.go
index 73160c6de346d55db83ed814b3ddbeb0535d5cc7..00ee50a81447c4cb0aa6bb4f4c651bbda09ce56a 100644
--- a/plugins/analysis/dashboard/fpc_livefeed.go
+++ b/plugins/analysis/dashboard/fpc_livefeed.go
@@ -41,7 +41,7 @@ type FPCUpdate struct {
 
 func configureFPCLiveFeed() {
 
-	if config.Node.GetBool(CfgMongoDBEnabled) {
+	if config.Node().GetBool(CfgMongoDBEnabled) {
 		mongoDB()
 	}
 
@@ -51,7 +51,7 @@ func configureFPCLiveFeed() {
 		task.Return(nil)
 	}, workerpool.WorkerCount(fpcLiveFeedWorkerCount), workerpool.QueueSize(fpcLiveFeedWorkerQueueSize))
 
-	if config.Node.GetBool(CfgMongoDBEnabled) {
+	if config.Node().GetBool(CfgMongoDBEnabled) {
 		fpcStoreFinalizedWorkerPool = workerpool.New(func(task workerpool.Task) {
 			storeFinalizedVoteContext(task.Param(0).(FPCRecords))
 			task.Return(nil)
@@ -69,7 +69,7 @@ func runFPCLiveFeed() {
 		fpcLiveFeedWorkerPool.Start()
 		defer fpcLiveFeedWorkerPool.Stop()
 
-		if config.Node.GetBool(CfgMongoDBEnabled) {
+		if config.Node().GetBool(CfgMongoDBEnabled) {
 			fpcStoreFinalizedWorkerPool.Start()
 			defer fpcStoreFinalizedWorkerPool.Stop()
 		}
@@ -150,7 +150,7 @@ func createFPCUpdate(hb *packet.FPCHeartbeat) *FPCUpdate {
 		})
 	}
 
-	if config.Node.GetBool(CfgMongoDBEnabled) {
+	if config.Node().GetBool(CfgMongoDBEnabled) {
 		fpcStoreFinalizedWorkerPool.TrySubmit(finalizedConflicts)
 	}
 
diff --git a/plugins/analysis/dashboard/fpc_storage.go b/plugins/analysis/dashboard/fpc_storage.go
index 47607b627b38049247d09353e2ed69719f1236be..66506742d89d6f184630889b3fd40a5561acde25 100644
--- a/plugins/analysis/dashboard/fpc_storage.go
+++ b/plugins/analysis/dashboard/fpc_storage.go
@@ -56,9 +56,9 @@ func mongoDB() *mongo.Database {
 }
 
 func newMongoDB() (*mongo.Client, error) {
-	username := config.Node.GetString(CfgMongoDBUsername)
-	password := config.Node.GetString(CfgMongoDBPassword)
-	hostAddr := config.Node.GetString(CfgMongoDBHostAddress)
+	username := config.Node().GetString(CfgMongoDBUsername)
+	password := config.Node().GetString(CfgMongoDBPassword)
+	hostAddr := config.Node().GetString(CfgMongoDBHostAddress)
 
 	client, err := mongo.NewClient(options.Client().ApplyURI("mongodb://" + username + ":" + password + "@" + hostAddr))
 	if err != nil {
diff --git a/plugins/analysis/dashboard/plugin.go b/plugins/analysis/dashboard/plugin.go
index 0d3817b561b24ffc0ecbc05f99bdcaab8c29fb3d..da6ab6e0ad79f52d2e44cb33bd9b8e83fde8720c 100644
--- a/plugins/analysis/dashboard/plugin.go
+++ b/plugins/analysis/dashboard/plugin.go
@@ -19,13 +19,18 @@ import (
 const PluginName = "Analysis-Dashboard"
 
 var (
-	// Plugin is the plugin instance of the dashboard plugin.
-	Plugin = node.NewPlugin(PluginName, node.Disabled, configure, run)
+	// plugin is the plugin instance of the dashboard plugin.
+	plugin = node.NewPlugin(PluginName, node.Disabled, configure, run)
 
 	log    *logger.Logger
 	server *echo.Echo
 )
 
+// Plugin gets the plugin instance
+func Plugin() *node.Plugin {
+	return plugin
+}
+
 func configure(plugin *node.Plugin) {
 	log = logger.NewLogger(plugin.Name)
 	configureFPCLiveFeed()
@@ -40,10 +45,10 @@ func configureServer() {
 	server.HidePort = true
 	server.Use(middleware.Recover())
 
-	if config.Node.GetBool(CfgBasicAuthEnabled) {
+	if config.Node().GetBool(CfgBasicAuthEnabled) {
 		server.Use(middleware.BasicAuth(func(username, password string, c echo.Context) (bool, error) {
-			if username == config.Node.GetString(CfgBasicAuthUsername) &&
-				password == config.Node.GetString(CfgBasicAuthPassword) {
+			if username == config.Node().GetString(CfgBasicAuthUsername) &&
+				password == config.Node().GetString(CfgBasicAuthPassword) {
 				return true, nil
 			}
 			return false, nil
@@ -71,7 +76,7 @@ func worker(shutdownSignal <-chan struct{}) {
 	defer log.Infof("Stopping %s ... done", PluginName)
 
 	stopped := make(chan struct{})
-	bindAddr := config.Node.GetString(CfgBindAddress)
+	bindAddr := config.Node().GetString(CfgBindAddress)
 	go func() {
 		log.Infof("%s started, bind-address=%s", PluginName, bindAddr)
 		if err := server.Start(bindAddr); err != nil {
diff --git a/plugins/analysis/dashboard/routes.go b/plugins/analysis/dashboard/routes.go
index 1ffc810bafdb4ac2e7c151873ecfef0da2c0bf0a..442af15b3f604d66c1c97a10437d51c5d1725e23 100644
--- a/plugins/analysis/dashboard/routes.go
+++ b/plugins/analysis/dashboard/routes.go
@@ -28,7 +28,7 @@ var appBox = packr.New("AnalysisDashboard_App", "./frontend/build")
 var assetsBox = packr.New("AnalysisDashboard_Assets", "./frontend/src/assets")
 
 func indexRoute(e echo.Context) error {
-	if config.Node.GetBool(CfgDev) {
+	if config.Node().GetBool(CfgDev) {
 		res, err := http.Get("http://127.0.0.1:9090/")
 		if err != nil {
 			return err
@@ -48,7 +48,7 @@ func indexRoute(e echo.Context) error {
 
 func setupRoutes(e *echo.Echo) {
 
-	if config.Node.GetBool("analysis.dashboard.dev") {
+	if config.Node().GetBool("analysis.dashboard.dev") {
 		e.Static("/assets", "./plugins/analysis/dashboard/frontend/src/assets")
 	} else {
 
diff --git a/plugins/analysis/packet/fpc_heartbeat.go b/plugins/analysis/packet/fpc_heartbeat.go
index 2746abe2b91af1d48d0c22c519f0817dd5d5cb5a..3c64aafc285011f91258e7717798225508a1adbd 100644
--- a/plugins/analysis/packet/fpc_heartbeat.go
+++ b/plugins/analysis/packet/fpc_heartbeat.go
@@ -5,7 +5,6 @@ import (
 	"encoding/binary"
 	"encoding/gob"
 	"errors"
-
 	"github.com/iotaledger/goshimmer/packages/vote"
 	"github.com/iotaledger/hive.go/protocol/message"
 	"github.com/iotaledger/hive.go/protocol/tlv"
@@ -16,15 +15,6 @@ var (
 	ErrInvalidFPCHeartbeat = errors.New("invalid FPC heartbeat")
 )
 
-var (
-	// FPCHeartbeatMessageDefinition defines a heartbeat message's format.
-	FPCHeartbeatMessageDefinition = &message.Definition{
-		ID:             MessageTypeFPCHeartbeat,
-		MaxBytesLength: 65535,
-		VariableLength: true,
-	}
-)
-
 // FPCHeartbeat represents a heartbeat packet.
 type FPCHeartbeat struct {
 	// The ID of the node who sent the heartbeat.
@@ -36,6 +26,20 @@ type FPCHeartbeat struct {
 	Finalized map[string]vote.Opinion
 }
 
+// FPCHeartbeatMessageDefinition gets the fpcHeartbeatMessageDefinition.
+func FPCHeartbeatMessageDefinition() *message.Definition {
+	// fpcHeartbeatMessageDefinition defines a heartbeat message's format.
+	var fpcHeartbeatMessageDefinition *message.Definition
+	fpcHeartBeatOnce.Do(func(){
+		fpcHeartbeatMessageDefinition = &message.Definition{
+			ID:             MessageTypeFPCHeartbeat,
+			MaxBytesLength: 65535,
+			VariableLength: true,
+		}
+	})
+	return fpcHeartbeatMessageDefinition
+}
+
 // ParseFPCHeartbeat parses a slice of bytes (serialized packet) into a FPC heartbeat.
 func ParseFPCHeartbeat(data []byte) (*FPCHeartbeat, error) {
 	hb := &FPCHeartbeat{}
diff --git a/plugins/analysis/packet/heartbeat.go b/plugins/analysis/packet/heartbeat.go
index 41cfd39bdd3b87197a2f7b514ed327ec0a51fce0..65f75e56358168c3f94f9a88ea5cd89e4279396e 100644
--- a/plugins/analysis/packet/heartbeat.go
+++ b/plugins/analysis/packet/heartbeat.go
@@ -6,7 +6,6 @@ import (
 	"encoding/binary"
 	"errors"
 	"fmt"
-
 	"github.com/iotaledger/hive.go/protocol/message"
 	"github.com/iotaledger/hive.go/protocol/tlv"
 )
@@ -25,9 +24,6 @@ const (
 	HeartbeatPacketPeerIDSize = sha256.Size
 	// HeartbeatPacketOutboundIDCountSize is the byte size of the counter indicating the amount of outbound IDs.
 	HeartbeatPacketOutboundIDCountSize = 1
-)
-
-var (
 	// HeartbeatPacketMinSize is the minimum byte size of a heartbeat packet.
 	HeartbeatPacketMinSize = HeartbeatPacketPeerIDSize + HeartbeatPacketOutboundIDCountSize
 	// HeartbeatPacketMaxSize is the maximum size a heartbeat packet can have.
@@ -35,14 +31,6 @@ var (
 		HeartbeatMaxOutboundPeersCount*sha256.Size + HeartbeatMaxInboundPeersCount*sha256.Size
 )
 
-var (
-	// HeartbeatMessageDefinition defines a heartbeat message's format.
-	HeartbeatMessageDefinition = &message.Definition{
-		ID:             MessageTypeHeartbeat,
-		MaxBytesLength: uint16(HeartbeatPacketMaxSize),
-		VariableLength: true,
-	}
-)
 
 // Heartbeat represents a heartbeat packet.
 type Heartbeat struct {
@@ -57,6 +45,20 @@ type Heartbeat struct {
 	InboundIDs [][]byte
 }
 
+// HeartBeatMessageDefinition gets the heartbeatMessageDefinition.
+func HeartBeatMessageDefinition() *message.Definition{
+	// heartbeatMessageDefinition defines a heartbeat message's format.
+	var heartbeatMessageDefinition *message.Definition
+	heartBeatOnce.Do(func(){
+		heartbeatMessageDefinition = &message.Definition{
+			ID:             MessageTypeHeartbeat,
+			MaxBytesLength: uint16(HeartbeatPacketMaxSize),
+			VariableLength: true,
+		}
+	})
+	return heartbeatMessageDefinition
+}
+
 // ParseHeartbeat parses a slice of bytes (serialized packet) into a heartbeat.
 func ParseHeartbeat(data []byte) (*Heartbeat, error) {
 	// check minimum size
diff --git a/plugins/analysis/packet/packet.go b/plugins/analysis/packet/packet.go
index d95c72d3bd59896597b5000c2e30ee2027127a01..cf5a9740e76a85dab4c378f3f1de2609e0b9870f 100644
--- a/plugins/analysis/packet/packet.go
+++ b/plugins/analysis/packet/packet.go
@@ -2,6 +2,7 @@ package packet
 
 import (
 	"errors"
+	"sync"
 
 	"github.com/iotaledger/hive.go/protocol/message"
 	"github.com/iotaledger/hive.go/protocol/tlv"
@@ -12,16 +13,25 @@ var (
 	ErrMalformedPacket = errors.New("malformed packet")
 )
 
-// AnalysisMsgRegistry holds all message definitions for analysis server related messages
-var AnalysisMsgRegistry *message.Registry
+var (
+	// analysisMsgRegistry holds all message definitions for analysis server related messages
+	analysisMsgRegistry *message.Registry
+	fpcHeartBeatOnce    sync.Once
+	heartBeatOnce       sync.Once
+)
 
 func init() {
 	// message definitions to be registered in registry
 	definitions := []*message.Definition{
 		tlv.HeaderMessageDefinition,
-		HeartbeatMessageDefinition,
-		FPCHeartbeatMessageDefinition,
+		HeartBeatMessageDefinition(),
+		FPCHeartbeatMessageDefinition(),
 		MetricHeartbeatMessageDefinition,
 	}
-	AnalysisMsgRegistry = message.NewRegistry(definitions)
+	analysisMsgRegistry = message.NewRegistry(definitions)
+}
+
+// AnalysisMsgRegistry gets the analysisMsgRegistry.
+func AnalysisMsgRegistry() *message.Registry {
+	return analysisMsgRegistry
 }
diff --git a/plugins/analysis/server/plugin.go b/plugins/analysis/server/plugin.go
index 603fd5c467d0f172f31e38d4fafe9c0a935857ad..6c7173fc3828adca685ff7541a74ec4710866191 100644
--- a/plugins/analysis/server/plugin.go
+++ b/plugins/analysis/server/plugin.go
@@ -5,6 +5,7 @@ import (
 	"net"
 	"strconv"
 	"strings"
+	"sync"
 	"time"
 
 	"github.com/iotaledger/goshimmer/packages/shutdown"
@@ -36,13 +37,22 @@ func init() {
 }
 
 var (
-	// Plugin is the plugin instance of the analysis server plugin.
-	Plugin = node.NewPlugin(PluginName, node.Disabled, configure, run)
+	// plugin is the plugin instance of the analysis server plugin.
+	plugin *node.Plugin
+	once   sync.Once
 	server *tcp.TCPServer
 	prot   *protocol.Protocol
 	log    *logger.Logger
 )
 
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	once.Do(func() {
+		plugin = node.NewPlugin(PluginName, node.Disabled, configure, run)
+	})
+	return plugin
+}
+
 func configure(_ *node.Plugin) {
 	log = logger.NewLogger(PluginName)
 	server = tcp.NewServer()
@@ -54,7 +64,7 @@ func configure(_ *node.Plugin) {
 }
 
 func run(_ *node.Plugin) {
-	bindAddr := config.Node.GetString(CfgAnalysisServerBindAddress)
+	bindAddr := config.Node().GetString(CfgAnalysisServerBindAddress)
 	addr, portStr, err := net.SplitHostPort(bindAddr)
 	if err != nil {
 		log.Fatal("invalid bind address in %s: %s", CfgAnalysisServerBindAddress, err)
@@ -69,7 +79,7 @@ func run(_ *node.Plugin) {
 		defer log.Infof("Stopping %s ... done", PluginName)
 
 		// connect protocol events to processors
-		prot = protocol.New(packet.AnalysisMsgRegistry)
+		prot = protocol.New(packet.AnalysisMsgRegistry())
 		wireUp(prot)
 
 		go server.Listen(addr, port)
diff --git a/plugins/autopeering/autopeering.go b/plugins/autopeering/autopeering.go
index 8f2b7f2604caad4981f235d4d40f452f11b4801b..7b33f4224e548f77467be7a277e2f854f05ec16c 100644
--- a/plugins/autopeering/autopeering.go
+++ b/plugins/autopeering/autopeering.go
@@ -33,8 +33,8 @@ var (
 	// ErrParsingMasterNode is returned for an invalid master node.
 	ErrParsingMasterNode = errors.New("cannot parse master node")
 
-	// NetworkID specifies the autopeering network identifier.
-	NetworkID = hash32([]byte(banner.AppVersion + NetworkVersion))
+	// networkID specifies the autopeering network identifier.
+	networkID = hash32([]byte(banner.AppVersion + NetworkVersion))
 
 	// Conn contains the network connection.
 	Conn *NetConnMetric
@@ -56,6 +56,11 @@ var (
 	}{c: make(chan *server.Server, 1)}
 )
 
+// NetworkID gets the networkID.
+func NetworkID() uint32 {
+	return networkID
+}
+
 // Discovery returns the peer discovery instance.
 func Discovery() *discover.Protocol {
 	peerDiscOnce.Do(createPeerDisc)
@@ -71,7 +76,7 @@ func Selection() *selection.Protocol {
 // BindAddress returns the string form of the autopeering bind address.
 func BindAddress() string {
 	peering := local.GetInstance().Services().Get(service.PeeringKey)
-	host := config.Node.GetString(local.CfgBind)
+	host := config.Node().GetString(local.CfgBind)
 	port := strconv.Itoa(peering.Port())
 	return net.JoinHostPort(host, port)
 }
@@ -97,7 +102,7 @@ func createPeerDisc() {
 	}
 	log.Debugf("Master peers: %v", masterPeers)
 
-	peerDisc = discover.New(local.GetInstance(), ProtocolVersion, NetworkID,
+	peerDisc = discover.New(local.GetInstance(), ProtocolVersion, networkID,
 		discover.Logger(log),
 		discover.MasterPeers(masterPeers),
 	)
@@ -177,7 +182,7 @@ func hash32(b []byte) uint32 {
 }
 
 func parseEntryNodes() (result []*peer.Peer, err error) {
-	for _, entryNodeDefinition := range config.Node.GetStringSlice(CfgEntryNodes) {
+	for _, entryNodeDefinition := range config.Node().GetStringSlice(CfgEntryNodes) {
 		if entryNodeDefinition == "" {
 			continue
 		}
diff --git a/plugins/autopeering/local/local.go b/plugins/autopeering/local/local.go
index b2a211c8a7d005f63e82cd3cc0393ab311577a07..d3fbdf923cad36b8e5ca204ab56a90f42dd24d94 100644
--- a/plugins/autopeering/local/local.go
+++ b/plugins/autopeering/local/local.go
@@ -26,7 +26,7 @@ func configureLocal() *peer.Local {
 	log := logger.NewLogger("Local")
 
 	var peeringIP net.IP
-	if str := config.Node.GetString(CfgExternal); strings.ToLower(str) == "auto" {
+	if str := config.Node().GetString(CfgExternal); strings.ToLower(str) == "auto" {
 		// let the autopeering discover the IP
 		peeringIP = net.IPv4zero
 	} else {
@@ -39,7 +39,7 @@ func configureLocal() *peer.Local {
 		}
 	}
 
-	peeringPort := config.Node.GetInt(CfgPort)
+	peeringPort := config.Node().GetInt(CfgPort)
 	if 0 > peeringPort || peeringPort > 65535 {
 		log.Fatalf("Invalid port number (%s): %d", CfgPort, peeringPort)
 	}
@@ -50,7 +50,7 @@ func configureLocal() *peer.Local {
 
 	// set the private key from the seed provided in the config
 	var seed [][]byte
-	if str := config.Node.GetString(CfgSeed); str != "" {
+	if str := config.Node().GetString(CfgSeed); str != "" {
 		var bytes []byte
 		var err error
 
diff --git a/plugins/autopeering/plugin.go b/plugins/autopeering/plugin.go
index 74aa171c2a368f5247a0224b61a548fce2daead6..c100b9768b4abae3da9ed6276a5421ee2ea804cc 100644
--- a/plugins/autopeering/plugin.go
+++ b/plugins/autopeering/plugin.go
@@ -1,6 +1,7 @@
 package autopeering
 
 import (
+	"sync"
 	"time"
 
 	"github.com/iotaledger/goshimmer/packages/shutdown"
@@ -16,12 +17,21 @@ import (
 const PluginName = "Autopeering"
 
 var (
-	// Plugin is the plugin instance of the autopeering plugin.
-	Plugin = node.NewPlugin(PluginName, node.Enabled, configure, run)
+	// plugin is the plugin instance of the autopeering plugin.
+	plugin *node.Plugin
+	once sync.Once
 
 	log *logger.Logger
 )
 
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	once.Do(func() {
+		plugin =  node.NewPlugin(PluginName, node.Enabled, configure, run)
+	})
+	return plugin
+}
+
 func configure(*node.Plugin) {
 	log = logger.NewLogger(PluginName)
 
diff --git a/plugins/banner/plugin.go b/plugins/banner/plugin.go
index 1f0936a6cd9cfa90a38a840f1cf200ef46883e33..f71fab08b3d5c946700d24ff87a47726682c0a98 100644
--- a/plugins/banner/plugin.go
+++ b/plugins/banner/plugin.go
@@ -2,6 +2,7 @@ package banner
 
 import (
 	"fmt"
+	"sync"
 
 	"github.com/iotaledger/hive.go/node"
 )
@@ -9,8 +10,11 @@ import (
 // PluginName is the name of the banner plugin.
 const PluginName = "Banner"
 
-// Plugin is the plugin instance of the banner plugin.
-var Plugin = node.NewPlugin(PluginName, node.Enabled, configure, run)
+var (
+	// plugin is the plugin instance of the banner plugin.
+	plugin *node.Plugin
+	once sync.Once
+)
 
 const (
 	// AppVersion version number
@@ -20,6 +24,14 @@ const (
 	AppName = "GoShimmer"
 )
 
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	once.Do(func() {
+		plugin =  node.NewPlugin(PluginName, node.Disabled, configure, run)
+	})
+	return plugin
+}
+
 func configure(ctx *node.Plugin) {
 	fmt.Printf(`
    _____  ____   _____ _    _ _____ __  __ __  __ ______ _____  
diff --git a/plugins/bootstrap/plugin.go b/plugins/bootstrap/plugin.go
index 1ebfd520865183b45508c6c2dca6d009618a433a..c1aab9ddcbd8aa4c8f51aa79c023e285108a5a06 100644
--- a/plugins/bootstrap/plugin.go
+++ b/plugins/bootstrap/plugin.go
@@ -1,6 +1,7 @@
 package bootstrap
 
 import (
+	goSync "sync"
 	"time"
 
 	"github.com/iotaledger/goshimmer/packages/binary/spammer"
@@ -32,11 +33,20 @@ func init() {
 }
 
 var (
-	// Plugin is the plugin instance of the bootstrap plugin.
-	Plugin = node.NewPlugin(PluginName, node.Disabled, configure, run)
+	// plugin is the plugin instance of the bootstrap plugin.
+	plugin *node.Plugin
+	once goSync.Once
 	log    *logger.Logger
 )
 
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	once.Do(func() {
+		plugin =  node.NewPlugin(PluginName, node.Disabled, configure, run)
+	})
+	return plugin
+}
+
 func configure(_ *node.Plugin) {
 	log = logger.NewLogger(PluginName)
 	// we're auto. synced if we start in bootstrapping mode
@@ -47,7 +57,7 @@ func configure(_ *node.Plugin) {
 func run(_ *node.Plugin) {
 
 	messageSpammer := spammer.New(issuer.IssuePayload)
-	issuancePeriodSec := config.Node.GetInt(CfgBootstrapInitialIssuanceTimePeriodSec)
+	issuancePeriodSec := config.Node().GetInt(CfgBootstrapInitialIssuanceTimePeriodSec)
 	issuancePeriod := time.Duration(issuancePeriodSec) * time.Second
 
 	// issue messages on top of the genesis
diff --git a/plugins/cli/plugin.go b/plugins/cli/plugin.go
index 99bb6368d2e1c0f960f236fc15e187279bdf2213..8946d22b12173110418873b919446ee8870759bf 100644
--- a/plugins/cli/plugin.go
+++ b/plugins/cli/plugin.go
@@ -3,6 +3,7 @@ package cli
 import (
 	"fmt"
 	"os"
+	"sync"
 
 	"github.com/iotaledger/hive.go/events"
 	"github.com/iotaledger/hive.go/node"
@@ -15,12 +16,23 @@ import (
 const PluginName = "CLI"
 
 var (
-	// Plugin is the plugin instance of the CLI plugin.
-	Plugin  = node.NewPlugin(PluginName, node.Enabled)
+	// plugin is the plugin instance of the CLI plugin.
+	plugin  *node.Plugin
+	once sync.Once
 	version = flag.BoolP("version", "v", false, "Prints the GoShimmer version")
 )
 
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	once.Do(func() {
+		plugin = node.NewPlugin(PluginName, node.Enabled)
+	})
+	return plugin
+}
+
 func init() {
+	plugin = Plugin()
+
 	for name, plugin := range node.GetPlugins() {
 		onAddPlugin(name, plugin.Status)
 	}
@@ -29,7 +41,7 @@ func init() {
 
 	flag.Usage = printUsage
 
-	Plugin.Events.Init.Attach(events.NewClosure(onInit))
+	plugin.Events.Init.Attach(events.NewClosure(onInit))
 }
 
 func onAddPlugin(name string, status int) {
diff --git a/plugins/config/plugin.go b/plugins/config/plugin.go
index da882233e400356dfeffae261fb0e500f37453a4..151ed747fe9d2c8677a5417d991ae754f71b2106 100644
--- a/plugins/config/plugin.go
+++ b/plugins/config/plugin.go
@@ -4,6 +4,7 @@ import (
 	"fmt"
 	"os"
 	"strings"
+	"sync"
 
 	"github.com/iotaledger/hive.go/events"
 	"github.com/iotaledger/hive.go/node"
@@ -16,8 +17,9 @@ import (
 const PluginName = "Config"
 
 var (
-	// Plugin is the plugin instance of the config plugin.
-	Plugin = node.NewPlugin(PluginName, node.Enabled)
+	// plugin is the plugin instance of the config plugin.
+	plugin     *node.Plugin
+	pluginOnce sync.Once
 
 	// flags
 	configName          = flag.StringP("config", "c", "config", "Filename of the config file without the file extension")
@@ -25,19 +27,38 @@ var (
 	skipConfigAvailable = flag.Bool("skip-config", false, "Skip config file availability check")
 
 	// Node is viper
-	Node *viper.Viper
+	_node *viper.Viper
+	nodeOnce sync.Once
 )
 
 // Init triggers the Init event.
 func Init() {
-	Plugin.Events.Init.Trigger(Plugin)
+	plugin.Events.Init.Trigger(plugin)
+}
+
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	pluginOnce.Do(func() {
+		plugin = node.NewPlugin(PluginName, node.Enabled)
+	})
+	return plugin
+}
+
+// Node gets the node.
+func Node() *viper.Viper {
+	nodeOnce.Do(func() {
+		_node = viper.New()
+	})
+	return _node
 }
 
 func init() {
 	// set the default logger config
-	Node = viper.New()
+	_node = Node()
+	plugin = Plugin()
+
 
-	Plugin.Events.Init.Attach(events.NewClosure(func(*node.Plugin) {
+	plugin.Events.Init.Attach(events.NewClosure(func(*node.Plugin) {
 		if err := fetch(false); err != nil {
 			if !*skipConfigAvailable {
 				// we wanted a config file but it was not present
@@ -59,24 +80,25 @@ func init() {
 func fetch(printConfig bool, ignoreSettingsAtPrint ...[]string) error {
 	// replace dots with underscores in env
 	dotReplacer := strings.NewReplacer(".", "_")
-	Node.SetEnvKeyReplacer(dotReplacer)
+	_node.SetEnvKeyReplacer(dotReplacer)
+	// read in ENV variables
 	// read in ENV variables
-	Node.AutomaticEnv()
+	_node.AutomaticEnv()
 
 	flag.Parse()
-	err := parameter.LoadConfigFile(Node, *configDirPath, *configName, true, *skipConfigAvailable)
+	err := parameter.LoadConfigFile(_node, *configDirPath, *configName, true, *skipConfigAvailable)
 	if err != nil {
 		return err
 	}
 
 	if printConfig {
-		parameter.PrintConfig(Node, ignoreSettingsAtPrint...)
+		parameter.PrintConfig(_node, ignoreSettingsAtPrint...)
 	}
 
-	for _, pluginName := range Node.GetStringSlice(node.CFG_DISABLE_PLUGINS) {
+	for _, pluginName := range _node.GetStringSlice(node.CFG_DISABLE_PLUGINS) {
 		node.DisabledPlugins[node.GetPluginIdentifier(pluginName)] = true
 	}
-	for _, pluginName := range Node.GetStringSlice(node.CFG_ENABLE_PLUGINS) {
+	for _, pluginName := range _node.GetStringSlice(node.CFG_ENABLE_PLUGINS) {
 		node.EnabledPlugins[node.GetPluginIdentifier(pluginName)] = true
 	}
 
diff --git a/plugins/dashboard/explorer_routes.go b/plugins/dashboard/explorer_routes.go
index 2f3463548c08d957b2ac867f3e6cebb2219cac44..5dc6bf4a82092477bdf296affcd3d9a27596c14f 100644
--- a/plugins/dashboard/explorer_routes.go
+++ b/plugins/dashboard/explorer_routes.go
@@ -30,7 +30,7 @@ type ExplorerMessage struct {
 
 func createExplorerMessage(msg *message.Message) (*ExplorerMessage, error) {
 	messageID := msg.Id()
-	messageMetadata := messagelayer.Tangle.MessageMetadata(messageID)
+	messageMetadata := messagelayer.Tangle().MessageMetadata(messageID)
 	t := &ExplorerMessage{
 		ID:              messageID.String(),
 		Timestamp:       0,
@@ -119,7 +119,7 @@ func setupExplorerRoutes(routeGroup *echo.Group) {
 }
 
 func findMessage(messageID message.Id) (explorerMsg *ExplorerMessage, err error) {
-	if !messagelayer.Tangle.Message(messageID).Consume(func(msg *message.Message) {
+	if !messagelayer.Tangle().Message(messageID).Consume(func(msg *message.Message) {
 		explorerMsg, err = createExplorerMessage(msg)
 	}) {
 		err = fmt.Errorf("%w: message %s", ErrNotFound, messageID.String())
diff --git a/plugins/dashboard/livefeed.go b/plugins/dashboard/livefeed.go
index f0bebaa62488444d0dfb6025759fa548cf695ed6..8e491becd120cd28f612d878d8af1e54ad27b828 100644
--- a/plugins/dashboard/livefeed.go
+++ b/plugins/dashboard/livefeed.go
@@ -40,11 +40,11 @@ func runLiveFeed() {
 	})
 
 	if err := daemon.BackgroundWorker("Dashboard[MsgUpdater]", func(shutdownSignal <-chan struct{}) {
-		messagelayer.Tangle.Events.MessageAttached.Attach(notifyNewMsg)
+		messagelayer.Tangle().Events.MessageAttached.Attach(notifyNewMsg)
 		liveFeedWorkerPool.Start()
 		<-shutdownSignal
 		log.Info("Stopping Dashboard[MsgUpdater] ...")
-		messagelayer.Tangle.Events.MessageAttached.Detach(notifyNewMsg)
+		messagelayer.Tangle().Events.MessageAttached.Detach(notifyNewMsg)
 		newMsgRateLimiter.Stop()
 		liveFeedWorkerPool.Stop()
 		log.Info("Stopping Dashboard[MsgUpdater] ... done")
diff --git a/plugins/dashboard/plugin.go b/plugins/dashboard/plugin.go
index f0f033aa705e2526f2521dff1fa4bb632ca472bc..b19aaf9ac79041b3507278a532c3a0b0e53290be 100644
--- a/plugins/dashboard/plugin.go
+++ b/plugins/dashboard/plugin.go
@@ -7,6 +7,7 @@ import (
 	"net/http"
 	"runtime"
 	"strconv"
+	"sync"
 	"time"
 
 	"github.com/iotaledger/goshimmer/packages/shutdown"
@@ -30,8 +31,9 @@ import (
 const PluginName = "Dashboard"
 
 var (
-	// Plugin is the plugin instance of the dashboard plugin.
-	Plugin = node.NewPlugin(PluginName, node.Enabled, configure, run)
+	// plugin is the plugin instance of the dashboard plugin.
+	plugin *node.Plugin
+	once sync.Once
 
 	log    *logger.Logger
 	server *echo.Echo
@@ -39,6 +41,14 @@ var (
 	nodeStartAt = time.Now()
 )
 
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	once.Do(func() {
+		plugin = node.NewPlugin(PluginName, node.Enabled, configure, run)
+	})
+	return plugin
+}
+
 func configure(plugin *node.Plugin) {
 	log = logger.NewLogger(plugin.Name)
 	configureWebSocketWorkerPool()
@@ -54,10 +64,10 @@ func configureServer() {
 	server.HidePort = true
 	server.Use(middleware.Recover())
 
-	if config.Node.GetBool(CfgBasicAuthEnabled) {
+	if config.Node().GetBool(CfgBasicAuthEnabled) {
 		server.Use(middleware.BasicAuth(func(username, password string, c echo.Context) (bool, error) {
-			if username == config.Node.GetString(CfgBasicAuthUsername) &&
-				password == config.Node.GetString(CfgBasicAuthPassword) {
+			if username == config.Node().GetString(CfgBasicAuthUsername) &&
+				password == config.Node().GetString(CfgBasicAuthPassword) {
 				return true, nil
 			}
 			return false, nil
@@ -75,7 +85,7 @@ func run(*node.Plugin) {
 	// run the visualizer vertex feed
 	runVisualizer()
 	// run dRNG live feed if dRNG plugin is enabled
-	if !node.IsSkipped(drng.Plugin) {
+	if !node.IsSkipped(drng.Plugin()) {
 		runDrngLiveFeed()
 	}
 
@@ -98,7 +108,7 @@ func worker(shutdownSignal <-chan struct{}) {
 	defer metrics.Events.ReceivedMPSUpdated.Detach(notifyStatus)
 
 	stopped := make(chan struct{})
-	bindAddr := config.Node.GetString(CfgBindAddress)
+	bindAddr := config.Node().GetString(CfgBindAddress)
 	go func() {
 		log.Infof("%s started, bind-address=%s", PluginName, bindAddr)
 		if err := server.Start(bindAddr); err != nil {
diff --git a/plugins/dashboard/routes.go b/plugins/dashboard/routes.go
index 63084bab4b4fa5d67dd747a27a5fa74f55f63e8f..5ae146bff14c2e27d746b23488309af7bb1de703 100644
--- a/plugins/dashboard/routes.go
+++ b/plugins/dashboard/routes.go
@@ -28,7 +28,7 @@ var appBox = packr.New("Dashboard_App", "./frontend/build")
 var assetsBox = packr.New("Dashboard_Assets", "./frontend/src/assets")
 
 func indexRoute(e echo.Context) error {
-	if config.Node.GetBool(CfgDev) {
+	if config.Node().GetBool(CfgDev) {
 		res, err := http.Get("http://127.0.0.1:9090/")
 		if err != nil {
 			return err
@@ -48,7 +48,7 @@ func indexRoute(e echo.Context) error {
 
 func setupRoutes(e *echo.Echo) {
 
-	if config.Node.GetBool("dashboard.dev") {
+	if config.Node().GetBool("dashboard.dev") {
 		e.Static("/assets", "./plugins/dashboard/frontend/src/assets")
 	} else {
 
diff --git a/plugins/dashboard/visualizer.go b/plugins/dashboard/visualizer.go
index 2725f40dcf2a997a3ee7f44d9f1bd206e345a1b7..fab0c7c5955ff1a1ebed3742536299a991695a1e 100644
--- a/plugins/dashboard/visualizer.go
+++ b/plugins/dashboard/visualizer.go
@@ -80,14 +80,14 @@ func runVisualizer() {
 	})
 
 	if err := daemon.BackgroundWorker("Dashboard[Visualizer]", func(shutdownSignal <-chan struct{}) {
-		messagelayer.Tangle.Events.MessageAttached.Attach(notifyNewMsg)
-		defer messagelayer.Tangle.Events.MessageAttached.Detach(notifyNewMsg)
-		messagelayer.Tangle.Events.MessageSolid.Attach(notifyNewMsg)
-		defer messagelayer.Tangle.Events.MessageSolid.Detach(notifyNewMsg)
-		messagelayer.TipSelector.Events.TipAdded.Attach(notifyNewTip)
-		defer messagelayer.TipSelector.Events.TipAdded.Detach(notifyNewTip)
-		messagelayer.TipSelector.Events.TipRemoved.Attach(notifyDeletedTip)
-		defer messagelayer.TipSelector.Events.TipRemoved.Detach(notifyDeletedTip)
+		messagelayer.Tangle().Events.MessageAttached.Attach(notifyNewMsg)
+		defer messagelayer.Tangle().Events.MessageAttached.Detach(notifyNewMsg)
+		messagelayer.Tangle().Events.MessageSolid.Attach(notifyNewMsg)
+		defer messagelayer.Tangle().Events.MessageSolid.Detach(notifyNewMsg)
+		messagelayer.TipSelector().Events.TipAdded.Attach(notifyNewTip)
+		defer messagelayer.TipSelector().Events.TipAdded.Detach(notifyNewTip)
+		messagelayer.TipSelector().Events.TipRemoved.Attach(notifyDeletedTip)
+		defer messagelayer.TipSelector().Events.TipRemoved.Detach(notifyDeletedTip)
 		visualizerWorkerPool.Start()
 		<-shutdownSignal
 		log.Info("Stopping Dashboard[Visualizer] ...")
diff --git a/plugins/dashboard/ws.go b/plugins/dashboard/ws.go
index 7092edfcb4b7ecd60069b548422219109e4c8b48..3288d77d6429b7429f19ea88efac0fdb25b77512 100644
--- a/plugins/dashboard/ws.go
+++ b/plugins/dashboard/ws.go
@@ -48,7 +48,7 @@ func configureWebSocketWorkerPool() {
 		broadcastWsMessage(&wsmsg{MsgTypeMPSMetric, task.Param(0).(uint64)})
 		broadcastWsMessage(&wsmsg{MsgTypeNodeStatus, currentNodeStatus()})
 		broadcastWsMessage(&wsmsg{MsgTypeNeighborMetric, neighborMetrics()})
-		broadcastWsMessage(&wsmsg{MsgTypeTipsMetric, messagelayer.TipSelector.TipCount()})
+		broadcastWsMessage(&wsmsg{MsgTypeTipsMetric, messagelayer.TipSelector().TipCount()})
 		task.Return(nil)
 	}, workerpool.WorkerCount(wsSendWorkerCount), workerpool.QueueSize(wsSendWorkerQueueSize))
 }
diff --git a/plugins/database/plugin.go b/plugins/database/plugin.go
index 1886ddb2db1e35236952cf24282b55d17cbefce4..a3f4d25cd7c4e97c4869f076b5c8861cc3aa5961 100644
--- a/plugins/database/plugin.go
+++ b/plugins/database/plugin.go
@@ -19,15 +19,24 @@ import (
 const PluginName = "Database"
 
 var (
-	// Plugin is the plugin instance of the database plugin.
-	Plugin = node.NewPlugin(PluginName, node.Enabled, configure)
-	log    *logger.Logger
+	// plugin is the plugin instance of the database plugin.
+	plugin     *node.Plugin
+	pluginOnce sync.Once
+	log        *logger.Logger
 
 	db        database.DB
 	store     kvstore.KVStore
 	storeOnce sync.Once
 )
 
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	pluginOnce.Do(func() {
+		plugin = node.NewPlugin(PluginName, node.Enabled, configure)
+	})
+	return plugin
+}
+
 // Store returns the KVStore instance.
 func Store() kvstore.KVStore {
 	storeOnce.Do(createStore)
@@ -43,10 +52,10 @@ func createStore() {
 	log = logger.NewLogger(PluginName)
 
 	var err error
-	if config.Node.GetBool(CfgDatabaseInMemory) {
+	if config.Node().GetBool(CfgDatabaseInMemory) {
 		db, err = database.NewMemDB()
 	} else {
-		dbDir := config.Node.GetString(CfgDatabaseDir)
+		dbDir := config.Node().GetString(CfgDatabaseDir)
 		db, err = database.NewDB(dbDir)
 	}
 	if err != nil {
diff --git a/plugins/drng/drng.go b/plugins/drng/drng.go
index 0d377b27a08b0f0cf2297cbae52fd5333f387758..6bfebe7c3486544bf9eeef52a1759046d7a71898 100644
--- a/plugins/drng/drng.go
+++ b/plugins/drng/drng.go
@@ -29,7 +29,7 @@ func configureDRNG() *drng.DRNG {
 
 	// parse distributed public key of the committee
 	var dpk []byte
-	if str := config.Node.GetString(CfgDRNGDistributedPubKey); str != "" {
+	if str := config.Node().GetString(CfgDRNGDistributedPubKey); str != "" {
 		bytes, err := hex.DecodeString(str)
 		if err != nil {
 			log.Warnf("Invalid %s: %s", CfgDRNGDistributedPubKey, err)
@@ -42,8 +42,8 @@ func configureDRNG() *drng.DRNG {
 
 	// configure committee
 	committeeConf := &state.Committee{
-		InstanceID:    config.Node.GetUint32(CfgDRNGInstanceID),
-		Threshold:     uint8(config.Node.GetUint32(CfgDRNGThreshold)),
+		InstanceID:    config.Node().GetUint32(CfgDRNGInstanceID),
+		Threshold:     uint8(config.Node().GetUint32(CfgDRNGThreshold)),
 		DistributedPK: dpk,
 		Identities:    committeeMembers,
 	}
@@ -58,7 +58,7 @@ func Instance() *drng.DRNG {
 }
 
 func parseCommitteeMembers() (result []ed25519.PublicKey, err error) {
-	for _, committeeMember := range config.Node.GetStringSlice(CfgDRNGCommitteeMembers) {
+	for _, committeeMember := range config.Node().GetStringSlice(CfgDRNGCommitteeMembers) {
 		if committeeMember == "" {
 			continue
 		}
diff --git a/plugins/drng/plugin.go b/plugins/drng/plugin.go
index 294f564d4884d5654cec07b05caa91bead13072b..041c1d5d0c52ef10f60db8178e216343cd7c5161 100644
--- a/plugins/drng/plugin.go
+++ b/plugins/drng/plugin.go
@@ -19,13 +19,23 @@ import (
 const PluginName = "DRNG"
 
 var (
-	// Plugin is the plugin instance of the DRNG plugin.
-	Plugin   = node.NewPlugin(PluginName, node.Enabled, configure, run)
+	// plugin is the plugin instance of the DRNG plugin.
+	plugin   *node.Plugin
+	pluginOnce sync.Once
 	instance *drng.DRNG
 	once     sync.Once
 	log      *logger.Logger
 )
 
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	pluginOnce.Do(func() {
+		plugin = node.NewPlugin(PluginName, node.Enabled, configure, run)
+	})
+	return plugin
+}
+
+
 func configure(_ *node.Plugin) {
 	configureEvents()
 }
@@ -34,7 +44,7 @@ func run(*node.Plugin) {}
 
 func configureEvents() {
 	instance := Instance()
-	messagelayer.Tangle.Events.MessageSolid.Attach(events.NewClosure(func(cachedMessage *message.CachedMessage, cachedMessageMetadata *tangle.CachedMessageMetadata) {
+	messagelayer.Tangle().Events.MessageSolid.Attach(events.NewClosure(func(cachedMessage *message.CachedMessage, cachedMessageMetadata *tangle.CachedMessageMetadata) {
 		cachedMessageMetadata.Release()
 
 		cachedMessage.Consume(func(msg *message.Message) {
diff --git a/plugins/gossip/gossip.go b/plugins/gossip/gossip.go
index 06162245c0e1f2d51740df2420e6b3b325483225..d08d8e61df133348a9e6113752f3475ac021f331 100644
--- a/plugins/gossip/gossip.go
+++ b/plugins/gossip/gossip.go
@@ -39,7 +39,7 @@ func createManager() {
 	log := logger.NewLogger(PluginName)
 
 	// announce the gossip service
-	gossipPort := config.Node.GetInt(CfgGossipPort)
+	gossipPort := config.Node().GetInt(CfgGossipPort)
 	if !netutil.IsValidPort(gossipPort) {
 		log.Fatalf("Invalid port number (%s): %d", CfgGossipPort, gossipPort)
 	}
@@ -60,7 +60,7 @@ func start(shutdownSignal <-chan struct{}) {
 	gossipEndpoint := lPeer.Services().Get(service.GossipKey)
 
 	// resolve the bind address
-	address := net.JoinHostPort(config.Node.GetString(local.CfgBind), strconv.Itoa(gossipEndpoint.Port()))
+	address := net.JoinHostPort(config.Node().GetString(local.CfgBind), strconv.Itoa(gossipEndpoint.Port()))
 	localAddr, err := net.ResolveTCPAddr(gossipEndpoint.Network(), address)
 	if err != nil {
 		log.Fatalf("Error resolving %s: %v", local.CfgBind, err)
@@ -92,7 +92,7 @@ func start(shutdownSignal <-chan struct{}) {
 
 // loads the given message from the message layer or an error if not found.
 func loadMessage(messageID message.Id) (bytes []byte, err error) {
-	if !messagelayer.Tangle.Message(messageID).Consume(func(message *message.Message) {
+	if !messagelayer.Tangle().Message(messageID).Consume(func(message *message.Message) {
 		bytes = message.Bytes()
 	}) {
 		err = ErrMessageNotFound
diff --git a/plugins/gossip/plugin.go b/plugins/gossip/plugin.go
index dfaaa6ade431e810c11d4aa6f71d27b532491c3e..4e62dc9aa548c3acf6c2a3e35669882aaaa8f765 100644
--- a/plugins/gossip/plugin.go
+++ b/plugins/gossip/plugin.go
@@ -13,18 +13,29 @@ import (
 	"github.com/iotaledger/hive.go/events"
 	"github.com/iotaledger/hive.go/logger"
 	"github.com/iotaledger/hive.go/node"
+	"sync"
 )
 
 // PluginName is the name of the gossip plugin.
 const PluginName = "Gossip"
 
 var (
-	// Plugin is the plugin instance of the gossip plugin.
-	Plugin = node.NewPlugin(PluginName, node.Enabled, configure, run)
+	// plugin is the plugin instance of the gossip plugin.
+	plugin *node.Plugin
+	once sync.Once
 
 	log *logger.Logger
 )
 
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	once.Do(func() {
+		plugin = node.NewPlugin(PluginName, node.Enabled, configure, run)
+	})
+	return plugin
+}
+
+
 func configure(*node.Plugin) {
 	log = logger.NewLogger(PluginName)
 
@@ -104,11 +115,11 @@ func configureMessageLayer() {
 
 	// configure flow of incoming messages
 	mgr.Events().MessageReceived.Attach(events.NewClosure(func(event *gossip.MessageReceivedEvent) {
-		messagelayer.MessageParser.Parse(event.Data, event.Peer)
+		messagelayer.MessageParser().Parse(event.Data, event.Peer)
 	}))
 
 	// configure flow of outgoing messages (gossip on solidification)
-	messagelayer.Tangle.Events.MessageSolid.Attach(events.NewClosure(func(cachedMessage *message.CachedMessage, cachedMessageMetadata *tangle.CachedMessageMetadata) {
+	messagelayer.Tangle().Events.MessageSolid.Attach(events.NewClosure(func(cachedMessage *message.CachedMessage, cachedMessageMetadata *tangle.CachedMessageMetadata) {
 		cachedMessageMetadata.Release()
 		cachedMessage.Consume(func(msg *message.Message) {
 			mgr.SendMessage(msg.Bytes())
@@ -116,7 +127,7 @@ func configureMessageLayer() {
 	}))
 
 	// request missing messages
-	messagelayer.MessageRequester.Events.SendRequest.Attach(events.NewClosure(func(messageId message.Id) {
+	messagelayer.MessageRequester().Events.SendRequest.Attach(events.NewClosure(func(messageId message.Id) {
 		mgr.RequestMessage(messageId[:])
 	}))
 }
diff --git a/plugins/gracefulshutdown/plugin.go b/plugins/gracefulshutdown/plugin.go
index 4caf49139575307ac26f07f8b6d9244ae147a485..efa546494613457530faeeb0309693aa954d1d4b 100644
--- a/plugins/gracefulshutdown/plugin.go
+++ b/plugins/gracefulshutdown/plugin.go
@@ -5,6 +5,7 @@ import (
 	"os/signal"
 	"sort"
 	"strings"
+	"sync"
 	"syscall"
 	"time"
 
@@ -20,45 +21,56 @@ const PluginName = "Graceful Shutdown"
 // After that the process is killed.
 const WaitToKillTimeInSeconds = 60
 
-var log *logger.Logger
-var gracefulStop chan os.Signal
+var (
+	// plugin is the plugin instance of the graceful shutdown plugin.
+ 	plugin *node.Plugin
+	once sync.Once
+	log *logger.Logger
+	gracefulStop chan os.Signal
+)
 
-// Plugin is the plugin instance of the graceful shutdown plugin.
-var Plugin = node.NewPlugin(PluginName, node.Enabled, func(plugin *node.Plugin) {
-	log = logger.NewLogger(PluginName)
-	gracefulStop = make(chan os.Signal)
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	once.Do(func() {
+		plugin = node.NewPlugin(PluginName, node.Enabled, func(plugin *node.Plugin) {
+			log = logger.NewLogger(PluginName)
+			gracefulStop = make(chan os.Signal)
 
-	signal.Notify(gracefulStop, syscall.SIGTERM)
-	signal.Notify(gracefulStop, syscall.SIGINT)
+			signal.Notify(gracefulStop, syscall.SIGTERM)
+			signal.Notify(gracefulStop, syscall.SIGINT)
 
-	go func() {
-		<-gracefulStop
+			go func() {
+				<-gracefulStop
 
-		log.Warnf("Received shutdown request - waiting (max %d) to finish processing ...", WaitToKillTimeInSeconds)
+				log.Warnf("Received shutdown request - waiting (max %d) to finish processing ...", WaitToKillTimeInSeconds)
 
-		go func() {
-			start := time.Now()
-			for x := range time.Tick(1 * time.Second) {
-				secondsSinceStart := x.Sub(start).Seconds()
+				go func() {
+					start := time.Now()
+					for x := range time.Tick(1 * time.Second) {
+						secondsSinceStart := x.Sub(start).Seconds()
 
-				if secondsSinceStart <= WaitToKillTimeInSeconds {
-					processList := ""
-					runningBackgroundWorkers := daemon.GetRunningBackgroundWorkers()
-					if len(runningBackgroundWorkers) >= 1 {
-						sort.Strings(runningBackgroundWorkers)
-						processList = "(" + strings.Join(runningBackgroundWorkers, ", ") + ") "
+						if secondsSinceStart <= WaitToKillTimeInSeconds {
+							processList := ""
+							runningBackgroundWorkers := daemon.GetRunningBackgroundWorkers()
+							if len(runningBackgroundWorkers) >= 1 {
+								sort.Strings(runningBackgroundWorkers)
+								processList = "(" + strings.Join(runningBackgroundWorkers, ", ") + ") "
+							}
+							log.Warnf("Received shutdown request - waiting (max %d seconds) to finish processing %s...", WaitToKillTimeInSeconds-int(secondsSinceStart), processList)
+						} else {
+							log.Error("Background processes did not terminate in time! Forcing shutdown ...")
+							os.Exit(1)
+						}
 					}
-					log.Warnf("Received shutdown request - waiting (max %d seconds) to finish processing %s...", WaitToKillTimeInSeconds-int(secondsSinceStart), processList)
-				} else {
-					log.Error("Background processes did not terminate in time! Forcing shutdown ...")
-					os.Exit(1)
-				}
-			}
-		}()
+				}()
+
+				daemon.Shutdown()
+			}()
+		})
+	})
+	return plugin
+}
 
-		daemon.Shutdown()
-	}()
-})
 
 // ShutdownWithError prints out an error message and shuts down the default daemon instance.
 func ShutdownWithError(err error) {
diff --git a/plugins/issuer/plugin.go b/plugins/issuer/plugin.go
index d34e6f3621499a77771f55653ff9b6f29254b6fb..8bc87008fb963db0da6737cc7ebfe52dbe12efc7 100644
--- a/plugins/issuer/plugin.go
+++ b/plugins/issuer/plugin.go
@@ -2,6 +2,7 @@ package issuer
 
 import (
 	"fmt"
+	goSync "sync"
 
 	"github.com/iotaledger/goshimmer/packages/binary/messagelayer/message"
 	"github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload"
@@ -14,10 +15,20 @@ import (
 const PluginName = "Issuer"
 
 var (
-	// Plugin is the plugin instance of the issuer plugin.
-	Plugin = node.NewPlugin(PluginName, node.Enabled, configure)
+	// plugin is the plugin instance of the issuer plugin.
+	plugin *node.Plugin
+	once goSync.Once
+
 )
 
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	once.Do(func() {
+		plugin = node.NewPlugin(PluginName, node.Enabled, configure)
+	})
+	return plugin
+}
+
 func configure(_ *node.Plugin) {}
 
 // IssuePayload issues a payload to the message layer.
@@ -26,5 +37,5 @@ func IssuePayload(payload payload.Payload) (*message.Message, error) {
 	if !sync.Synced() {
 		return nil, fmt.Errorf("can't issue payload: %w", sync.ErrNodeNotSynchronized)
 	}
-	return messagelayer.MessageFactory.IssuePayload(payload), nil
+	return messagelayer.MessageFactory().IssuePayload(payload), nil
 }
diff --git a/plugins/logger/plugin.go b/plugins/logger/plugin.go
index ebe1430995db139074114058d7774b5a4d3ba577..5ab85c84f05b9e926536fc3998f88b48d7c8bbf3 100644
--- a/plugins/logger/plugin.go
+++ b/plugins/logger/plugin.go
@@ -5,24 +5,39 @@ import (
 	"github.com/iotaledger/hive.go/events"
 	"github.com/iotaledger/hive.go/logger"
 	"github.com/iotaledger/hive.go/node"
+	"sync"
 )
 
 // PluginName is the name of the logger plugin.
 const PluginName = "Logger"
 
-// Plugin is the plugin instance of the logger plugin.
-var Plugin = node.NewPlugin(PluginName, node.Enabled)
+var (
+	// plugin is the plugin instance of the logger plugin.
+	plugin *node.Plugin
+	once sync.Once
+)
+
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	once.Do(func() {
+		plugin = node.NewPlugin(PluginName, node.Enabled)
+	})
+	return plugin
+}
+
 
 // Init triggers the Init event.
 func Init() {
-	Plugin.Events.Init.Trigger(Plugin)
+	plugin.Events.Init.Trigger(plugin)
 }
 
 func init() {
+	plugin = Plugin()
+
 	initFlags()
 
-	Plugin.Events.Init.Attach(events.NewClosure(func(*node.Plugin) {
-		if err := logger.InitGlobalLogger(config.Node); err != nil {
+	plugin.Events.Init.Attach(events.NewClosure(func(*node.Plugin) {
+		if err := logger.InitGlobalLogger(config.Node()); err != nil {
 			panic(err)
 		}
 	}))
diff --git a/plugins/messagelayer/plugin.go b/plugins/messagelayer/plugin.go
index ca1fb0e535950b01ec4c74816aae0c30141682bb..d43792edc02368fc39c11c15732f6ba5ded2f8b0 100644
--- a/plugins/messagelayer/plugin.go
+++ b/plugins/messagelayer/plugin.go
@@ -1,6 +1,8 @@
 package messagelayer
 
 import (
+	"sync"
+
 	"github.com/iotaledger/goshimmer/packages/binary/messagelayer/message"
 	"github.com/iotaledger/goshimmer/packages/binary/messagelayer/messagefactory"
 	"github.com/iotaledger/goshimmer/packages/binary/messagelayer/messageparser"
@@ -23,68 +25,122 @@ const (
 )
 
 var (
-	// Plugin is the plugin instance of the message layer plugin.
-	Plugin           = node.NewPlugin(PluginName, node.Enabled, configure, run)
-	MessageParser    *messageparser.MessageParser
-	MessageRequester *messagerequester.MessageRequester
-	TipSelector      *tipselector.TipSelector
-	Tangle           *tangle.Tangle
-	MessageFactory   *messagefactory.MessageFactory
+	// plugin is the plugin instance of the message layer plugin.
+	plugin           *node.Plugin
+	pluginOnce       sync.Once
+	messageParser    *messageparser.MessageParser
+	msgParserOnce    sync.Once
+	messageRequester *messagerequester.MessageRequester
+	msgReqOnce       sync.Once
+	tipSelector      *tipselector.TipSelector
+	tipSelectorOnce  sync.Once
+	_tangle          *tangle.Tangle
+	tangleOnce       sync.Once
+	messageFactory   *messagefactory.MessageFactory
+	msgFactoryOnce   sync.Once
 	log              *logger.Logger
 )
 
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	pluginOnce.Do(func() {
+		plugin = node.NewPlugin(PluginName, node.Enabled, configure, run)
+	})
+	return plugin
+}
+
+// MessageParser gets the messageParser instance.
+func MessageParser() *messageparser.MessageParser {
+	msgParserOnce.Do(func() {
+		messageParser = messageparser.New()
+	})
+	return messageParser
+}
+
+// TipSelector gets the tipSelector instance.
+func TipSelector() *tipselector.TipSelector {
+	tipSelectorOnce.Do(func() {
+		tipSelector = tipselector.New()
+	})
+	return tipSelector
+}
+
+// Tangle gets the tangle instance.
+func Tangle() *tangle.Tangle {
+	tangleOnce.Do(func() {
+		store := database.Store()
+		_tangle = tangle.New(store)
+	})
+	return _tangle
+}
+
+// MessageFactory gets the messageFactory instance.
+func MessageFactory() *messagefactory.MessageFactory {
+	msgFactoryOnce.Do(func() {
+		messageFactory = messagefactory.New(database.Store(), []byte(DBSequenceNumber), local.GetInstance().LocalIdentity(), TipSelector())
+	})
+	return messageFactory
+}
+
+// MessageRequester gets the messageRequester instance.
+func MessageRequester() *messagerequester.MessageRequester {
+	msgReqOnce.Do(func() {
+		messageRequester = messagerequester.New()
+	})
+	return messageRequester
+}
+
 func configure(*node.Plugin) {
 	log = logger.NewLogger(PluginName)
-	store := database.Store()
 
 	// create instances
-	MessageParser = messageparser.New()
-	MessageRequester = messagerequester.New()
-	TipSelector = tipselector.New()
-	Tangle = tangle.New(store)
-
-	// Setup MessageFactory (behavior + logging))
-	MessageFactory = messagefactory.New(database.Store(), []byte(DBSequenceNumber), local.GetInstance().LocalIdentity(), TipSelector)
-	MessageFactory.Events.MessageConstructed.Attach(events.NewClosure(Tangle.AttachMessage))
-	MessageFactory.Events.Error.Attach(events.NewClosure(func(err error) {
+	messageParser = MessageParser()
+	messageRequester = MessageRequester()
+	tipSelector = TipSelector()
+	_tangle = Tangle()
+
+	// Setup messageFactory (behavior + logging))
+	messageFactory = MessageFactory()
+	messageFactory.Events.MessageConstructed.Attach(events.NewClosure(_tangle.AttachMessage))
+	messageFactory.Events.Error.Attach(events.NewClosure(func(err error) {
 		log.Errorf("internal error in message factory: %v", err)
 	}))
 
-	// setup MessageParser
-	MessageParser.Events.MessageParsed.Attach(events.NewClosure(func(msg *message.Message, peer *peer.Peer) {
+	// setup messageParser
+	messageParser.Events.MessageParsed.Attach(events.NewClosure(func(msg *message.Message, peer *peer.Peer) {
 		// TODO: ADD PEER
-		Tangle.AttachMessage(msg)
+		_tangle.AttachMessage(msg)
 	}))
 
-	// setup MessageRequester
-	Tangle.Events.MessageMissing.Attach(events.NewClosure(MessageRequester.ScheduleRequest))
-	Tangle.Events.MissingMessageReceived.Attach(events.NewClosure(func(cachedMessage *message.CachedMessage, cachedMessageMetadata *tangle.CachedMessageMetadata) {
+	// setup messageRequester
+	_tangle.Events.MessageMissing.Attach(events.NewClosure(messageRequester.ScheduleRequest))
+	_tangle.Events.MissingMessageReceived.Attach(events.NewClosure(func(cachedMessage *message.CachedMessage, cachedMessageMetadata *tangle.CachedMessageMetadata) {
 		cachedMessageMetadata.Release()
 		cachedMessage.Consume(func(msg *message.Message) {
-			MessageRequester.StopRequest(msg.Id())
+			messageRequester.StopRequest(msg.Id())
 		})
 	}))
 
-	// setup TipSelector
-	Tangle.Events.MessageSolid.Attach(events.NewClosure(func(cachedMessage *message.CachedMessage, cachedMessageMetadata *tangle.CachedMessageMetadata) {
+	// setup tipSelector
+	_tangle.Events.MessageSolid.Attach(events.NewClosure(func(cachedMessage *message.CachedMessage, cachedMessageMetadata *tangle.CachedMessageMetadata) {
 		cachedMessageMetadata.Release()
-		cachedMessage.Consume(TipSelector.AddTip)
+		cachedMessage.Consume(tipSelector.AddTip)
 	}))
 }
 
 func run(*node.Plugin) {
 
-	if err := daemon.BackgroundWorker("Tangle[MissingMessagesMonitor]", func(shutdownSignal <-chan struct{}) {
-		Tangle.MonitorMissingMessages(shutdownSignal)
+	if err := daemon.BackgroundWorker("_tangle[MissingMessagesMonitor]", func(shutdownSignal <-chan struct{}) {
+		_tangle.MonitorMissingMessages(shutdownSignal)
 	}, shutdown.PriorityMissingMessagesMonitoring); err != nil {
 		log.Panicf("Failed to start as daemon: %s", err)
 	}
 
-	if err := daemon.BackgroundWorker("Tangle", func(shutdownSignal <-chan struct{}) {
+	if err := daemon.BackgroundWorker("_tangle", func(shutdownSignal <-chan struct{}) {
 		<-shutdownSignal
-		MessageFactory.Shutdown()
-		MessageParser.Shutdown()
-		Tangle.Shutdown()
+		messageFactory.Shutdown()
+		messageParser.Shutdown()
+		_tangle.Shutdown()
 	}, shutdown.PriorityTangle); err != nil {
 		log.Panicf("Failed to start as daemon: %s", err)
 	}
diff --git a/plugins/metrics/message.go b/plugins/metrics/message.go
index 569ba349121fc41018d2527fa7d4c68fc86796ef..927ce519c53aa8da031b1dd116d69682885fefb2 100644
--- a/plugins/metrics/message.go
+++ b/plugins/metrics/message.go
@@ -66,7 +66,7 @@ func increasePerPayloadCounter(p payload.Type) {
 }
 
 func measureMessageTips() {
-	metrics.Events().MessageTips.Trigger((uint64)(messagelayer.TipSelector.TipCount()))
+	metrics.Events().MessageTips.Trigger((uint64)(messagelayer.TipSelector().TipCount()))
 }
 
 // ReceivedMessagesPerSecond retrieves the current messages per second number.
diff --git a/plugins/metrics/message_test.go b/plugins/metrics/message_test.go
index 3d1eb537111765793333480cb3f20157c6cb5e23..bdf7925a2a2cc979ca13dc62ed831423ccf1afa4 100644
--- a/plugins/metrics/message_test.go
+++ b/plugins/metrics/message_test.go
@@ -7,7 +7,6 @@ import (
 	valuepayload "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/payload"
 	drngpayload "github.com/iotaledger/goshimmer/packages/binary/drng/payload"
 	"github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload"
-	"github.com/iotaledger/goshimmer/packages/binary/messagelayer/tipselector"
 	"github.com/iotaledger/goshimmer/packages/metrics"
 	"github.com/iotaledger/goshimmer/plugins/messagelayer"
 	"github.com/iotaledger/hive.go/events"
@@ -34,7 +33,7 @@ func TestMessageCountPerPayload(t *testing.T) {
 func TestMessageTips(t *testing.T) {
 	var wg sync.WaitGroup
 	// messagelayer TipSelector not configured here, so to avoid nil pointer panic, we instantiate it
-	messagelayer.TipSelector = tipselector.New()
+	messagelayer.TipSelector()
 	metrics.Events().MessageTips.Attach(events.NewClosure(func(tips uint64) {
 		messageTips.Store(tips)
 		wg.Done()
diff --git a/plugins/metrics/plugin.go b/plugins/metrics/plugin.go
index c7c295f17667e0167c1242f2d66395acfe70ec7c..a60b7be6f95dfdd1d71a5e105eedb420687e3527 100644
--- a/plugins/metrics/plugin.go
+++ b/plugins/metrics/plugin.go
@@ -1,6 +1,7 @@
 package metrics
 
 import (
+	"sync"
 	"time"
 
 	"github.com/iotaledger/goshimmer/dapps/valuetransfers"
@@ -27,30 +28,38 @@ import (
 const PluginName = "Metrics"
 
 var (
-	// Plugin is the plugin instance of the metrics plugin.
-	Plugin = node.NewPlugin(PluginName, node.Enabled, configure, run)
-
-	log *logger.Logger
+	// plugin is the plugin instance of the metrics plugin.
+	plugin *node.Plugin
+	once   sync.Once
+	log    *logger.Logger
 )
 
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	once.Do(func() {
+		plugin = node.NewPlugin(PluginName, node.Enabled, configure, run)
+	})
+	return plugin
+}
+
 func configure(_ *node.Plugin) {
 	log = logger.NewLogger(PluginName)
 }
 
 func run(_ *node.Plugin) {
 
-	if config.Node.GetBool(CfgMetricsLocal) {
+	if config.Node().GetBool(CfgMetricsLocal) {
 		registerLocalMetrics()
 	}
 
 	// Events from analysis server
-	if config.Node.GetBool(CfgMetricsGlobal) {
+	if config.Node().GetBool(CfgMetricsGlobal) {
 		server.Events.MetricHeartbeat.Attach(onMetricHeartbeatReceived)
 	}
 
 	// create a background worker that update the metrics every second
 	if err := daemon.BackgroundWorker("Metrics Updater", func(shutdownSignal <-chan struct{}) {
-		if config.Node.GetBool(CfgMetricsLocal) {
+		if config.Node().GetBool(CfgMetricsLocal) {
 			timeutil.Ticker(func() {
 				measureCPUUsage()
 				measureMemUsage()
@@ -65,7 +74,7 @@ func run(_ *node.Plugin) {
 				gossipCurrentTx.Store(uint64(g.BytesWritten))
 			}, 1*time.Second, shutdownSignal)
 		}
-		if config.Node.GetBool(CfgMetricsGlobal) {
+		if config.Node().GetBool(CfgMetricsGlobal) {
 			timeutil.Ticker(calculateNetworkDiameter, 1*time.Minute, shutdownSignal)
 		}
 
@@ -78,7 +87,7 @@ func registerLocalMetrics() {
 	//// Events declared in other packages which we want to listen to here ////
 
 	// increase received MPS counter whenever we attached a message
-	messagelayer.Tangle.Events.MessageAttached.Attach(events.NewClosure(func(cachedMessage *message.CachedMessage, cachedMessageMetadata *tangle.CachedMessageMetadata) {
+	messagelayer.Tangle().Events.MessageAttached.Attach(events.NewClosure(func(cachedMessage *message.CachedMessage, cachedMessageMetadata *tangle.CachedMessageMetadata) {
 		_payloadType := cachedMessage.Unwrap().Payload().Type()
 		cachedMessage.Release()
 		cachedMessageMetadata.Release()
@@ -87,7 +96,7 @@ func registerLocalMetrics() {
 	}))
 
 	// Value payload attached
-	valuetransfers.Tangle.Events.PayloadAttached.Attach(events.NewClosure(func(cachedPayload *payload.CachedPayload, cachedPayloadMetadata *valuetangle.CachedPayloadMetadata) {
+	valuetransfers.Tangle().Events.PayloadAttached.Attach(events.NewClosure(func(cachedPayload *payload.CachedPayload, cachedPayloadMetadata *valuetangle.CachedPayloadMetadata) {
 		cachedPayload.Release()
 		cachedPayloadMetadata.Release()
 		valueTransactionCounter.Inc()
diff --git a/plugins/portcheck/plugin.go b/plugins/portcheck/plugin.go
index 85ac7a6d034c2110d4b2b6a565a6d48b0382eddc..e1b6845b0c9f000e19a720876afe5756a24749d6 100644
--- a/plugins/portcheck/plugin.go
+++ b/plugins/portcheck/plugin.go
@@ -2,6 +2,7 @@ package portcheck
 
 import (
 	"net"
+	"sync"
 
 	"github.com/iotaledger/goshimmer/plugins/autopeering"
 	"github.com/iotaledger/goshimmer/plugins/autopeering/local"
@@ -17,11 +18,20 @@ import (
 const PluginName = "PortCheck"
 
 var (
-	// Plugin is the plugin instance of the port check plugin.
-	Plugin = node.NewPlugin(PluginName, node.Enabled, configure, run)
+	// plugin is the plugin instance of the port check plugin.
+	plugin *node.Plugin
+	once sync.Once
 	log    *logger.Logger
 )
 
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	once.Do(func() {
+		plugin = node.NewPlugin(PluginName, node.Enabled, configure, run)
+	})
+	return plugin
+}
+
 func configure(*node.Plugin) {
 	log = logger.NewLogger(PluginName)
 }
@@ -49,7 +59,7 @@ func checkAutopeeringConnection() {
 	defer conn.Close()
 
 	// create a new discovery server for the port check
-	disc := discover.New(local.GetInstance(), autopeering.ProtocolVersion, autopeering.NetworkID, discover.Logger(log))
+	disc := discover.New(local.GetInstance(), autopeering.ProtocolVersion, autopeering.NetworkID(), discover.Logger(log))
 	srv := server.Serve(local.GetInstance(), conn, log, disc)
 	defer srv.Close()
 
diff --git a/plugins/pow/plugin.go b/plugins/pow/plugin.go
index 1660eecb7218f1fd39b9a0dbdd5e8423f7f2b058..90b76e0c2f9c12eda2620417554ce286e4c95e65 100644
--- a/plugins/pow/plugin.go
+++ b/plugins/pow/plugin.go
@@ -20,7 +20,7 @@ func run(*node.Plugin) {
 	// assure that the logger is available
 	log := logger.NewLogger(PluginName)
 
-	if node.IsSkipped(messagelayer.Plugin) {
+	if node.IsSkipped(messagelayer.Plugin()) {
 		log.Infof("%s is disabled; skipping %s\n", messagelayer.PluginName, PluginName)
 		return
 	}
@@ -28,6 +28,6 @@ func run(*node.Plugin) {
 	// assure that the PoW worker is initialized
 	worker := Worker()
 
-	messagelayer.MessageParser.AddBytesFilter(builtinfilters.NewPowFilter(worker, difficulty))
-	messagelayer.MessageFactory.SetWorker(messagefactory.WorkerFunc(DoPOW))
+	messagelayer.MessageParser().AddBytesFilter(builtinfilters.NewPowFilter(worker, difficulty))
+	messagelayer.MessageFactory().SetWorker(messagefactory.WorkerFunc(DoPOW))
 }
diff --git a/plugins/pow/pow.go b/plugins/pow/pow.go
index c547d4ae6f78f342b226b42ec794fdca543a7f3c..69207f5b6792ae48585dcaa3c81e3cd0d6ba7225 100644
--- a/plugins/pow/pow.go
+++ b/plugins/pow/pow.go
@@ -41,9 +41,9 @@ func Worker() *pow.Worker {
 	workerOnce.Do(func() {
 		log = logger.NewLogger(PluginName)
 		// load the parameters
-		difficulty = config.Node.GetInt(CfgPOWDifficulty)
-		numWorkers = config.Node.GetInt(CfgPOWNumThreads)
-		timeout = config.Node.GetDuration(CfgPOWTimeout)
+		difficulty = config.Node().GetInt(CfgPOWDifficulty)
+		numWorkers = config.Node().GetInt(CfgPOWNumThreads)
+		timeout = config.Node().GetDuration(CfgPOWTimeout)
 		// create the worker
 		worker = pow.New(hash, numWorkers)
 	})
diff --git a/plugins/profiling/plugin.go b/plugins/profiling/plugin.go
index 388da6453312ed18e7a030241dafbe03eb7af109..4ab416d6e41f3bad7750d2ef7cd9ff3a6c015714 100644
--- a/plugins/profiling/plugin.go
+++ b/plugins/profiling/plugin.go
@@ -3,6 +3,7 @@ package profiling
 import (
 	"net/http"
 	"runtime"
+	"sync"
 
 	// import required to profile
 	_ "net/http/pprof"
@@ -17,14 +18,23 @@ import (
 const PluginName = "Profiling"
 
 var (
-	// Plugin is the profiling plugin.
-	Plugin = node.NewPlugin(PluginName, node.Enabled, configure, run)
+	// plugin is the profiling plugin.
+	plugin *node.Plugin
+	once sync.Once
 	log    *logger.Logger
 )
 
 // CfgProfilingBindAddress defines the config flag of the profiling binding address.
 const CfgProfilingBindAddress = "profiling.bindAddress"
 
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	once.Do(func() {
+		plugin = node.NewPlugin(PluginName, node.Enabled, configure, run)
+	})
+	return plugin
+}
+
 func init() {
 	flag.String(CfgProfilingBindAddress, "127.0.0.1:6061", "bind address for the pprof server")
 }
@@ -34,7 +44,7 @@ func configure(_ *node.Plugin) {
 }
 
 func run(_ *node.Plugin) {
-	bindAddr := config.Node.GetString(CfgProfilingBindAddress)
+	bindAddr := config.Node().GetString(CfgProfilingBindAddress)
 
 	runtime.SetMutexProfileFraction(5)
 	runtime.SetBlockProfileRate(5)
diff --git a/plugins/prometheus/db_size.go b/plugins/prometheus/db_size.go
index 99408a8e692fea1d8633da4ac7c52d66d6302bf7..df6e1372ed97805b0c1a22d3c72d37608ff3eab9 100644
--- a/plugins/prometheus/db_size.go
+++ b/plugins/prometheus/db_size.go
@@ -27,7 +27,7 @@ func registerDBMetrics() {
 }
 
 func collectDBSize() {
-	size, err := directorySize(config.Node.GetString(database.CfgDatabaseDir))
+	size, err := directorySize(config.Node().GetString(database.CfgDatabaseDir))
 	if err == nil {
 		dbSize.Set(float64(size))
 	}
diff --git a/plugins/prometheus/plugin.go b/plugins/prometheus/plugin.go
index 8aa2f765e07ed52910b7e66ce7327827ca4213e4..5f32a260f1d88e7b54efab6614f7709b0e71c207 100644
--- a/plugins/prometheus/plugin.go
+++ b/plugins/prometheus/plugin.go
@@ -29,14 +29,14 @@ var (
 func configure(plugin *node.Plugin) {
 	log = logger.NewLogger(plugin.Name)
 
-	if config.Node.GetBool(CfgPrometheusGoMetrics) {
+	if config.Node().GetBool(CfgPrometheusGoMetrics) {
 		registry.MustRegister(prometheus.NewGoCollector())
 	}
-	if config.Node.GetBool(CfgPrometheusProcessMetrics) {
+	if config.Node().GetBool(CfgPrometheusProcessMetrics) {
 		registry.MustRegister(prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{}))
 	}
 
-	if config.Node.GetBool(metrics.CfgMetricsLocal) {
+	if config.Node().GetBool(metrics.CfgMetricsLocal) {
 		registerAutopeeringMetrics()
 		registerDBMetrics()
 		registerFPCMetrics()
@@ -46,7 +46,7 @@ func configure(plugin *node.Plugin) {
 		registerTangleMetrics()
 	}
 
-	if config.Node.GetBool(metrics.CfgMetricsGlobal) {
+	if config.Node().GetBool(metrics.CfgMetricsGlobal) {
 		registerClientsMetrics()
 	}
 }
@@ -73,13 +73,13 @@ func run(plugin *node.Plugin) {
 					EnableOpenMetrics: true,
 				},
 			)
-			if config.Node.GetBool(CfgPrometheusPromhttpMetrics) {
+			if config.Node().GetBool(CfgPrometheusPromhttpMetrics) {
 				handler = promhttp.InstrumentMetricHandler(registry, handler)
 			}
 			handler.ServeHTTP(c.Writer, c.Request)
 		})
 
-		bindAddr := config.Node.GetString(CfgPrometheusBindAddress)
+		bindAddr := config.Node().GetString(CfgPrometheusBindAddress)
 		server = &http.Server{Addr: bindAddr, Handler: engine}
 
 		go func() {
diff --git a/plugins/remotelog/plugin.go b/plugins/remotelog/plugin.go
index 298038d337d303007ce73879fe92d942e3006791..6d4e6f9ae0fa1b176b11d79b3f2cfd85cd7be630 100644
--- a/plugins/remotelog/plugin.go
+++ b/plugins/remotelog/plugin.go
@@ -36,8 +36,9 @@ const (
 )
 
 var (
-	// Plugin is the plugin instance of the remote plugin instance.
-	Plugin      = node.NewPlugin(PluginName, node.Disabled, configure, run)
+	// plugin is the plugin instance of the remote plugin instance.
+	plugin      *node.Plugin
+	pluginOnce	sync.Once
 	log         *logger.Logger
 	myID        string
 	myGitHead   string
@@ -48,6 +49,14 @@ var (
 	remoteLoggerOnce sync.Once
 )
 
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	pluginOnce.Do(func() {
+		plugin = node.NewPlugin(PluginName, node.Disabled, configure, run)
+	})
+	return plugin
+}
+
 func init() {
 	flag.String(CfgLoggerRemotelogServerAddress, "remotelog.goshimmer.iota.cafe:5213", "RemoteLog server address")
 }
@@ -55,7 +64,7 @@ func init() {
 func configure(plugin *node.Plugin) {
 	log = logger.NewLogger(PluginName)
 
-	if config.Node.GetBool(CfgDisableEvents) {
+	if config.Node().GetBool(CfgDisableEvents) {
 		log.Fatalf("%s in config.json needs to be false so that events can be captured!", CfgDisableEvents)
 		return
 	}
@@ -151,7 +160,7 @@ func getGitDir() string {
 // RemoteLogger represents a connection to our remote log server.
 func RemoteLogger() *RemoteLoggerConn {
 	remoteLoggerOnce.Do(func() {
-		r, err := newRemoteLoggerConn(config.Node.GetString(CfgLoggerRemotelogServerAddress))
+		r, err := newRemoteLoggerConn(config.Node().GetString(CfgLoggerRemotelogServerAddress))
 		if err != nil {
 			log.Fatal(err)
 			return
diff --git a/plugins/sync/plugin.go b/plugins/sync/plugin.go
index 5a08344855585bbdb2a9d140205ff91126a2f657..738285a9dea335578d4e3f2d0488cc07df42b45d 100644
--- a/plugins/sync/plugin.go
+++ b/plugins/sync/plugin.go
@@ -49,8 +49,9 @@ func init() {
 }
 
 var (
-	// Plugin is the plugin instance of the sync plugin.
-	Plugin = node.NewPlugin(PluginName, node.Enabled, configure, run)
+	// plugin is the plugin instance of the sync plugin.
+	plugin *node.Plugin
+	once sync.Once
 	// ErrNodeNotSynchronized is returned when an operation can't be executed because
 	// the node is not synchronized.
 	ErrNodeNotSynchronized = errors.New("node is not synchronized")
@@ -59,6 +60,14 @@ var (
 	log    *logger.Logger
 )
 
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	once.Do(func() {
+		plugin = node.NewPlugin(PluginName, node.Enabled, configure, run)
+	})
+	return plugin
+}
+
 // Synced tells whether the node is in a state we consider synchronized, meaning
 // it has the relevant past and present message data.
 func Synced() bool {
@@ -133,10 +142,10 @@ func monitorForDesynchronization() {
 	if err := daemon.BackgroundWorker("Desync-Monitor", func(shutdownSignal <-chan struct{}) {
 		gossip.Manager().Events().NeighborRemoved.Attach(monitorPeerCountClosure)
 		defer gossip.Manager().Events().NeighborRemoved.Detach(monitorPeerCountClosure)
-		messagelayer.Tangle.Events.MessageAttached.Attach(monitorMessageInflowClosure)
-		defer messagelayer.Tangle.Events.MessageAttached.Detach(monitorMessageInflowClosure)
+		messagelayer.Tangle().Events.MessageAttached.Attach(monitorMessageInflowClosure)
+		defer messagelayer.Tangle().Events.MessageAttached.Detach(monitorMessageInflowClosure)
 
-		desyncedIfNoMessageInSec := config.Node.GetDuration(CfgSyncDesyncedIfNoMessageAfterSec) * time.Second
+		desyncedIfNoMessageInSec := config.Node().GetDuration(CfgSyncDesyncedIfNoMessageAfterSec) * time.Second
 		timer := time.NewTimer(desyncedIfNoMessageInSec)
 		for {
 			select {
@@ -171,7 +180,7 @@ func monitorForDesynchronization() {
 // starts a background worker and event handlers to check whether the node is synchronized by first collecting
 // a set of newly received messages and then waiting for them to become solid.
 func monitorForSynchronization() {
-	wantedAnchorPointsCount := config.Node.GetInt(CfgSyncAnchorPointsCount)
+	wantedAnchorPointsCount := config.Node().GetInt(CfgSyncAnchorPointsCount)
 	anchorPoints := newAnchorPoints(wantedAnchorPointsCount)
 	log.Infof("monitoring for synchronization, awaiting %d anchor point messages to become solid", wantedAnchorPointsCount)
 
@@ -203,13 +212,13 @@ func monitorForSynchronization() {
 	})
 
 	if err := daemon.BackgroundWorker("Sync-Monitor", func(shutdownSignal <-chan struct{}) {
-		messagelayer.Tangle.Events.MessageAttached.Attach(initAnchorPointClosure)
-		defer messagelayer.Tangle.Events.MessageAttached.Detach(initAnchorPointClosure)
-		messagelayer.Tangle.Events.MessageSolid.Attach(checkAnchorPointSolidityClosure)
-		defer messagelayer.Tangle.Events.MessageSolid.Detach(checkAnchorPointSolidityClosure)
+		messagelayer.Tangle().Events.MessageAttached.Attach(initAnchorPointClosure)
+		defer messagelayer.Tangle().Events.MessageAttached.Detach(initAnchorPointClosure)
+		messagelayer.Tangle().Events.MessageSolid.Attach(checkAnchorPointSolidityClosure)
+		defer messagelayer.Tangle().Events.MessageSolid.Detach(checkAnchorPointSolidityClosure)
 
-		cleanupDelta := config.Node.GetDuration(CfgSyncAnchorPointsCleanupAfterSec) * time.Second
-		ticker := time.NewTimer(config.Node.GetDuration(CfgSyncAnchorPointsCleanupIntervalSec) * time.Second)
+		cleanupDelta := config.Node().GetDuration(CfgSyncAnchorPointsCleanupAfterSec) * time.Second
+		ticker := time.NewTimer(config.Node().GetDuration(CfgSyncAnchorPointsCleanupIntervalSec) * time.Second)
 		defer ticker.Stop()
 		for {
 			select {
diff --git a/plugins/webapi/autopeering/plugin.go b/plugins/webapi/autopeering/plugin.go
index 0267831b63819f1495c4ae4a373cf816ac3486f2..9b046602fe5a00cafbc752b64f60ea7a1c72cbb0 100644
--- a/plugins/webapi/autopeering/plugin.go
+++ b/plugins/webapi/autopeering/plugin.go
@@ -4,6 +4,7 @@ import (
 	"net"
 	"net/http"
 	"strconv"
+	"sync"
 
 	"github.com/iotaledger/goshimmer/plugins/autopeering"
 	"github.com/iotaledger/goshimmer/plugins/webapi"
@@ -16,11 +17,22 @@ import (
 // PluginName is the name of the web API autopeering endpoint plugin.
 const PluginName = "WebAPI autopeering Endpoint"
 
-// Plugin is the plugin instance of the web API autopeering endpoint plugin.
-var Plugin = node.NewPlugin(PluginName, node.Enabled, configure)
+var (
+	// plugin is the plugin instance of the web API autopeering endpoint plugin.
+	plugin *node.Plugin
+	once sync.Once
+)
 
 func configure(plugin *node.Plugin) {
-	webapi.Server.GET("autopeering/neighbors", getNeighbors)
+	webapi.Server().GET("autopeering/neighbors", getNeighbors)
+}
+
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	once.Do(func() {
+		plugin = node.NewPlugin(PluginName, node.Enabled, configure)
+	})
+	return plugin
 }
 
 // getNeighbors returns the chosen and accepted neighbors of the node
diff --git a/plugins/webapi/data/plugin.go b/plugins/webapi/data/plugin.go
index 83d86d267015c60a4254b340f2796ac6812c5e0e..91f683f5299017a731db018a1cdeb0d17b072320 100644
--- a/plugins/webapi/data/plugin.go
+++ b/plugins/webapi/data/plugin.go
@@ -2,6 +2,7 @@ package data
 
 import (
 	"net/http"
+	"sync"
 
 	"github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload"
 	"github.com/iotaledger/goshimmer/plugins/issuer"
@@ -15,14 +16,23 @@ import (
 const PluginName = "WebAPI data Endpoint"
 
 var (
-	// Plugin is the plugin instance of the web API data endpoint plugin.
-	Plugin = node.NewPlugin(PluginName, node.Enabled, configure)
+	// plugin is the plugin instance of the web API data endpoint plugin.
+	plugin *node.Plugin
+	once sync.Once
 	log    *logger.Logger
 )
 
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	once.Do(func() {
+		plugin = node.NewPlugin(PluginName, node.Enabled, configure)
+	})
+	return plugin
+}
+
 func configure(plugin *node.Plugin) {
 	log = logger.NewLogger(PluginName)
-	webapi.Server.POST("data", broadcastData)
+	webapi.Server().POST("data", broadcastData)
 }
 
 // broadcastData creates a message of the given payload and
diff --git a/plugins/webapi/drng/plugin.go b/plugins/webapi/drng/plugin.go
index b9e542c6c512342c79e04d16c96126fa03a65e9a..d2a89ec67c693e31dbdda4c0ad2e48d5a95d2a27 100644
--- a/plugins/webapi/drng/plugin.go
+++ b/plugins/webapi/drng/plugin.go
@@ -6,18 +6,28 @@ import (
 	"github.com/iotaledger/goshimmer/plugins/webapi/drng/info/committee"
 	"github.com/iotaledger/goshimmer/plugins/webapi/drng/info/randomness"
 	"github.com/iotaledger/hive.go/node"
+	"sync"
 )
 
 // PluginName is the name of the web API DRNG endpoint plugin.
 const PluginName = "WebAPI DRNG Endpoint"
 
 var (
-	// Plugin is the plugin instance of the web API DRNG endpoint plugin.
-	Plugin = node.NewPlugin(PluginName, node.Enabled, configure)
+	// plugin is the plugin instance of the web API DRNG endpoint plugin.
+	plugin *node.Plugin
+	once sync.Once
 )
 
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	once.Do(func() {
+		plugin = node.NewPlugin(PluginName, node.Enabled, configure)
+	})
+	return plugin
+}
+
 func configure(_ *node.Plugin) {
-	webapi.Server.POST("drng/collectiveBeacon", collectivebeacon.Handler)
-	webapi.Server.GET("drng/info/committee", committee.Handler)
-	webapi.Server.GET("drng/info/randomness", randomness.Handler)
+	webapi.Server().POST("drng/collectiveBeacon", collectivebeacon.Handler)
+	webapi.Server().GET("drng/info/committee", committee.Handler)
+	webapi.Server().GET("drng/info/randomness", randomness.Handler)
 }
diff --git a/plugins/webapi/healthz/plugin.go b/plugins/webapi/healthz/plugin.go
index 29af56fdd889537a576ec07e3b77f9d011b6bfd6..d0c859d4771ed3762821ba5ca42242894b2b85ff 100644
--- a/plugins/webapi/healthz/plugin.go
+++ b/plugins/webapi/healthz/plugin.go
@@ -2,6 +2,7 @@ package healthz
 
 import (
 	"net/http"
+	goSync "sync"
 
 	"github.com/iotaledger/goshimmer/plugins/gossip"
 	"github.com/iotaledger/goshimmer/plugins/sync"
@@ -13,11 +14,21 @@ import (
 // PluginName is the name of the web API healthz endpoint plugin.
 const PluginName = "WebAPI healthz Endpoint"
 
-// Plugin is the plugin instance of the web API info endpoint plugin.
-var Plugin = node.NewPlugin(PluginName, node.Enabled, configure)
+var (
+	// plugin is the plugin instance of the web API info endpoint plugin.
+	plugin *node.Plugin
+	once goSync.Once
+)
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	once.Do(func() {
+		plugin = node.NewPlugin(PluginName, node.Enabled, configure)
+	})
+	return plugin
+}
 
 func configure(_ *node.Plugin) {
-	webapi.Server.GET("healthz", getHealthz)
+	webapi.Server().GET("healthz", getHealthz)
 }
 
 func getHealthz(c echo.Context) error {
diff --git a/plugins/webapi/info/plugin.go b/plugins/webapi/info/plugin.go
index 6dc44a26c5fac5a606d5770a462b9ff75a874035..255343b62f108094e0ad774fc72d6c9c33dbcfea 100644
--- a/plugins/webapi/info/plugin.go
+++ b/plugins/webapi/info/plugin.go
@@ -3,6 +3,7 @@ package info
 import (
 	"net/http"
 	"sort"
+	goSync "sync"
 
 	"github.com/iotaledger/goshimmer/plugins/autopeering/local"
 	"github.com/iotaledger/goshimmer/plugins/banner"
@@ -15,11 +16,22 @@ import (
 // PluginName is the name of the web API info endpoint plugin.
 const PluginName = "WebAPI info Endpoint"
 
-// Plugin is the plugin instance of the web API info endpoint plugin.
-var Plugin = node.NewPlugin(PluginName, node.Enabled, configure)
+var (
+	// plugin is the plugin instance of the web API info endpoint plugin.
+	plugin *node.Plugin
+	once goSync.Once
+)
+
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	once.Do(func() {
+		plugin = node.NewPlugin(PluginName, node.Enabled, configure)
+	})
+	return plugin
+}
 
 func configure(_ *node.Plugin) {
-	webapi.Server.GET("info", getInfo)
+	webapi.Server().GET("info", getInfo)
 }
 
 // getInfo returns the info of the node
diff --git a/plugins/webapi/message/plugin.go b/plugins/webapi/message/plugin.go
index 7e29b872a354005704691d82c221df31bc6988a9..015a69e32b231f589f3200b798c8f6501f8b1d1b 100644
--- a/plugins/webapi/message/plugin.go
+++ b/plugins/webapi/message/plugin.go
@@ -2,6 +2,7 @@ package message
 
 import (
 	"net/http"
+	"sync"
 
 	"github.com/iotaledger/goshimmer/packages/binary/messagelayer/message"
 	"github.com/iotaledger/goshimmer/plugins/messagelayer"
@@ -15,15 +16,24 @@ import (
 const PluginName = "WebAPI message Endpoint"
 
 var (
-	// Plugin is the plugin instance of the web API message endpoint plugin.
-	Plugin = node.NewPlugin(PluginName, node.Enabled, configure)
+	// plugin is the plugin instance of the web API message endpoint plugin.
+	plugin *node.Plugin
+	once   sync.Once
 	log    *logger.Logger
 )
 
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	once.Do(func() {
+		plugin = node.NewPlugin(PluginName, node.Enabled, configure)
+	})
+	return plugin
+}
+
 func configure(plugin *node.Plugin) {
 	log = logger.NewLogger(PluginName)
-	webapi.Server.POST("message/findById", findMessageByID)
-	webapi.Server.POST("message/sendPayload", sendPayload)
+	webapi.Server().POST("message/findById", findMessageByID)
+	webapi.Server().POST("message/sendPayload", sendPayload)
 }
 
 // findMessageByID returns the array of messages for the
@@ -48,8 +58,8 @@ func findMessageByID(c echo.Context) error {
 			return c.JSON(http.StatusBadRequest, Response{Error: err.Error()})
 		}
 
-		msgObject := messagelayer.Tangle.Message(msgID)
-		msgMetadataObject := messagelayer.Tangle.MessageMetadata(msgID)
+		msgObject := messagelayer.Tangle().Message(msgID)
+		msgMetadataObject := messagelayer.Tangle().MessageMetadata(msgID)
 
 		if !msgObject.Exists() || !msgMetadataObject.Exists() {
 			result = append(result, Message{})
diff --git a/plugins/webapi/plugin.go b/plugins/webapi/plugin.go
index f97f3db9b9978caa4726aaeea60ad034921cab85..73482f88a02bc766688f62c69e56a6e1c74d5030 100644
--- a/plugins/webapi/plugin.go
+++ b/plugins/webapi/plugin.go
@@ -4,6 +4,7 @@ import (
 	"context"
 	"errors"
 	"net/http"
+	"sync"
 	"time"
 
 	"github.com/iotaledger/goshimmer/packages/shutdown"
@@ -18,25 +19,44 @@ import (
 const PluginName = "WebAPI"
 
 var (
-	// Plugin is the plugin instance of the web API plugin.
-	Plugin = node.NewPlugin(PluginName, node.Enabled, configure, run)
-	// Server is the web API server.
-	Server = echo.New()
+	// plugin is the plugin instance of the web API plugin.
+	plugin     *node.Plugin
+	pluginOnce sync.Once
+	// server is the web API server.
+	server *echo.Echo
+	serverOnce sync.Once
 
 	log *logger.Logger
 )
 
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	pluginOnce.Do(func() {
+		plugin = node.NewPlugin(PluginName, node.Enabled, configure, run)
+	})
+	return plugin
+}
+
+// Server gets the server instance.
+func Server() *echo.Echo {
+	serverOnce.Do(func() {
+		server = echo.New()
+	})
+	return server
+}
+
 func configure(*node.Plugin) {
+	server = Server()
 	log = logger.NewLogger(PluginName)
 	// configure the server
-	Server.HideBanner = true
-	Server.HidePort = true
-	Server.GET("/", IndexRequest)
+	server.HideBanner = true
+	server.HidePort = true
+	server.GET("/", IndexRequest)
 }
 
 func run(*node.Plugin) {
 	log.Infof("Starting %s ...", PluginName)
-	if err := daemon.BackgroundWorker("WebAPI Server", worker, shutdown.PriorityWebAPI); err != nil {
+	if err := daemon.BackgroundWorker("WebAPI server", worker, shutdown.PriorityWebAPI); err != nil {
 		log.Panicf("Failed to start as daemon: %s", err)
 	}
 }
@@ -45,10 +65,10 @@ func worker(shutdownSignal <-chan struct{}) {
 	defer log.Infof("Stopping %s ... done", PluginName)
 
 	stopped := make(chan struct{})
-	bindAddr := config.Node.GetString(CfgBindAddress)
+	bindAddr := config.Node().GetString(CfgBindAddress)
 	go func() {
 		log.Infof("%s started, bind-address=%s", PluginName, bindAddr)
-		if err := Server.Start(bindAddr); err != nil {
+		if err := server.Start(bindAddr); err != nil {
 			if !errors.Is(err, http.ErrServerClosed) {
 				log.Errorf("Error serving: %s", err)
 			}
@@ -65,7 +85,7 @@ func worker(shutdownSignal <-chan struct{}) {
 	log.Infof("Stopping %s ...", PluginName)
 	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
 	defer cancel()
-	if err := Server.Shutdown(ctx); err != nil {
+	if err := server.Shutdown(ctx); err != nil {
 		log.Errorf("Error stopping: %s", err)
 	}
 }
diff --git a/plugins/webapi/spammer/plugin.go b/plugins/webapi/spammer/plugin.go
index f4de8c78a287796a5b01eaad065b119af72e6dc9..248338f641745de3ead979261703e38d14dff8d0 100644
--- a/plugins/webapi/spammer/plugin.go
+++ b/plugins/webapi/spammer/plugin.go
@@ -8,6 +8,7 @@ import (
 	"github.com/iotaledger/hive.go/daemon"
 	"github.com/iotaledger/hive.go/logger"
 	"github.com/iotaledger/hive.go/node"
+	"sync"
 )
 
 var messageSpammer *spammer.Spammer
@@ -15,15 +16,25 @@ var messageSpammer *spammer.Spammer
 // PluginName is the name of the spammer plugin.
 const PluginName = "Spammer"
 
-// Plugin is the plugin instance of the spammer plugin.
-var Plugin = node.NewPlugin(PluginName, node.Disabled, configure, run)
+var (
+	// plugin is the plugin instance of the spammer plugin.
+	plugin *node.Plugin
+	once sync.Once
+	log *logger.Logger
+)
 
-var log *logger.Logger
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	once.Do(func() {
+		plugin = node.NewPlugin(PluginName, node.Disabled, configure, run)
+	})
+	return plugin
+}
 
 func configure(plugin *node.Plugin) {
 	log = logger.NewLogger(PluginName)
 	messageSpammer = spammer.New(issuer.IssuePayload)
-	webapi.Server.GET("spammer", handleRequest)
+	webapi.Server().GET("spammer", handleRequest)
 }
 
 func run(*node.Plugin) {
diff --git a/plugins/webapi/value/attachments/handler.go b/plugins/webapi/value/attachments/handler.go
index 9996feec57343fe68a61b70f4f3ff22df2315830..a54d517efdb2c7ab43f82d92ff756ad15917bac9 100644
--- a/plugins/webapi/value/attachments/handler.go
+++ b/plugins/webapi/value/attachments/handler.go
@@ -21,7 +21,7 @@ func Handler(c echo.Context) error {
 	var valueObjs []ValueObject
 
 	// get txn by txn id
-	txnObj := valuetransfers.Tangle.Transaction(txnID)
+	txnObj := valuetransfers.Tangle().Transaction(txnID)
 	defer txnObj.Release()
 	if !txnObj.Exists() {
 		return c.JSON(http.StatusNotFound, Response{Error: "Transaction not found"})
@@ -29,7 +29,7 @@ func Handler(c echo.Context) error {
 	txn := utils.ParseTransaction(txnObj.Unwrap())
 
 	// get attachements by txn id
-	for _, attachmentObj := range valuetransfers.Tangle.Attachments(txnID) {
+	for _, attachmentObj := range valuetransfers.Tangle().Attachments(txnID) {
 		defer attachmentObj.Release()
 		if !attachmentObj.Exists() {
 			continue
@@ -37,7 +37,7 @@ func Handler(c echo.Context) error {
 		attachment := attachmentObj.Unwrap()
 
 		// get payload by payload id
-		payloadObj := valuetransfers.Tangle.Payload(attachment.PayloadID())
+		payloadObj := valuetransfers.Tangle().Payload(attachment.PayloadID())
 		defer payloadObj.Release()
 		if !payloadObj.Exists() {
 			continue
diff --git a/plugins/webapi/value/gettransactionbyid/handler.go b/plugins/webapi/value/gettransactionbyid/handler.go
index b4bee704b621f56a4e5afdb2b34cc93dc40cc4dd..0f8ebaaab66fbe85d26e502cfb9268fcc47ca1d6 100644
--- a/plugins/webapi/value/gettransactionbyid/handler.go
+++ b/plugins/webapi/value/gettransactionbyid/handler.go
@@ -17,12 +17,12 @@ func Handler(c echo.Context) error {
 	}
 
 	// get txn by txn id
-	cachedTxnMetaObj := valuetransfers.Tangle.TransactionMetadata(txnID)
+	cachedTxnMetaObj := valuetransfers.Tangle().TransactionMetadata(txnID)
 	defer cachedTxnMetaObj.Release()
 	if !cachedTxnMetaObj.Exists() {
 		return c.JSON(http.StatusNotFound, Response{Error: "Transaction not found"})
 	}
-	cachedTxnObj := valuetransfers.Tangle.Transaction(txnID)
+	cachedTxnObj := valuetransfers.Tangle().Transaction(txnID)
 	defer cachedTxnObj.Release()
 	if !cachedTxnObj.Exists() {
 		return c.JSON(http.StatusNotFound, Response{Error: "Transaction not found"})
diff --git a/plugins/webapi/value/plugin.go b/plugins/webapi/value/plugin.go
index 72facce9182a959913a67031ecdf92ea0d3b40ca..4fcdf40e9b06d51701fad95ca9607a9f96992c5c 100644
--- a/plugins/webapi/value/plugin.go
+++ b/plugins/webapi/value/plugin.go
@@ -8,20 +8,30 @@ import (
 	"github.com/iotaledger/goshimmer/plugins/webapi/value/testsendtxn"
 	"github.com/iotaledger/goshimmer/plugins/webapi/value/unspentoutputs"
 	"github.com/iotaledger/hive.go/node"
+	"sync"
 )
 
 // PluginName is the name of the web API DRNG endpoint plugin.
 const PluginName = "WebAPI Value Endpoint"
 
 var (
-	// Plugin is the plugin instance of the web API DRNG endpoint plugin.
-	Plugin = node.NewPlugin(PluginName, node.Enabled, configure)
+	// plugin is the plugin instance of the web API DRNG endpoint plugin.
+	plugin *node.Plugin
+	once sync.Once
 )
 
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	once.Do(func() {
+		plugin = node.NewPlugin(PluginName, node.Enabled, configure)
+	})
+	return plugin
+}
+
 func configure(_ *node.Plugin) {
-	webapi.Server.GET("value/attachments", attachments.Handler)
-	webapi.Server.POST("value/unspentOutputs", unspentoutputs.Handler)
-	webapi.Server.POST("value/sendTransaction", sendtransaction.Handler)
-	webapi.Server.POST("value/testSendTxn", testsendtxn.Handler)
-	webapi.Server.GET("value/transactionByID", gettransactionbyid.Handler)
+	webapi.Server().GET("value/attachments", attachments.Handler)
+	webapi.Server().POST("value/unspentOutputs", unspentoutputs.Handler)
+	webapi.Server().POST("value/sendTransaction", sendtransaction.Handler)
+	webapi.Server().POST("value/testSendTxn", testsendtxn.Handler)
+	webapi.Server().GET("value/transactionByID", gettransactionbyid.Handler)
 }
diff --git a/plugins/webapi/value/unspentoutputs/handler.go b/plugins/webapi/value/unspentoutputs/handler.go
index 05be4eb55ba1d901e0f3544cdec998fcef66c9a8..22dc4f0e37709055d0a0f6b77bd3d5c0480a18d6 100644
--- a/plugins/webapi/value/unspentoutputs/handler.go
+++ b/plugins/webapi/value/unspentoutputs/handler.go
@@ -28,11 +28,11 @@ func Handler(c echo.Context) error {
 
 		outputids := make([]OutputID, 0)
 		// get outputids by address
-		for id, cachedOutput := range valuetransfers.Tangle.OutputsOnAddress(address) {
+		for id, cachedOutput := range valuetransfers.Tangle().OutputsOnAddress(address) {
 			// TODO: don't do this in a for
 			defer cachedOutput.Release()
 			output := cachedOutput.Unwrap()
-			cachedTxMeta := valuetransfers.Tangle.TransactionMetadata(output.TransactionID())
+			cachedTxMeta := valuetransfers.Tangle().TransactionMetadata(output.TransactionID())
 			// TODO: don't do this in a for
 			defer cachedTxMeta.Release()
 
diff --git a/plugins/webauth/webauth.go b/plugins/webauth/webauth.go
index 946f0c8b29bca8fab1ea379d8ab95bcef8fa21a2..a337d7ba34cc5a44ca427c4484441fe7ba60ac8c 100644
--- a/plugins/webauth/webauth.go
+++ b/plugins/webauth/webauth.go
@@ -3,6 +3,7 @@ package webauth
 import (
 	"net/http"
 	"strings"
+	"sync"
 	"time"
 
 	"github.com/dgrijalva/jwt-go"
@@ -18,20 +19,29 @@ import (
 const PluginName = "WebAPI Auth"
 
 var (
-	// Plugin is the plugin instance of the web API auth plugin.
-	Plugin     = node.NewPlugin(PluginName, node.Disabled, configure)
+	// plugin is the plugin instance of the web API auth plugin.
+	plugin     *node.Plugin
+	once 	   sync.Once
 	log        *logger.Logger
 	privateKey string
 )
 
+// Plugin gets the plugin instance.
+func Plugin() *node.Plugin {
+	once.Do(func() {
+		plugin = node.NewPlugin(PluginName, node.Disabled, configure)
+	})
+	return plugin
+}
+
 func configure(plugin *node.Plugin) {
 	log = logger.NewLogger(PluginName)
-	privateKey = config.Node.GetString(CfgWebAPIAuthPrivateKey)
+	privateKey = config.Node().GetString(CfgWebAPIAuthPrivateKey)
 	if len(privateKey) == 0 {
 		panic("")
 	}
 
-	webapi.Server.Use(middleware.JWTWithConfig(middleware.JWTConfig{
+	webapi.Server().Use(middleware.JWTWithConfig(middleware.JWTConfig{
 		SigningKey: []byte(privateKey),
 		Skipper: func(c echo.Context) bool {
 			if strings.HasPrefix(c.Path(), "/ui") || c.Path() == "/login" {
@@ -41,7 +51,7 @@ func configure(plugin *node.Plugin) {
 		},
 	}))
 
-	webapi.Server.POST("/login", Handler)
+	webapi.Server().POST("/login", Handler)
 	log.Info("WebAPI is now secured through JWT authentication")
 }
 
@@ -66,8 +76,8 @@ func Handler(c echo.Context) error {
 		return echo.ErrBadRequest
 	}
 
-	if login.Username != config.Node.GetString(CfgWebAPIAuthUsername) ||
-		login.Password != config.Node.GetString(CfgWebAPIAuthPassword) {
+	if login.Username != config.Node().GetString(CfgWebAPIAuthUsername) ||
+		login.Password != config.Node().GetString(CfgWebAPIAuthPassword) {
 		return echo.ErrUnauthorized
 	}
 
diff --git a/tools/relay-checker/config.go b/tools/relay-checker/config.go
index eceecbcb296f11a54a22ae0734f21170f98d38b7..5e8d2ed774ba1e3e2a0cd09795c99ccdf7e77197 100644
--- a/tools/relay-checker/config.go
+++ b/tools/relay-checker/config.go
@@ -11,24 +11,24 @@ var (
 )
 
 func initConfig() {
-	if config.Node.GetString(CfgTargetNode) == "" {
+	if config.Node().GetString(CfgTargetNode) == "" {
 		panic("Set the target node address\n")
 	}
-	target = config.Node.GetString(CfgTargetNode)
+	target = config.Node().GetString(CfgTargetNode)
 
-	if len(config.Node.GetStringSlice(CfgTestNodes)) == 0 {
+	if len(config.Node().GetStringSlice(CfgTestNodes)) == 0 {
 		panic("Set node addresses\n")
 	}
-	nodes = append(nodes, config.Node.GetStringSlice(CfgTestNodes)...)
+	nodes = append(nodes, config.Node().GetStringSlice(CfgTestNodes)...)
 
 	// optional settings
-	if config.Node.GetString(CfgData) != "" {
-		msgData = config.Node.GetString(CfgData)
+	if config.Node().GetString(CfgData) != "" {
+		msgData = config.Node().GetString(CfgData)
 	}
-	if config.Node.GetInt(CfgCooldownTime) > 0 {
-		cooldownTime = config.Node.GetInt(CfgCooldownTime)
+	if config.Node().GetInt(CfgCooldownTime) > 0 {
+		cooldownTime = config.Node().GetInt(CfgCooldownTime)
 	}
-	if config.Node.GetInt(CfgRepeat) > 0 {
-		repeat = config.Node.GetInt(CfgRepeat)
+	if config.Node().GetInt(CfgRepeat) > 0 {
+		repeat = config.Node().GetInt(CfgRepeat)
 	}
 }