diff --git a/controller/controller.go b/controller/controller.go
index 431791eb1cf3a8b768f0bec968f7d5445c8c35a6..6a8f5c5a51651fb6c43be614bddb2cee863983f0 100644
--- a/controller/controller.go
+++ b/controller/controller.go
@@ -77,7 +77,7 @@ func initialize() error {
 		return err
 	}
 
-	nodeService := nodes.NewNodeService(nodes.NewDatabaseNodeStore())
+	nodeService := nodes.NewNodeService(nodes.NewDatabaseNodeStore(), eventService)
 	portService := ports.NewPortService(ports.NewDatabasePortStore())
 
 	c = &Core{
diff --git a/controller/topology/nodes/nodeService.go b/controller/topology/nodes/nodeService.go
index 1a444a48b18db7d5c519e94b8ef80d8df2f39912..520add41ce21d4dcd8ecd85ae7627c250283bd99 100644
--- a/controller/topology/nodes/nodeService.go
+++ b/controller/topology/nodes/nodeService.go
@@ -1,10 +1,17 @@
 package nodes
 
 import (
+	"code.fbi.h-da.de/danet/gosdn/controller/event"
+	eventInterfaces "code.fbi.h-da.de/danet/gosdn/controller/interfaces/event"
 	"code.fbi.h-da.de/danet/gosdn/controller/topology/store"
 	"github.com/google/uuid"
 )
 
+const (
+	// NodeEventTopic is the used topic for node related entity changes
+	NodeEventTopic = "node"
+)
+
 // Service defines a interface for a NodeService
 type Service interface {
 	EnsureExists(Node) (Node, error)
@@ -16,29 +23,33 @@ type Service interface {
 
 // NodeService is a NodeService
 type NodeService struct {
-	store Store
+	store        Store
+	eventService eventInterfaces.Service
 }
 
 // NewNodeService creates a NodeService
-func NewNodeService(store Store) Service {
+func NewNodeService(store Store, eventService eventInterfaces.Service) Service {
 	return &NodeService{
-		store: store,
+		store:        store,
+		eventService: eventService,
 	}
 }
 
 // EnsureExists either creates a new node or returns an already existing node
-func (p *NodeService) EnsureExists(node Node) (Node, error) {
+func (n *NodeService) EnsureExists(node Node) (Node, error) {
 	if node.ID == uuid.Nil {
 		node.ID = uuid.New()
-		err := p.store.Add(node)
+		err := n.store.Add(node)
 		if err != nil {
 			return node, err
 		}
 
+		n.eventService.PublishEvent(NodeEventTopic, event.NewAddEvent(node.ID))
+
 		return node, nil
 	}
 
-	node, err := p.Get(store.Query{ID: node.ID})
+	node, err := n.Get(store.Query{ID: node.ID})
 	if err != nil {
 		return node, err
 	}
@@ -47,28 +58,32 @@ func (p *NodeService) EnsureExists(node Node) (Node, error) {
 }
 
 // Update updates an existing node
-func (p *NodeService) Update(node Node) error {
-	err := p.store.Update(node)
+func (n *NodeService) Update(node Node) error {
+	err := n.store.Update(node)
 	if err != nil {
 		return err
 	}
 
+	n.eventService.PublishEvent(NodeEventTopic, event.NewUpdateEvent(node.ID))
+
 	return nil
 }
 
 // Delete deletes a node
-func (p *NodeService) Delete(node Node) error {
-	err := p.store.Delete(node)
+func (n *NodeService) Delete(node Node) error {
+	err := n.store.Delete(node)
 	if err != nil {
 		return err
 	}
 
+	n.eventService.PublishEvent(NodeEventTopic, event.NewDeleteEvent(node.ID))
+
 	return nil
 }
 
 // Get gets a node
-func (p *NodeService) Get(query store.Query) (Node, error) {
-	node, err := p.store.Get(query)
+func (n *NodeService) Get(query store.Query) (Node, error) {
+	node, err := n.store.Get(query)
 	if err != nil {
 		return node, err
 	}
@@ -77,8 +92,8 @@ func (p *NodeService) Get(query store.Query) (Node, error) {
 }
 
 // GetAll gets all existing nodes
-func (p *NodeService) GetAll() ([]Node, error) {
-	nodes, err := p.store.GetAll()
+func (n *NodeService) GetAll() ([]Node, error) {
+	nodes, err := n.store.GetAll()
 	if err != nil {
 		return nodes, err
 	}
diff --git a/controller/topology/nodes/nodeService_test.go b/controller/topology/nodes/nodeService_test.go
index e9b76b8634babdbbb44942ab55eecda17837e009..d4457b050c3ae01b85ac3b1486c41072ea7c46cd 100644
--- a/controller/topology/nodes/nodeService_test.go
+++ b/controller/topology/nodes/nodeService_test.go
@@ -4,6 +4,8 @@ import (
 	"reflect"
 	"testing"
 
+	eventservice "code.fbi.h-da.de/danet/gosdn/controller/eventService"
+	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/event"
 	"code.fbi.h-da.de/danet/gosdn/controller/topology/store"
 	"github.com/google/uuid"
 )
@@ -37,7 +39,8 @@ func getTestStoreWithNodes(t *testing.T, nodes []Node) Store {
 
 func TestNewNodeService(t *testing.T) {
 	type args struct {
-		store Store
+		store        Store
+		eventService event.Service
 	}
 	tests := []struct {
 		name string
@@ -47,14 +50,15 @@ func TestNewNodeService(t *testing.T) {
 		{
 			name: "should create a new node service",
 			args: args{
-				store: getTestStoreWithNodes(t, []Node{}),
+				store:        getTestStoreWithNodes(t, []Node{}),
+				eventService: eventservice.NewMockEventService(),
 			},
-			want: NewNodeService(getTestStoreWithNodes(t, []Node{})),
+			want: NewNodeService(getTestStoreWithNodes(t, []Node{}), eventservice.NewMockEventService()),
 		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			if got := NewNodeService(tt.args.store); !reflect.DeepEqual(got, tt.want) {
+			if got := NewNodeService(tt.args.store, tt.args.eventService); !reflect.DeepEqual(got, tt.want) {
 				t.Errorf("NewNodeService() = %v, want %v", got, tt.want)
 			}
 		})
@@ -63,7 +67,8 @@ func TestNewNodeService(t *testing.T) {
 
 func TestNodeService_EnsureExists(t *testing.T) {
 	type fields struct {
-		store Store
+		store        Store
+		eventService event.Service
 	}
 	type args struct {
 		node Node
@@ -94,7 +99,8 @@ func TestNodeService_EnsureExists(t *testing.T) {
 		{
 			name: "should error if node with uuid is not in store",
 			fields: fields{
-				store: store.NewGenericStore[Node](),
+				store:        store.NewGenericStore[Node](),
+				eventService: eventservice.NewMockEventService(),
 			},
 			args: args{
 				node: getTestNode(),
@@ -105,7 +111,8 @@ func TestNodeService_EnsureExists(t *testing.T) {
 		{
 			name: "should return node that is in the store",
 			fields: fields{
-				store: getTestStoreWithNodes(t, []Node{getTestNode()}),
+				store:        getTestStoreWithNodes(t, []Node{getTestNode()}),
+				eventService: eventservice.NewMockEventService(),
 			},
 			args: args{
 				node: getTestNode(),
@@ -117,7 +124,8 @@ func TestNodeService_EnsureExists(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			p := &NodeService{
-				store: tt.fields.store,
+				store:        tt.fields.store,
+				eventService: tt.fields.eventService,
 			}
 			got, err := p.EnsureExists(tt.args.node)
 			if (err != nil) != tt.wantErr {
@@ -133,7 +141,8 @@ func TestNodeService_EnsureExists(t *testing.T) {
 
 func TestNodeService_Update(t *testing.T) {
 	type fields struct {
-		store Store
+		store        Store
+		eventService event.Service
 	}
 	type args struct {
 		node Node
@@ -148,7 +157,8 @@ func TestNodeService_Update(t *testing.T) {
 		{
 			name: "should update an existing node",
 			fields: fields{
-				store: getTestStoreWithNodes(t, []Node{getTestNode()}),
+				store:        getTestStoreWithNodes(t, []Node{getTestNode()}),
+				eventService: eventservice.NewMockEventService(),
 			},
 			args: args{
 				node: getTestNode(),
@@ -160,7 +170,8 @@ func TestNodeService_Update(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			p := &NodeService{
-				store: tt.fields.store,
+				store:        tt.fields.store,
+				eventService: tt.fields.eventService,
 			}
 			if err := p.Update(tt.args.node); (err != nil) != tt.wantErr {
 				t.Errorf("NodeService.Update() error = %v, wantErr %v", err, tt.wantErr)
@@ -180,7 +191,8 @@ func TestNodeService_Update(t *testing.T) {
 
 func TestNodeService_Delete(t *testing.T) {
 	type fields struct {
-		store Store
+		store        Store
+		eventService event.Service
 	}
 	type args struct {
 		node Node
@@ -194,7 +206,8 @@ func TestNodeService_Delete(t *testing.T) {
 		{
 			name: "should delete an existing node",
 			fields: fields{
-				store: getTestStoreWithNodes(t, []Node{getTestNode()}),
+				store:        getTestStoreWithNodes(t, []Node{getTestNode()}),
+				eventService: eventservice.NewMockEventService(),
 			},
 			args: args{
 				node: getTestNode(),
@@ -204,7 +217,8 @@ func TestNodeService_Delete(t *testing.T) {
 		{
 			name: "should fail if a node does not exists",
 			fields: fields{
-				store: store.NewGenericStore[Node](),
+				store:        store.NewGenericStore[Node](),
+				eventService: eventservice.NewMockEventService(),
 			},
 			args: args{
 				node: getTestNode(),
@@ -215,7 +229,8 @@ func TestNodeService_Delete(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			p := &NodeService{
-				store: tt.fields.store,
+				store:        tt.fields.store,
+				eventService: tt.fields.eventService,
 			}
 			if err := p.Delete(tt.args.node); (err != nil) != tt.wantErr {
 				t.Errorf("NodeService.Delete() error = %v, wantErr %v", err, tt.wantErr)
@@ -226,7 +241,8 @@ func TestNodeService_Delete(t *testing.T) {
 
 func TestNodeService_Get(t *testing.T) {
 	type fields struct {
-		store Store
+		store        Store
+		eventService event.Service
 	}
 	type args struct {
 		query store.Query
@@ -241,7 +257,8 @@ func TestNodeService_Get(t *testing.T) {
 		{
 			name: "should error if node with uuid is not in store",
 			fields: fields{
-				store: store.NewGenericStore[Node](),
+				store:        store.NewGenericStore[Node](),
+				eventService: eventservice.NewMockEventService(),
 			},
 			args: args{
 				query: store.Query{
@@ -255,7 +272,8 @@ func TestNodeService_Get(t *testing.T) {
 		{
 			name: "should return node that is in the store",
 			fields: fields{
-				store: getTestStoreWithNodes(t, []Node{getTestNode()}),
+				store:        getTestStoreWithNodes(t, []Node{getTestNode()}),
+				eventService: eventservice.NewMockEventService(),
 			},
 			args: args{
 				query: store.Query{
@@ -270,7 +288,8 @@ func TestNodeService_Get(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			p := &NodeService{
-				store: tt.fields.store,
+				store:        tt.fields.store,
+				eventService: tt.fields.eventService,
 			}
 			got, err := p.Get(tt.args.query)
 			if (err != nil) != tt.wantErr {
@@ -286,7 +305,8 @@ func TestNodeService_Get(t *testing.T) {
 
 func TestNodeService_GetAll(t *testing.T) {
 	type fields struct {
-		store Store
+		store        Store
+		eventService event.Service
 	}
 	tests := []struct {
 		name    string
@@ -297,7 +317,8 @@ func TestNodeService_GetAll(t *testing.T) {
 		{
 			name: "should get all stored nodes",
 			fields: fields{
-				store: getTestStoreWithNodes(t, []Node{getTestNode()}),
+				store:        getTestStoreWithNodes(t, []Node{getTestNode()}),
+				eventService: eventservice.NewMockEventService(),
 			},
 			want:    []Node{getTestNode()},
 			wantErr: false,
@@ -306,7 +327,8 @@ func TestNodeService_GetAll(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			p := &NodeService{
-				store: tt.fields.store,
+				store:        tt.fields.store,
+				eventService: tt.fields.eventService,
 			}
 			got, err := p.GetAll()
 			if (err != nil) != tt.wantErr {
diff --git a/controller/topology/topologyService_test.go b/controller/topology/topologyService_test.go
index 06c25eb38f756b6123d05d3b0bff644ec5944b24..68b17027a48418022f79de42645fa11fc3f123a0 100644
--- a/controller/topology/topologyService_test.go
+++ b/controller/topology/topologyService_test.go
@@ -4,10 +4,12 @@ import (
 	"reflect"
 	"testing"
 
+	eventservice "code.fbi.h-da.de/danet/gosdn/controller/eventService"
 	"code.fbi.h-da.de/danet/gosdn/controller/topology/links"
 	"code.fbi.h-da.de/danet/gosdn/controller/topology/nodes"
 	"code.fbi.h-da.de/danet/gosdn/controller/topology/ports"
 	"code.fbi.h-da.de/danet/gosdn/controller/topology/store"
+
 	"github.com/google/uuid"
 )
 
@@ -108,12 +110,12 @@ func TestNewTopologyService(t *testing.T) {
 			name: "should create a new topology service",
 			args: args{
 				store:       getTestStoreWithLinks(t, []links.Link{}),
-				nodeService: nodes.NewNodeService(getTestStoreWithNodes(t, []nodes.Node{})),
+				nodeService: nodes.NewNodeService(getTestStoreWithNodes(t, []nodes.Node{}), eventservice.NewMockEventService()),
 				portService: ports.NewPortService(getTestStoreWithPorts(t, []ports.Port{})),
 			},
 			want: NewTopologyService(
 				getTestStoreWithLinks(t, []links.Link{}),
-				nodes.NewNodeService(getTestStoreWithNodes(t, []nodes.Node{})),
+				nodes.NewNodeService(getTestStoreWithNodes(t, []nodes.Node{}), eventservice.NewMockEventService()),
 				ports.NewPortService(getTestStoreWithPorts(t, []ports.Port{})),
 			),
 		},
@@ -150,7 +152,7 @@ func TestTopologyService_AddLink(t *testing.T) {
 				nodeService: nodes.NewNodeService(getTestStoreWithNodes(
 					t,
 					[]nodes.Node{getTestSourceNode(), getTestTargetNode()},
-				)),
+				), eventservice.NewMockEventService()),
 				portService: ports.NewPortService(getTestStoreWithPorts(
 					t,
 					[]ports.Port{getTestSourcePort(), getTestTargetPort()},
@@ -208,7 +210,7 @@ func TestTopologyService_Update(t *testing.T) {
 			name: "should update an existing link",
 			fields: fields{
 				store:       getTestStoreWithLinks(t, []links.Link{getTestLink()}),
-				nodeService: nodes.NewNodeService(getTestStoreWithNodes(t, []nodes.Node{})),
+				nodeService: nodes.NewNodeService(getTestStoreWithNodes(t, []nodes.Node{}), eventservice.NewMockEventService()),
 				portService: ports.NewPortService(getTestStoreWithPorts(t, []ports.Port{})),
 			},
 			args: args{
@@ -263,7 +265,7 @@ func TestNodeService_Delete(t *testing.T) {
 			name: "should delete an existing link",
 			fields: fields{
 				store:       getTestStoreWithLinks(t, []links.Link{getTestLink()}),
-				nodeService: nodes.NewNodeService(getTestStoreWithNodes(t, []nodes.Node{})),
+				nodeService: nodes.NewNodeService(getTestStoreWithNodes(t, []nodes.Node{}), eventservice.NewMockEventService()),
 				portService: ports.NewPortService(getTestStoreWithPorts(t, []ports.Port{})),
 			},
 			args: args{
@@ -275,7 +277,7 @@ func TestNodeService_Delete(t *testing.T) {
 			name: "should fail if a node does not exists",
 			fields: fields{
 				store:       store.NewGenericStore[links.Link](),
-				nodeService: nodes.NewNodeService(getTestStoreWithNodes(t, []nodes.Node{})),
+				nodeService: nodes.NewNodeService(getTestStoreWithNodes(t, []nodes.Node{}), eventservice.NewMockEventService()),
 				portService: ports.NewPortService(getTestStoreWithPorts(t, []ports.Port{})),
 			},
 			args: args{
@@ -318,7 +320,7 @@ func TestTopologyService_Get(t *testing.T) {
 			name: "should error if link with uuid is not in store",
 			fields: fields{
 				store:       getTestStoreWithLinks(t, []links.Link{}),
-				nodeService: nodes.NewNodeService(getTestStoreWithNodes(t, []nodes.Node{})),
+				nodeService: nodes.NewNodeService(getTestStoreWithNodes(t, []nodes.Node{}), eventservice.NewMockEventService()),
 				portService: ports.NewPortService(getTestStoreWithPorts(t, []ports.Port{})),
 			},
 			args: args{
@@ -380,7 +382,7 @@ func TestTopologyService_GetAll(t *testing.T) {
 			name: "should get all stored links",
 			fields: fields{
 				store:       getTestStoreWithLinks(t, []links.Link{getTestLink()}),
-				nodeService: nodes.NewNodeService(getTestStoreWithNodes(t, []nodes.Node{})),
+				nodeService: nodes.NewNodeService(getTestStoreWithNodes(t, []nodes.Node{}), eventservice.NewMockEventService()),
 				portService: ports.NewPortService(getTestStoreWithPorts(t, []ports.Port{})),
 			},
 			want:    []links.Link{getTestLink()},