diff --git a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/startup/RuntimeDeploymentManager.java b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/startup/RuntimeDeploymentManager.java
index 3ef5ad8f2d11c..9206d4f93e0b8 100644
--- a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/startup/RuntimeDeploymentManager.java
+++ b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/startup/RuntimeDeploymentManager.java
@@ -131,7 +131,7 @@ public BeanFactory.BeanInstance<?> apply(Class<?> aClass) {
 
         //it is possible that multiple resource classes use the same path
         //we use this map to merge them
-        Map<URITemplate, Map<String, TreeMap<URITemplate, List<RequestMapper.RequestPath<RuntimeResource>>>>> mappers = new TreeMap<>();
+        Map<MappersKey, Map<String, TreeMap<URITemplate, List<RequestMapper.RequestPath<RuntimeResource>>>>> mappers = new TreeMap<>();
 
         for (int i = 0; i < resourceClasses.size(); i++) {
             ResourceClass clazz = resourceClasses.get(i);
@@ -139,9 +139,12 @@ public BeanFactory.BeanInstance<?> apply(Class<?> aClass) {
                 continue;
             }
             URITemplate classTemplate = new URITemplate(clazz.getPath(), true);
-            var perClassMappers = mappers.get(classTemplate);
+
+            MappersKey key = new MappersKey(classTemplate);
+
+            var perClassMappers = mappers.get(key);
             if (perClassMappers == null) {
-                mappers.put(classTemplate, perClassMappers = new HashMap<>());
+                mappers.put(key, perClassMappers = new HashMap<>());
             }
             for (int j = 0; j < clazz.getMethods().size(); j++) {
                 ResourceMethod method = clazz.getMethods().get(j);
@@ -153,6 +156,7 @@ public BeanFactory.BeanInstance<?> apply(Class<?> aClass) {
             }
 
         }
+
         classMappers = new ArrayList<>(mappers.size());
         mappers.forEach(this::forEachMapperEntry);
 
@@ -208,14 +212,14 @@ public BeanFactory.BeanInstance<?> apply(Class<?> aClass) {
                 runtimeConfigurableServerRestHandlers, exceptionMapper, info.isResumeOn404(), info.getResteasyReactiveConfig());
     }
 
-    private void forEachMapperEntry(URITemplate path,
+    private void forEachMapperEntry(MappersKey key,
             Map<String, TreeMap<URITemplate, List<RequestMapper.RequestPath<RuntimeResource>>>> classTemplates) {
-        int classTemplateNameCount = path.countPathParamNames();
+        int classTemplateNameCount = key.path.countPathParamNames();
         RuntimeMappingDeployment runtimeMappingDeployment = new RuntimeMappingDeployment(classTemplates);
         ClassRoutingHandler classRoutingHandler = new ClassRoutingHandler(runtimeMappingDeployment.buildClassMapper(),
                 classTemplateNameCount,
                 info.isResumeOn404());
-        classMappers.add(new RequestMapper.RequestPath<>(true, path,
+        classMappers.add(new RequestMapper.RequestPath<>(true, key.path,
                 new RestInitialHandler.InitialMatch(new ServerRestHandler[] { classRoutingHandler },
                         runtimeMappingDeployment.getMaxMethodTemplateNameCount() + classTemplateNameCount)));
     }
@@ -267,4 +271,69 @@ private String sanitizePathPrefix(String prefix) {
         return prefix;
     }
 
+    private static class MappersKey implements Comparable<MappersKey> {
+        private final String key;
+        private final URITemplate path;
+
+        public MappersKey(URITemplate path) {
+            this.path = path;
+
+            if (path.components.length == 0) {
+                this.key = "";
+            } else {
+                // create a key without any names. Names of e.g. default regex components can differ, but the component still has the same meaning.
+                StringBuilder keyBuilder = new StringBuilder();
+                for (URITemplate.TemplateComponent component : path.components) {
+                    int standardLength = component.type.name().length() + 1
+                            + (component.literalText != null ? component.literalText.length() : 0) + 1 + 1;
+                    int additionalLength = 0;
+                    if (component.pattern != null) {
+                        additionalLength = component.pattern.pattern().length();
+                    }
+                    StringBuilder kb = new StringBuilder(standardLength + additionalLength);
+                    kb.append(component.type);
+                    kb.append(";");
+                    kb.append(component.literalText);
+                    kb.append(";");
+                    if (component.pattern != null) {
+                        // (?<id1>[a-zA-Z]+) -> [a-zA-Z]+
+                        String pattern = component.pattern.pattern();
+                        kb.append(component.pattern.pattern(), pattern.indexOf('>') + 1, pattern.length() - 1);
+                    }
+                    kb.append("|");
+                    keyBuilder.append(kb);
+                }
+
+                this.key = keyBuilder.toString();
+            }
+
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null) {
+                return false;
+            }
+
+            return key.equals(((MappersKey) o).key);
+        }
+
+        @Override
+        public int hashCode() {
+            return key.hashCode();
+        }
+
+        @Override
+        public int compareTo(MappersKey o) {
+            if (key.equals(o.key)) {
+                return 0;
+            }
+
+            return path.compareTo(o.path);
+        }
+    }
+
 }
diff --git a/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/matching/ResourceClassMergeTest.java b/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/matching/ResourceClassMergeTest.java
new file mode 100644
index 0000000000000..b5ae2b66821cb
--- /dev/null
+++ b/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/matching/ResourceClassMergeTest.java
@@ -0,0 +1,103 @@
+package org.jboss.resteasy.reactive.server.vertx.test.matching;
+
+import static io.restassured.RestAssured.given;
+import static org.hamcrest.Matchers.is;
+
+import java.util.function.Supplier;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.jboss.resteasy.reactive.server.vertx.test.framework.ResteasyReactiveUnitTest;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+public class ResourceClassMergeTest {
+    @RegisterExtension
+    static ResteasyReactiveUnitTest test = new ResteasyReactiveUnitTest()
+            .setArchiveProducer(new Supplier<>() {
+                @Override
+                public JavaArchive get() {
+                    return ShrinkWrap.create(JavaArchive.class)
+                            .addClasses(MatchDefaultRegexDifferentNameResourceA.class,
+                                    MatchDefaultRegexDifferentNameResourceB.class, MatchCustomRegexDifferentNameResourceA.class,
+                                    MatchCustomRegexDifferentNameResourceB.class);
+                }
+            });
+
+    @Test
+    public void testCallMatchDefaultRegexDifferentNameResource() {
+        given()
+                .when().get("routing-broken/abc/some/other/path")
+                .then()
+                .statusCode(200)
+                .body(is("abc"));
+
+        given()
+                .when().get("routing-broken/efg/some/path")
+                .then()
+                .statusCode(200)
+                .body(is("efg"));
+    }
+
+    @Test
+    public void testCallMatchCustomRegexDifferentNameResource() {
+        given()
+                .when().get("routing-broken-custom-regex/abc/some/other/path")
+                .then()
+                .statusCode(200)
+                .body(is("abc"));
+
+        given()
+                .when().get("routing-broken-custom-regex/efg/some/path")
+                .then()
+                .statusCode(200)
+                .body(is("efg"));
+    }
+
+    @Path("/routing-broken/{id1}")
+    public static class MatchDefaultRegexDifferentNameResourceA {
+        @GET
+        @Path("/some/other/path")
+        @Produces(MediaType.TEXT_PLAIN)
+        public Response doSomething(@PathParam("id1") String id) {
+            return Response.ok(id).build();
+        }
+    }
+
+    @Path("/routing-broken/{id}")
+    public static class MatchDefaultRegexDifferentNameResourceB {
+        @GET
+        @Path("/some/path")
+        @Produces(MediaType.TEXT_PLAIN)
+        public Response doSomething(@PathParam("id") String id) {
+            return Response.ok(id).build();
+        }
+    }
+
+    @Path("/routing-broken-custom-regex/{id1: [a-zA-Z]+}")
+    public static class MatchCustomRegexDifferentNameResourceA {
+        @GET
+        @Path("/some/other/path")
+        @Produces(MediaType.TEXT_PLAIN)
+        public Response doSomething(@PathParam("id1") String id) {
+            return Response.ok(id).build();
+        }
+    }
+
+    @Path("/routing-broken-custom-regex/{id: [a-zA-Z]+}")
+    public static class MatchCustomRegexDifferentNameResourceB {
+        @GET
+        @Path("/some/path")
+        @Produces(MediaType.TEXT_PLAIN)
+        public Response doSomething(@PathParam("id") String id) {
+            return Response.ok(id).build();
+        }
+    }
+}