diff --git a/assets/templates/middleware/metrics b/assets/templates/middleware/metrics
index 42483bc0f834f12349a028344111675ac7722ed0..9e1406280e5f19c4535e0ca6ca9d77d4f2206ef6 100644
--- a/assets/templates/middleware/metrics
+++ b/assets/templates/middleware/metrics
@@ -26,11 +26,14 @@ func {{ $funcName }} (requestMetrics *metrics.RequestMetrics) Middleware {
 {{ range $method := .Interface.Methods }}
     // {{ $method.Name }} implements {{ $.Interface.Type }}
     func (m {{ $decorator }}) {{ $method.Declaration }} {
-        timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("{{ $.Interface.Name }}", "{{ $method.Name }}"))
+        m.requestMetrics.Total.WithLabelValues("{{ $method.Name }}").Inc()
+        timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("{{ $method.Name }}"))
         defer func() {
-                timer.ObserveDuration()
-        		m.requestMetrics.Total.WithLabelValues("{{ $.Interface.Name }}", "{{ $method.Name }}").Inc()
-        	}()
+            timer.ObserveDuration()
+            if err != nil {
+                m.requestMetrics.FailedTotal.WithLabelValues("{{ $method.Name }}").Inc()
+            }
+        }()
         {{ $method.Pass "m.next." }}
     }
 {{ end }}
\ No newline at end of file
diff --git a/pkg/items/middleware/metrics_middleware.go b/pkg/items/middleware/metrics_middleware.go
index 360716b94373564dbb2a508ed0f01f6c7779f969..72fb917b0ab4afc128c65adfc3a2891de685f1ad 100644
--- a/pkg/items/middleware/metrics_middleware.go
+++ b/pkg/items/middleware/metrics_middleware.go
@@ -33,180 +33,234 @@ func MetricsMiddleware(requestMetrics *metrics.RequestMetrics) Middleware {
 
 // Aggregate implements items.Items
 func (m metricsMiddleware) Aggregate(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.AggregateOptions) (result map[string]interface{}, err error) {
-	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "Aggregate"))
+	m.requestMetrics.Total.WithLabelValues("Aggregate").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Aggregate"))
 	defer func() {
 		timer.ObserveDuration()
-		m.requestMetrics.Total.WithLabelValues("Items", "Aggregate").Inc()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Aggregate").Inc()
+		}
 	}()
 	return m.next.Aggregate(ctx, spaceId, envId, collectionId, filter, options...)
 }
 
 // AggregatePublished implements items.Items
 func (m metricsMiddleware) AggregatePublished(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.AggregatePublishedOptions) (result map[string]interface{}, err error) {
-	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "AggregatePublished"))
+	m.requestMetrics.Total.WithLabelValues("AggregatePublished").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("AggregatePublished"))
 	defer func() {
 		timer.ObserveDuration()
-		m.requestMetrics.Total.WithLabelValues("Items", "AggregatePublished").Inc()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("AggregatePublished").Inc()
+		}
 	}()
 	return m.next.AggregatePublished(ctx, spaceId, envId, collectionId, filter, options...)
 }
 
 // Archive implements items.Items
 func (m metricsMiddleware) Archive(ctx context.Context, item *items.Item, options ...*items.ArchiveOptions) (err error) {
-	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "Archive"))
+	m.requestMetrics.Total.WithLabelValues("Archive").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Archive"))
 	defer func() {
 		timer.ObserveDuration()
-		m.requestMetrics.Total.WithLabelValues("Items", "Archive").Inc()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Archive").Inc()
+		}
 	}()
 	return m.next.Archive(ctx, item, options...)
 }
 
 // Create implements items.Items
 func (m metricsMiddleware) Create(ctx context.Context, item *items.Item, opts ...*items.CreateOptions) (created *items.Item, err error) {
-	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "Create"))
+	m.requestMetrics.Total.WithLabelValues("Create").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Create"))
 	defer func() {
 		timer.ObserveDuration()
-		m.requestMetrics.Total.WithLabelValues("Items", "Create").Inc()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Create").Inc()
+		}
 	}()
 	return m.next.Create(ctx, item, opts...)
 }
 
 // Delete implements items.Items
 func (m metricsMiddleware) Delete(ctx context.Context, item *items.Item, options ...*items.DeleteOptions) (err error) {
-	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "Delete"))
+	m.requestMetrics.Total.WithLabelValues("Delete").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Delete"))
 	defer func() {
 		timer.ObserveDuration()
-		m.requestMetrics.Total.WithLabelValues("Items", "Delete").Inc()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Delete").Inc()
+		}
 	}()
 	return m.next.Delete(ctx, item, options...)
 }
 
 // Find implements items.Items
 func (m metricsMiddleware) Find(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.FindOptions) (items []*items.Item, total int, err error) {
-	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "Find"))
+	m.requestMetrics.Total.WithLabelValues("Find").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Find"))
 	defer func() {
 		timer.ObserveDuration()
-		m.requestMetrics.Total.WithLabelValues("Items", "Find").Inc()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Find").Inc()
+		}
 	}()
 	return m.next.Find(ctx, spaceId, envId, collectionId, filter, options...)
 }
 
 // FindArchived implements items.Items
 func (m metricsMiddleware) FindArchived(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.FindArchivedOptions) (items []*items.Item, total int, err error) {
-	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "FindArchived"))
+	m.requestMetrics.Total.WithLabelValues("FindArchived").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("FindArchived"))
 	defer func() {
 		timer.ObserveDuration()
-		m.requestMetrics.Total.WithLabelValues("Items", "FindArchived").Inc()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("FindArchived").Inc()
+		}
 	}()
 	return m.next.FindArchived(ctx, spaceId, envId, collectionId, filter, options...)
 }
 
 // FindPublished implements items.Items
 func (m metricsMiddleware) FindPublished(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.FindPublishedOptions) (items []*items.Item, total int, err error) {
-	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "FindPublished"))
+	m.requestMetrics.Total.WithLabelValues("FindPublished").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("FindPublished"))
 	defer func() {
 		timer.ObserveDuration()
-		m.requestMetrics.Total.WithLabelValues("Items", "FindPublished").Inc()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("FindPublished").Inc()
+		}
 	}()
 	return m.next.FindPublished(ctx, spaceId, envId, collectionId, filter, options...)
 }
 
 // Get implements items.Items
 func (m metricsMiddleware) Get(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, options ...*items.GetOptions) (item *items.Item, err error) {
-	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "Get"))
+	m.requestMetrics.Total.WithLabelValues("Get").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Get"))
 	defer func() {
 		timer.ObserveDuration()
-		m.requestMetrics.Total.WithLabelValues("Items", "Get").Inc()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Get").Inc()
+		}
 	}()
 	return m.next.Get(ctx, spaceId, envId, collectionId, itemId, options...)
 }
 
 // GetPublished implements items.Items
 func (m metricsMiddleware) GetPublished(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, options ...*items.GetPublishedOptions) (item *items.Item, err error) {
-	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "GetPublished"))
+	m.requestMetrics.Total.WithLabelValues("GetPublished").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("GetPublished"))
 	defer func() {
 		timer.ObserveDuration()
-		m.requestMetrics.Total.WithLabelValues("Items", "GetPublished").Inc()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("GetPublished").Inc()
+		}
 	}()
 	return m.next.GetPublished(ctx, spaceId, envId, collectionId, itemId, options...)
 }
 
 // GetRevision implements items.Items
 func (m metricsMiddleware) GetRevision(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, revisionId string, options ...*items.GetRevisionOptions) (item *items.Item, err error) {
-	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "GetRevision"))
+	m.requestMetrics.Total.WithLabelValues("GetRevision").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("GetRevision"))
 	defer func() {
 		timer.ObserveDuration()
-		m.requestMetrics.Total.WithLabelValues("Items", "GetRevision").Inc()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("GetRevision").Inc()
+		}
 	}()
 	return m.next.GetRevision(ctx, spaceId, envId, collectionId, itemId, revisionId, options...)
 }
 
 // Introspect implements items.Items
 func (m metricsMiddleware) Introspect(ctx context.Context, item *items.Item, opts ...*items.IntrospectOptions) (itm *items.Item, sch *schema.Schema, err error) {
-	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "Introspect"))
+	m.requestMetrics.Total.WithLabelValues("Introspect").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Introspect"))
 	defer func() {
 		timer.ObserveDuration()
-		m.requestMetrics.Total.WithLabelValues("Items", "Introspect").Inc()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Introspect").Inc()
+		}
 	}()
 	return m.next.Introspect(ctx, item, opts...)
 }
 
 // ListRevisions implements items.Items
 func (m metricsMiddleware) ListRevisions(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, options ...*items.ListRevisionsOptions) (items []*items.Item, err error) {
-	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "ListRevisions"))
+	m.requestMetrics.Total.WithLabelValues("ListRevisions").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("ListRevisions"))
 	defer func() {
 		timer.ObserveDuration()
-		m.requestMetrics.Total.WithLabelValues("Items", "ListRevisions").Inc()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("ListRevisions").Inc()
+		}
 	}()
 	return m.next.ListRevisions(ctx, spaceId, envId, collectionId, itemId, options...)
 }
 
 // Publish implements items.Items
 func (m metricsMiddleware) Publish(ctx context.Context, item *items.Item, options ...*items.PublishOptions) (err error) {
-	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "Publish"))
+	m.requestMetrics.Total.WithLabelValues("Publish").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Publish"))
 	defer func() {
 		timer.ObserveDuration()
-		m.requestMetrics.Total.WithLabelValues("Items", "Publish").Inc()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Publish").Inc()
+		}
 	}()
 	return m.next.Publish(ctx, item, options...)
 }
 
 // Unarchive implements items.Items
 func (m metricsMiddleware) Unarchive(ctx context.Context, item *items.Item, options ...*items.UnarchiveOptions) (err error) {
-	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "Unarchive"))
+	m.requestMetrics.Total.WithLabelValues("Unarchive").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Unarchive"))
 	defer func() {
 		timer.ObserveDuration()
-		m.requestMetrics.Total.WithLabelValues("Items", "Unarchive").Inc()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Unarchive").Inc()
+		}
 	}()
 	return m.next.Unarchive(ctx, item, options...)
 }
 
 // Undelete implements items.Items
 func (m metricsMiddleware) Undelete(ctx context.Context, item *items.Item, options ...*items.UndeleteOptions) (err error) {
-	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "Undelete"))
+	m.requestMetrics.Total.WithLabelValues("Undelete").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Undelete"))
 	defer func() {
 		timer.ObserveDuration()
-		m.requestMetrics.Total.WithLabelValues("Items", "Undelete").Inc()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Undelete").Inc()
+		}
 	}()
 	return m.next.Undelete(ctx, item, options...)
 }
 
 // Unpublish implements items.Items
 func (m metricsMiddleware) Unpublish(ctx context.Context, item *items.Item, options ...*items.UnpublishOptions) (err error) {
-	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "Unpublish"))
+	m.requestMetrics.Total.WithLabelValues("Unpublish").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Unpublish"))
 	defer func() {
 		timer.ObserveDuration()
-		m.requestMetrics.Total.WithLabelValues("Items", "Unpublish").Inc()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Unpublish").Inc()
+		}
 	}()
 	return m.next.Unpublish(ctx, item, options...)
 }
 
 // Update implements items.Items
 func (m metricsMiddleware) Update(ctx context.Context, item *items.Item, options ...*items.UpdateOptions) (err error) {
-	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "Update"))
+	m.requestMetrics.Total.WithLabelValues("Update").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Update"))
 	defer func() {
 		timer.ObserveDuration()
-		m.requestMetrics.Total.WithLabelValues("Items", "Update").Inc()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Update").Inc()
+		}
 	}()
 	return m.next.Update(ctx, item, options...)
 }
diff --git a/pkg/metrics/request.go b/pkg/metrics/request.go
index fbfb63fa8e4b43a435e0a0e5e2a04764ae9e2797..01837bf956aef3ad6172050f444ee67bb52d6de8 100644
--- a/pkg/metrics/request.go
+++ b/pkg/metrics/request.go
@@ -2,33 +2,34 @@ package metrics
 
 import (
 	"github.com/prometheus/client_golang/prometheus"
-	"github.com/prometheus/client_golang/prometheus/promauto"
 )
 
 type RequestMetrics struct {
 	Total           *prometheus.CounterVec
+	FailedTotal     *prometheus.CounterVec
 	DurationSeconds *prometheus.HistogramVec
 }
 
-// NewRequestMetrics
-//
-// # Example metrics
-//
-// svc_request_duration_seconds_bucket{service="Collections",method="Get",le="+Inf"} 2
-//
-// svc_request_duration_seconds_sum{service="Collections",method="Get"} 0.711158607
-//
-// svc_request_duration_seconds_count{service="Collections",method="Get"} 2
-//
-// svc_requests_total{service="Collections",method="Get"} 2
-func NewRequestMetrics(registry prometheus.Registerer, buckets []float64) *RequestMetrics {
-	return &RequestMetrics{
-		Total: promauto.With(registry).NewCounterVec(prometheus.CounterOpts{
-			Name: "svc_requests_total",
-		}, []string{"service", "method"}),
-		DurationSeconds: promauto.With(registry).NewHistogramVec(prometheus.HistogramOpts{
-			Name:    "svc_request_duration_seconds",
-			Buckets: buckets,
-		}, []string{"service", "method"}),
+func NewRequestMetrics(subsystem string, durationBuckets []float64, labels ...string) *RequestMetrics {
+	metrics := &RequestMetrics{
+		Total: prometheus.NewCounterVec(prometheus.CounterOpts{
+			Subsystem: subsystem,
+			Name:      "service_requests_total",
+		}, []string{"method"}),
+		FailedTotal: prometheus.NewCounterVec(prometheus.CounterOpts{
+			Subsystem: subsystem,
+			Name:      "service_requests_failed_total",
+		}, []string{"method"}),
+		DurationSeconds: prometheus.NewHistogramVec(prometheus.HistogramOpts{
+			Subsystem: subsystem,
+			Name:      "service_request_duration_seconds",
+			Buckets:   durationBuckets,
+		}, []string{"method"}),
 	}
+	prometheus.WrapRegistererWith(GetLabelsFromKV(labels), prometheus.DefaultRegisterer).MustRegister(
+		metrics.Total,
+		metrics.FailedTotal,
+		metrics.DurationSeconds,
+	)
+	return metrics
 }