diff --git a/workhorse/internal/upstream/metrics.go b/workhorse/internal/upstream/metrics.go
index 38528056d432d3e2a22a7a7793a197bee7585a53..1a11bdc8b5355dfb9d2f3fca703c02490bea91bc 100644
--- a/workhorse/internal/upstream/metrics.go
+++ b/workhorse/internal/upstream/metrics.go
@@ -101,6 +101,16 @@ var (
 		},
 		[]string{"code", "method", "route"},
 	)
+
+	httpGeoProxiedRequestsTotal = promauto.NewCounterVec(
+		prometheus.CounterOpts{
+			Namespace: namespace,
+			Subsystem: httpSubsystem,
+			Name:      "geo_proxied_requests_total",
+			Help:      "A counter for Geo proxied requests through workhorse.",
+		},
+		[]string{"code", "method", "route"},
+	)
 )
 
 func instrumentRoute(next http.Handler, method string, regexpStr string) http.Handler {
@@ -115,3 +125,7 @@ func instrumentRoute(next http.Handler, method string, regexpStr string) http.Ha
 
 	return handler
 }
+
+func instrumentGeoProxyRoute(next http.Handler, method string, regexpStr string) http.Handler {
+	return promhttp.InstrumentHandlerCounter(httpGeoProxiedRequestsTotal.MustCurryWith(map[string]string{"route": regexpStr}), next)
+}
diff --git a/workhorse/internal/upstream/metrics_test.go b/workhorse/internal/upstream/metrics_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..29a9e09777c49b8375a5c3c6c4bcf80ded464dc3
--- /dev/null
+++ b/workhorse/internal/upstream/metrics_test.go
@@ -0,0 +1,54 @@
+package upstream
+
+import (
+	"io"
+	"net/http"
+	"net/http/httptest"
+	"testing"
+
+	"github.com/prometheus/client_golang/prometheus/testutil"
+	"github.com/sirupsen/logrus"
+	"github.com/stretchr/testify/require"
+
+	"gitlab.com/gitlab-org/gitlab/workhorse/internal/config"
+)
+
+func TestInstrumentGeoProxyRoute(t *testing.T) {
+	const (
+		remote = `\A/remote\z`
+		local  = `\A/local\z`
+		main   = ""
+	)
+
+	u := newUpstream(config.Config{}, logrus.StandardLogger(), func(u *upstream) {
+		u.Routes = []routeEntry{
+			handleRouteWithMatchers(u, remote, withGeoProxy()),
+			handleRouteWithMatchers(u, local),
+			handleRouteWithMatchers(u, main),
+		}
+	})
+	ts := httptest.NewServer(u)
+	defer ts.Close()
+
+	testCases := []testCase{
+		{"remote", "/remote", remote},
+		{"local", "/local", local},
+		{"main", "/", main},
+	}
+
+	httpGeoProxiedRequestsTotal.Reset()
+
+	runTestCases(t, ts, testCases)
+
+	require.Equal(t, 1, testutil.CollectAndCount(httpGeoProxiedRequestsTotal))
+	require.InDelta(t, 1, testutil.ToFloat64(httpGeoProxiedRequestsTotal.WithLabelValues("200", "get", remote)), 0.1)
+	require.InDelta(t, 0, testutil.ToFloat64(httpGeoProxiedRequestsTotal.WithLabelValues("200", "get", local)), 0.1)
+	require.InDelta(t, 0, testutil.ToFloat64(httpGeoProxiedRequestsTotal.WithLabelValues("200", "get", main)), 0.1)
+}
+
+func handleRouteWithMatchers(u *upstream, regex string, matchers ...func(*routeOptions)) routeEntry {
+	handler := http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
+		io.WriteString(w, regex)
+	})
+	return u.route("", regex, handler, matchers...)
+}
diff --git a/workhorse/internal/upstream/routes.go b/workhorse/internal/upstream/routes.go
index 22b30fe8a632f544fe1d25a2f34954a895e1a16c..06160702f840a22e5e665df3ed8e9c7332998c66 100644
--- a/workhorse/internal/upstream/routes.go
+++ b/workhorse/internal/upstream/routes.go
@@ -42,8 +42,9 @@ type routeEntry struct {
 }
 
 type routeOptions struct {
-	tracing  bool
-	matchers []matcherFunc
+	tracing         bool
+	isGeoProxyRoute bool
+	matchers        []matcherFunc
 }
 
 type uploadPreparers struct {
@@ -94,7 +95,13 @@ func withoutTracing() func(*routeOptions) {
 	}
 }
 
-func (u *upstream) observabilityMiddlewares(handler http.Handler, method string, regexpStr string) http.Handler {
+func withGeoProxy() func(*routeOptions) {
+	return func(options *routeOptions) {
+		options.isGeoProxyRoute = true
+	}
+}
+
+func (u *upstream) observabilityMiddlewares(handler http.Handler, method string, regexpStr string, opts *routeOptions) http.Handler {
 	handler = log.AccessLogger(
 		handler,
 		log.WithAccessLogger(u.accessLogger),
@@ -106,6 +113,11 @@ func (u *upstream) observabilityMiddlewares(handler http.Handler, method string,
 	)
 
 	handler = instrumentRoute(handler, method, regexpStr) // Add prometheus metrics
+
+	if opts != nil && opts.isGeoProxyRoute {
+		handler = instrumentGeoProxyRoute(handler, method, regexpStr) // Add Geo prometheus metrics
+	}
+
 	return handler
 }
 
@@ -119,7 +131,7 @@ func (u *upstream) route(method, regexpStr string, handler http.Handler, opts ..
 		f(&options)
 	}
 
-	handler = u.observabilityMiddlewares(handler, method, regexpStr)
+	handler = u.observabilityMiddlewares(handler, method, regexpStr, &options)
 	handler = denyWebsocket(handler) // Disallow websockets
 	if options.tracing {
 		// Add distributed tracing
@@ -136,7 +148,7 @@ func (u *upstream) route(method, regexpStr string, handler http.Handler, opts ..
 
 func (u *upstream) wsRoute(regexpStr string, handler http.Handler, matchers ...matcherFunc) routeEntry {
 	method := "GET"
-	handler = u.observabilityMiddlewares(handler, method, regexpStr)
+	handler = u.observabilityMiddlewares(handler, method, regexpStr, nil)
 
 	return routeEntry{
 		method:   method,
diff --git a/workhorse/internal/upstream/upstream.go b/workhorse/internal/upstream/upstream.go
index 99d1245fafcc8121952df7775e2f917bd0caef9e..065cae53e2b6c544822f11ab9b68a709794d57b2 100644
--- a/workhorse/internal/upstream/upstream.go
+++ b/workhorse/internal/upstream/upstream.go
@@ -239,5 +239,5 @@ func (u *upstream) updateGeoProxyFields(geoProxyURL *url.URL) {
 	geoProxyRoundTripper := roundtripper.NewBackendRoundTripper(u.geoProxyBackend, "", u.ProxyHeadersTimeout, u.DevelopmentMode)
 	geoProxyUpstream := proxypkg.NewProxy(u.geoProxyBackend, u.Version, geoProxyRoundTripper)
 	u.geoProxyCableRoute = u.wsRoute(`^/-/cable\z`, geoProxyUpstream)
-	u.geoProxyRoute = u.route("", "", geoProxyUpstream)
+	u.geoProxyRoute = u.route("", "", geoProxyUpstream, withGeoProxy())
 }