diff --git a/ctrl/internal/application/app.go b/ctrl/internal/application/app.go
index efbcbc62a0e24e0757448bf4bbd972483a5d85b9..f17d22d8797cb1d0e59bae11b3a6ceebea8660d7 100644
--- a/ctrl/internal/application/app.go
+++ b/ctrl/internal/application/app.go
@@ -4,16 +4,20 @@ import (
 	"code.fbi.h-da.de/danet/costaquanta/ctrl/internal/core/ports"
 	"code.fbi.h-da.de/danet/costaquanta/ctrl/internal/infrastructure/interaction"
 	"code.fbi.h-da.de/danet/costaquanta/ctrl/internal/infrastructure/store"
+	"code.fbi.h-da.de/danet/costaquanta/ctrl/internal/service"
 	"code.fbi.h-da.de/danet/costaquanta/libs/logging"
 	sdktrace "go.opentelemetry.io/otel/sdk/trace"
 	"go.uber.org/zap"
 )
 
 type Application struct {
-	tracer        *sdktrace.TracerProvider
-	HealthServer  *interaction.HealthServer
-	RoutingServer *interaction.RoutingServer
-	KmsStore      ports.KmsStore
+	tracer *sdktrace.TracerProvider
+
+	HealthServer *interaction.HealthServer
+
+	RoutingService ports.RoutingService
+	RoutingServer  *interaction.RoutingServer
+	KmsStore       ports.KmsStore
 }
 
 func NewApplication(log *zap.Logger, tracer *sdktrace.TracerProvider) *Application {
@@ -21,9 +25,13 @@ func NewApplication(log *zap.Logger, tracer *sdktrace.TracerProvider) *Applicati
 	healthTracer := tracer.Tracer("healthServer")
 	healthSrv := interaction.NewHealthServer(healthLogger, healthTracer)
 
+	routingServiceLogger := logging.CreateChildLogger(log, "routingService")
+	routingServiceTracer := tracer.Tracer("routingService")
+	rSrv := service.NewRoutingService(routingServiceLogger, routingServiceTracer)
+
 	routingLogger := logging.CreateChildLogger(log, "routingServer")
 	routingTracer := tracer.Tracer("routingServer")
-	routerSrv := interaction.NewRoutingServer(routingLogger, routingTracer)
+	routerSrv := interaction.NewRoutingServer(routingLogger, routingTracer, rSrv)
 
 	// Create the in-memory KMS store, as we currently have no other option.
 	// Can be replaced by a store choice via flags or config file later.
@@ -32,9 +40,10 @@ func NewApplication(log *zap.Logger, tracer *sdktrace.TracerProvider) *Applicati
 	kmsStore := store.NewInMemoryKmsStore(kmsStoreLogger, kmsStoreTracer)
 
 	return &Application{
-		tracer:        tracer,
-		HealthServer:  healthSrv,
-		RoutingServer: routerSrv,
-		KmsStore:      kmsStore,
+		tracer:         tracer,
+		HealthServer:   healthSrv,
+		RoutingServer:  routerSrv,
+		RoutingService: rSrv,
+		KmsStore:       kmsStore,
 	}
 }
diff --git a/ctrl/internal/core/model/route.go b/ctrl/internal/core/model/route.go
new file mode 100644
index 0000000000000000000000000000000000000000..efffdab924594601fa94a231369c53580eea2d5c
--- /dev/null
+++ b/ctrl/internal/core/model/route.go
@@ -0,0 +1,17 @@
+package model
+
+type RoutingCryptoAlgorithm int
+
+const (
+	Unspecified RoutingCryptoAlgorithm = iota
+	AES256GCM
+	OTP
+	Hybrid
+)
+
+type Route struct {
+	ID              string
+	NextHopID       string
+	PrevHopID       string
+	CryptoAlgorithm RoutingCryptoAlgorithm
+}
diff --git a/ctrl/internal/core/ports/routing.go b/ctrl/internal/core/ports/routing.go
new file mode 100644
index 0000000000000000000000000000000000000000..2cdd282edf7085f3fa479e4a051cc78e72971f67
--- /dev/null
+++ b/ctrl/internal/core/ports/routing.go
@@ -0,0 +1,16 @@
+package ports
+
+import (
+	"context"
+
+	"code.fbi.h-da.de/danet/costaquanta/ctrl/internal/core/model"
+	"code.fbi.h-da.de/danet/costaquanta/ctrl/internal/service"
+)
+
+type RoutingService interface {
+	RequestRoute(context.Context, service.RequestRouteDTO) (model.Route, error)
+	AnnouncePayloadRelay(context.Context, service.AnnouncePayloadRelayRequestDTO) error
+	PayloadRelayFinished(context.Context, service.PayloadRelayFinishedRequestDTO) error
+	PayloadRelayError(context.Context, service.PayloadRelayErrorDTO) error
+	PushKeyStoreFillLevel(context.Context, service.PushKeyStoreFillLevelRequestDTO) error
+}
diff --git a/ctrl/internal/infrastructure/interaction/health_test.go b/ctrl/internal/infrastructure/interaction/health_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..78ffa296c69c8bf1376ded40fd7e95818fea785d
--- /dev/null
+++ b/ctrl/internal/infrastructure/interaction/health_test.go
@@ -0,0 +1,112 @@
+package interaction
+
+import (
+	"context"
+	"log"
+	"net"
+	"testing"
+
+	pb "code.fbi.h-da.de/danet/costaquanta/gen/go/ctrl/v1"
+	"code.fbi.h-da.de/danet/costaquanta/libs/tracing"
+	"go.uber.org/zap"
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/credentials/insecure"
+	"google.golang.org/grpc/test/bufconn"
+)
+
+func newHealthServer() pb.HealthCtrlServer {
+	logs := zap.NewExample()
+
+	traceProvider := tracing.GetTestTracer()
+	defer func() {
+		if err := traceProvider.Shutdown(context.Background()); err != nil {
+			logs.Info(err.Error())
+		}
+	}()
+
+	srv := NewHealthServer(
+		zap.NewExample().Sugar(),
+		traceProvider.Tracer("test"),
+	)
+
+	return srv
+}
+
+//nolint:staticcheck
+func getTestServer(ctx context.Context) (pb.HealthCtrlClient, func()) {
+	buffer := 101024 * 1024
+	lis := bufconn.Listen(buffer)
+
+	baseServer := grpc.NewServer()
+	pb.RegisterHealthCtrlServer(baseServer, newHealthServer())
+	go func() {
+		if err := baseServer.Serve(lis); err != nil {
+			log.Printf("error serving server: %v", err)
+		}
+	}()
+
+	conn, err := grpc.DialContext(ctx, "",
+		grpc.WithContextDialer(func(context.Context, string) (net.Conn, error) {
+			return lis.Dial()
+		}), grpc.WithTransportCredentials(insecure.NewCredentials()))
+	if err != nil {
+		log.Printf("error connecting to server: %v", err)
+	}
+
+	closer := func() {
+		err := lis.Close()
+		if err != nil {
+			log.Printf("error closing listener: %v", err)
+		}
+		baseServer.Stop()
+	}
+
+	client := pb.NewHealthCtrlClient(conn)
+
+	return client, closer
+}
+
+//nolint:paralleltest
+func TestHealthServer_Health(t *testing.T) {
+	ctx := context.Background()
+
+	client, closer := getTestServer(ctx)
+	defer closer()
+
+	type expectation struct {
+		out *pb.HealthResponse
+		err error
+	}
+
+	tests := map[string]struct {
+		in       *pb.HealthRequest
+		expected expectation
+	}{
+		"echo-should-succeed": {
+			in: &pb.HealthRequest{
+				Message: "hello-world",
+			},
+			expected: expectation{
+				out: &pb.HealthResponse{
+					Message: "hello-world",
+				},
+				err: nil,
+			},
+		},
+	}
+
+	for scenario, tt := range tests {
+		t.Run(scenario, func(t *testing.T) {
+			out, err := client.Health(ctx, tt.in)
+			if err != nil {
+				if tt.expected.err.Error() != err.Error() {
+					t.Errorf("Err -> \nWant: %q\nGot: %q\n", tt.expected.err, err)
+				}
+			} else {
+				if tt.expected.out.GetMessage() != out.GetMessage() {
+					t.Errorf("Out -> \nWant: %q\nGot : %q", tt.expected.out, out)
+				}
+			}
+		})
+	}
+}
diff --git a/ctrl/internal/infrastructure/interaction/routing.go b/ctrl/internal/infrastructure/interaction/routing.go
index 52ebd7bd620ddc787cedcbfd8d109f503910a496..d3d0d0a2c157762a2607feb3072c3a3b6d64fed0 100644
--- a/ctrl/internal/infrastructure/interaction/routing.go
+++ b/ctrl/internal/infrastructure/interaction/routing.go
@@ -1,9 +1,17 @@
 package interaction
 
 import (
+	"context"
+	"fmt"
+
+	"code.fbi.h-da.de/danet/costaquanta/ctrl/internal/core/model"
+	"code.fbi.h-da.de/danet/costaquanta/ctrl/internal/core/ports"
+	"code.fbi.h-da.de/danet/costaquanta/ctrl/internal/service"
 	pb "code.fbi.h-da.de/danet/costaquanta/gen/go/ctrl/v1"
 	"go.opentelemetry.io/otel/trace"
 	"go.uber.org/zap"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/status"
 )
 
 type RoutingServer struct {
@@ -11,13 +19,128 @@ type RoutingServer struct {
 
 	logger *zap.SugaredLogger
 	tracer trace.Tracer
+
+	srv ports.RoutingService
 }
 
-func NewRoutingServer(logger *zap.SugaredLogger, tracer trace.Tracer) *RoutingServer {
+func NewRoutingServer(
+	logger *zap.SugaredLogger,
+	tracer trace.Tracer,
+	srv *service.Routing,
+) *RoutingServer {
 	s := &RoutingServer{
 		logger: logger,
 		tracer: tracer,
+		srv:    srv,
 	}
 
 	return s
 }
+
+func (r *RoutingServer) RequestRoute(
+	ctx context.Context,
+	req *pb.RequestRouteRequest,
+) (*pb.RequestRouteResponse, error) {
+	_, span := r.tracer.Start(ctx, "request-route")
+	defer span.End()
+
+	dto := service.RequestRouteDTO{
+		SourceKMSID: req.GetSourceKmsId(),
+		TargetKMSID: req.GetTargetKmsId(),
+		// TODO: I'm pretty sure this doesn't work yet.
+		// I need to figure out if there is an pretty way to convert an proto
+		// enum into a Go enum.
+		CryptoAlgorithm: model.RoutingCryptoAlgorithm(req.GetCryptoAlgorithm()),
+	}
+
+	route, err := r.srv.RequestRoute(ctx, dto)
+	if err != nil {
+		return nil, status.Errorf(codes.Internal, "%s", fmt.Sprintf("%s", err))
+	}
+
+	return &pb.RequestRouteResponse{
+		RouteId: route.ID,
+	}, nil
+}
+
+func (r *RoutingServer) AnnouncePayloadRelay(
+	ctx context.Context,
+	req *pb.AnnouncePayloadRelayRequest,
+) (*pb.AnnouncePayloadRelayResponse, error) {
+	_, span := r.tracer.Start(ctx, "announce-payload-relay")
+	defer span.End()
+
+	dto := service.AnnouncePayloadRelayRequestDTO{
+		RequestID: req.GetRequestId(),
+		RouteID:   req.GetRouteId(),
+	}
+
+	err := r.srv.AnnouncePayloadRelay(ctx, dto)
+	if err != nil {
+		return nil, status.Errorf(codes.Internal, "%s", fmt.Sprintf("%s", err))
+	}
+
+	return &pb.AnnouncePayloadRelayResponse{}, nil
+}
+
+func (r *RoutingServer) PayloadRelayFinished(
+	ctx context.Context,
+	req *pb.PayloadRelayFinishedRequest,
+) (*pb.PayloadRelayFinishedResponse, error) {
+	_, span := r.tracer.Start(ctx, "payload-relay-finished")
+	defer span.End()
+
+	dto := service.PayloadRelayFinishedRequestDTO{
+		RequestID: req.GetRequestId(),
+		RouteID:   req.GetRouteId(),
+	}
+
+	err := r.srv.PayloadRelayFinished(ctx, dto)
+	if err != nil {
+		return nil, status.Errorf(codes.Internal, "%s", fmt.Sprintf("%s", err))
+	}
+
+	return &pb.PayloadRelayFinishedResponse{}, nil
+}
+
+func (r *RoutingServer) PayloadRelayError(
+	ctx context.Context,
+	req *pb.PayloadRelayErrorRequest,
+) (*pb.PayloadRelayErrorResponse, error) {
+	_, span := r.tracer.Start(ctx, "payload-relay-error")
+	defer span.End()
+
+	dto := service.PayloadRelayErrorDTO{
+		RequestID: req.GetRequestId(),
+		RouteID:   req.GetRouteId(),
+		ErrorType: req.GetError().Enum().String(),
+	}
+
+	err := r.srv.PayloadRelayError(ctx, dto)
+	if err != nil {
+		return nil, status.Errorf(codes.Internal, "%s", fmt.Sprintf("%s", err))
+	}
+
+	return &pb.PayloadRelayErrorResponse{}, nil
+}
+
+func (r *RoutingServer) PushKeyStoreFillLevel(
+	ctx context.Context,
+	req *pb.PushKeyStoreFillLevelRequest,
+) (*pb.PushKeyStoreFillLevelResponse, error) {
+	_, span := r.tracer.Start(ctx, "push-key-store-fill-level")
+	defer span.End()
+
+	dto := service.PushKeyStoreFillLevelRequestDTO{
+		KMSID:     req.GetKmsId(),
+		PeerID:    req.GetPeerId(),
+		FillLevel: req.GetFillLevel(),
+	}
+
+	err := r.srv.PushKeyStoreFillLevel(ctx, dto)
+	if err != nil {
+		return nil, status.Errorf(codes.Internal, "%s", fmt.Sprintf("%s", err))
+	}
+
+	return &pb.PushKeyStoreFillLevelResponse{}, nil
+}
diff --git a/ctrl/internal/infrastructure/interaction/routing_test.go b/ctrl/internal/infrastructure/interaction/routing_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..5b2f5ff987898beed151fb5e1d082d7fce549868
--- /dev/null
+++ b/ctrl/internal/infrastructure/interaction/routing_test.go
@@ -0,0 +1,118 @@
+package interaction
+
+import (
+	"context"
+	"log"
+	"net"
+	"testing"
+
+	"code.fbi.h-da.de/danet/costaquanta/ctrl/internal/service"
+	pb "code.fbi.h-da.de/danet/costaquanta/gen/go/ctrl/v1"
+	sharedv1 "code.fbi.h-da.de/danet/costaquanta/gen/go/shared/v1"
+	"code.fbi.h-da.de/danet/costaquanta/libs/tracing"
+	"go.uber.org/zap"
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/credentials/insecure"
+	"google.golang.org/grpc/test/bufconn"
+)
+
+func newRoutingServer() pb.CtrlRoutingServiceServer {
+	logs := zap.NewExample()
+
+	traceProvider := tracing.GetTestTracer()
+	defer func() {
+		if err := traceProvider.Shutdown(context.Background()); err != nil {
+			logs.Info(err.Error())
+		}
+	}()
+
+	svc := service.NewRoutingService(logs.Sugar(), traceProvider.Tracer("test"))
+	srv := NewRoutingServer(
+		zap.NewExample().Sugar(),
+		traceProvider.Tracer("test"),
+		svc,
+	)
+
+	return srv
+}
+
+//nolint:staticcheck
+func getTestRoutingServer(ctx context.Context) (pb.CtrlRoutingServiceClient, func()) {
+	buffer := 101024 * 1024
+	lis := bufconn.Listen(buffer)
+
+	baseServer := grpc.NewServer()
+	pb.RegisterCtrlRoutingServiceServer(baseServer, newRoutingServer())
+	go func() {
+		if err := baseServer.Serve(lis); err != nil {
+			log.Printf("error serving server: %v", err)
+		}
+	}()
+
+	conn, err := grpc.DialContext(ctx, "",
+		grpc.WithContextDialer(func(context.Context, string) (net.Conn, error) {
+			return lis.Dial()
+		}), grpc.WithTransportCredentials(insecure.NewCredentials()))
+	if err != nil {
+		log.Printf("error connecting to server: %v", err)
+	}
+
+	closer := func() {
+		err := lis.Close()
+		if err != nil {
+			log.Printf("error closing listener: %v", err)
+		}
+		baseServer.Stop()
+	}
+
+	client := pb.NewCtrlRoutingServiceClient(conn)
+
+	return client, closer
+}
+
+//nolint:paralleltest
+func TestRoutingServer_RequestRoute(t *testing.T) {
+	ctx := context.Background()
+
+	client, closer := getTestRoutingServer(ctx)
+	defer closer()
+
+	type expectation struct {
+		out *pb.RequestRouteResponse
+		err error
+	}
+
+	tests := map[string]struct {
+		in       *pb.RequestRouteRequest
+		expected expectation
+	}{
+		"first-test": {
+			in: &pb.RequestRouteRequest{
+				SourceKmsId:     "1337",
+				TargetKmsId:     "42",
+				CryptoAlgorithm: sharedv1.CryptoAlgorithm_CRYPTO_ALGORITHM_AES_256_GCM,
+			},
+			expected: expectation{
+				out: &pb.RequestRouteResponse{
+					RouteId: "1337",
+				},
+				err: nil,
+			},
+		},
+	}
+
+	for scenario, tt := range tests {
+		t.Run(scenario, func(t *testing.T) {
+			out, err := client.RequestRoute(ctx, tt.in)
+			if err != nil {
+				if tt.expected.err.Error() != err.Error() {
+					t.Errorf("Err -> \nWant: %q\nGot: %q\n", tt.expected.err, err)
+				}
+			} else {
+				if tt.expected.out.GetRouteId() != out.GetRouteId() {
+					t.Errorf("Out -> \nWant: %q\nGot : %q", tt.expected.out, out)
+				}
+			}
+		})
+	}
+}
diff --git a/ctrl/internal/service/routing.go b/ctrl/internal/service/routing.go
new file mode 100644
index 0000000000000000000000000000000000000000..7d29c80bf0c61c54d9532c31adf7784a084fab0f
--- /dev/null
+++ b/ctrl/internal/service/routing.go
@@ -0,0 +1,101 @@
+package service
+
+import (
+	"context"
+	"time"
+
+	"code.fbi.h-da.de/danet/costaquanta/ctrl/internal/core/model"
+	"go.opentelemetry.io/otel/trace"
+	"go.uber.org/zap"
+)
+
+type Routing struct {
+	logger *zap.SugaredLogger
+	tracer trace.Tracer
+}
+
+type RequestRouteDTO struct {
+	SourceKMSID     string
+	TargetKMSID     string
+	CryptoAlgorithm model.RoutingCryptoAlgorithm
+}
+
+type AnnouncePayloadRelayRequestDTO struct {
+	RequestID string
+	RouteID   string
+}
+
+type PayloadRelayFinishedRequestDTO struct {
+	RequestID string
+	RouteID   string
+}
+
+type PayloadRelayErrorDTO struct {
+	RequestID string
+	RouteID   string
+	ErrorType string
+}
+
+type PushKeyStoreFillLevelRequestDTO struct {
+	KMSID     string
+	PeerID    string
+	FillLevel int64
+}
+
+func NewRoutingService(logger *zap.SugaredLogger, tracer trace.Tracer) *Routing {
+	return &Routing{
+		logger: logger,
+		tracer: tracer,
+	}
+}
+
+func (r *Routing) RequestRoute(ctx context.Context, req RequestRouteDTO) (model.Route, error) {
+	_, span := r.tracer.Start(ctx, "request-route")
+	defer span.End()
+
+	// calculate route
+	time.Sleep(time.Second)
+
+	return model.Route{
+		ID: "1337",
+	}, nil
+}
+
+func (r *Routing) AnnouncePayloadRelay(
+	ctx context.Context,
+	req AnnouncePayloadRelayRequestDTO,
+) error {
+	_, span := r.tracer.Start(ctx, "announce-payload-relay")
+	defer span.End()
+
+	// gossip routes to KMS
+
+	return nil
+}
+
+func (r *Routing) PayloadRelayFinished(
+	ctx context.Context,
+	req PayloadRelayFinishedRequestDTO,
+) error {
+	_, span := r.tracer.Start(ctx, "payload-relay-finished")
+	defer span.End()
+
+	return nil
+}
+
+func (r *Routing) PayloadRelayError(ctx context.Context, req PayloadRelayErrorDTO) error {
+	_, span := r.tracer.Start(ctx, "payload-relay-error")
+	defer span.End()
+
+	return nil
+}
+
+func (r *Routing) PushKeyStoreFillLevel(
+	ctx context.Context,
+	req PushKeyStoreFillLevelRequestDTO,
+) error {
+	_, span := r.tracer.Start(ctx, "push-key-store-fill-level")
+	defer span.End()
+
+	return nil
+}
diff --git a/ctrl/internal/service/routing_test.go b/ctrl/internal/service/routing_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..277c2674449c292cd82bc3425779954b34350f1c
--- /dev/null
+++ b/ctrl/internal/service/routing_test.go
@@ -0,0 +1,221 @@
+package service
+
+import (
+	"context"
+	"reflect"
+	"testing"
+
+	"code.fbi.h-da.de/danet/costaquanta/ctrl/internal/core/model"
+	"go.opentelemetry.io/otel/trace"
+	"go.opentelemetry.io/otel/trace/noop"
+	"go.uber.org/zap"
+)
+
+func TestNewRouting(t *testing.T) {
+	t.Parallel()
+
+	type args struct {
+		logger *zap.SugaredLogger
+		tracer trace.Tracer
+	}
+	tests := []struct {
+		name string
+		args args
+		want *Routing
+	}{
+		{
+			name: "test",
+			args: args{
+				logger: zap.NewNop().Sugar(),
+				tracer: noop.NewTracerProvider().Tracer("test"),
+			},
+			want: &Routing{
+				logger: zap.NewNop().Sugar(),
+				tracer: noop.NewTracerProvider().Tracer("test"),
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			t.Parallel()
+			if got := NewRoutingService(tt.args.logger, tt.args.tracer); !reflect.DeepEqual(
+				got,
+				tt.want,
+			) {
+				t.Errorf("NewRouting() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestRouting_RequestRoute(t *testing.T) {
+	t.Parallel()
+
+	type fields struct {
+		logger *zap.SugaredLogger
+		tracer trace.Tracer
+	}
+	type args struct {
+		ctx context.Context
+		req RequestRouteDTO
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		want    model.Route
+		wantErr bool
+	}{
+		// TODO: Add test cases.
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			t.Parallel()
+			r := &Routing{
+				logger: tt.fields.logger,
+				tracer: tt.fields.tracer,
+			}
+			got, err := r.RequestRoute(tt.args.ctx, tt.args.req)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("Routing.RequestRoute() error = %v, wantErr %v", err, tt.wantErr)
+
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("Routing.RequestRoute() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestRouting_AnnouncePayloadRelay(t *testing.T) {
+	t.Parallel()
+
+	type fields struct {
+		logger *zap.SugaredLogger
+		tracer trace.Tracer
+	}
+	type args struct {
+		ctx context.Context
+		req AnnouncePayloadRelayRequestDTO
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		wantErr bool
+	}{
+		// TODO: Add test cases.
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			t.Parallel()
+			r := &Routing{
+				logger: tt.fields.logger,
+				tracer: tt.fields.tracer,
+			}
+			if err := r.AnnouncePayloadRelay(tt.args.ctx, tt.args.req); (err != nil) != tt.wantErr {
+				t.Errorf("Routing.AnnouncePayloadRelay() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+}
+
+func TestRouting_PayloadRelayFinished(t *testing.T) {
+	t.Parallel()
+
+	type fields struct {
+		logger *zap.SugaredLogger
+		tracer trace.Tracer
+	}
+	type args struct {
+		ctx context.Context
+		req PayloadRelayFinishedRequestDTO
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		wantErr bool
+	}{
+		// TODO: Add test cases.
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			t.Parallel()
+			r := &Routing{
+				logger: tt.fields.logger,
+				tracer: tt.fields.tracer,
+			}
+			if err := r.PayloadRelayFinished(tt.args.ctx, tt.args.req); (err != nil) != tt.wantErr {
+				t.Errorf("Routing.PayloadRelayFinished() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+}
+
+func TestRouting_PayloadRelayError(t *testing.T) {
+	t.Parallel()
+
+	type fields struct {
+		logger *zap.SugaredLogger
+		tracer trace.Tracer
+	}
+	type args struct {
+		ctx context.Context
+		req PayloadRelayErrorDTO
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		wantErr bool
+	}{
+		// TODO: Add test cases.
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			t.Parallel()
+			r := &Routing{
+				logger: tt.fields.logger,
+				tracer: tt.fields.tracer,
+			}
+			if err := r.PayloadRelayError(tt.args.ctx, tt.args.req); (err != nil) != tt.wantErr {
+				t.Errorf("Routing.PayloadRelayError() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+}
+
+func TestRouting_PushKeyStoreFillLevel(t *testing.T) {
+	t.Parallel()
+
+	type fields struct {
+		logger *zap.SugaredLogger
+		tracer trace.Tracer
+	}
+	type args struct {
+		ctx context.Context
+		req PushKeyStoreFillLevelRequestDTO
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		wantErr bool
+	}{
+		// TODO: Add test cases.
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			t.Parallel()
+			r := &Routing{
+				logger: tt.fields.logger,
+				tracer: tt.fields.tracer,
+			}
+			if err := r.PushKeyStoreFillLevel(tt.args.ctx, tt.args.req); (err != nil) != tt.wantErr {
+				t.Errorf("Routing.PushKeyStoreFillLevel() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+}
diff --git a/libs/tracing/tracing.go b/libs/tracing/tracing.go
index 67e5a9c6603b68cee86ce2529709cef38f98c207..64fd6099f36207a983dd163cbac08e24fa66a092 100644
--- a/libs/tracing/tracing.go
+++ b/libs/tracing/tracing.go
@@ -58,3 +58,12 @@ func GetTracer(ctx context.Context, target TraceExportTarget) (*sdktrace.TracerP
 func SetRuntimeSettings(serviceName string) {
 	_ = os.Setenv("OTEL_SERVICE_NAME", serviceName)
 }
+
+func GetTestTracer() *sdktrace.TracerProvider {
+	traceProvider, err := GetTracer(context.Background(), Stdout)
+	if err != nil {
+		panic(err)
+	}
+
+	return traceProvider
+}