diff --git a/src/InputValidator/FrontMatterValidator.php b/src/InputValidator/FrontMatterValidator.php
index eb1aebeb9266dc3b1c0006ceca7d68942db77189..0b1a8bc0208548f7a2f837a80a3e3554b46692ce 100644
--- a/src/InputValidator/FrontMatterValidator.php
+++ b/src/InputValidator/FrontMatterValidator.php
@@ -15,6 +15,7 @@ use Distantmagic\Resonance\Constraint\StringConstraint;
 use Distantmagic\Resonance\FrontMatterCollectionReference;
 use Distantmagic\Resonance\InputValidatedData\FrontMatter;
 use Distantmagic\Resonance\InputValidator;
+use Distantmagic\Resonance\SingletonCollection;
 use Distantmagic\Resonance\StaticPageContentType;
 use Generator;
 use RuntimeException;
@@ -32,7 +33,7 @@ use RuntimeException;
  *     title: non-empty-string,
  * }>
  */
-#[Singleton]
+#[Singleton(collection: SingletonCollection::InputValidator)]
 readonly class FrontMatterValidator extends InputValidator
 {
     public function castValidatedData(mixed $data): FrontMatter
diff --git a/src/InputValidator/RPCMessageValidator.php b/src/InputValidator/RPCMessageValidator.php
index 954d1344d8ee5fad73b4f1366841572c1b6dbe16..68cfd78c3dc510beb1df2d174e8f0cee45023fa3 100644
--- a/src/InputValidator/RPCMessageValidator.php
+++ b/src/InputValidator/RPCMessageValidator.php
@@ -16,6 +16,7 @@ use Distantmagic\Resonance\Feature;
 use Distantmagic\Resonance\InputValidatedData\RPCMessage;
 use Distantmagic\Resonance\InputValidator;
 use Distantmagic\Resonance\RPCMethodValidatorInterface;
+use Distantmagic\Resonance\SingletonCollection;
 
 /**
  * @extends InputValidator<RPCMessage, array{
@@ -25,7 +26,7 @@ use Distantmagic\Resonance\RPCMethodValidatorInterface;
  * }>
  */
 #[GrantsFeature(Feature::WebSocket)]
-#[Singleton]
+#[Singleton(collection: SingletonCollection::InputValidator)]
 readonly class RPCMessageValidator extends InputValidator
 {
     public function __construct(private RPCMethodValidatorInterface $rpcMethodValidator) {}
diff --git a/src/InputValidatorController.php b/src/InputValidatorController.php
index d02f6d0980fab3081a2c39214045679cea9e1601..a8e33f33f55fd8bff89517040016c9fe76d65851 100644
--- a/src/InputValidatorController.php
+++ b/src/InputValidatorController.php
@@ -5,10 +5,21 @@ declare(strict_types=1);
 namespace Distantmagic\Resonance;
 
 use Distantmagic\Resonance\Attribute\Singleton;
+use Ds\Map;
 
 #[Singleton]
 readonly class InputValidatorController
 {
+    /**
+     * @var Map<InputValidator,Constraint>
+     */
+    public Map $cachedConstraints;
+
+    public function __construct()
+    {
+        $this->cachedConstraints = new Map();
+    }
+
     /**
      * @template TCastedData of InputValidatedData
      * @template TValidatedData
@@ -19,7 +30,7 @@ readonly class InputValidatorController
      */
     public function validateData(InputValidator $inputValidator, mixed $data): InputValidationResult
     {
-        $constraintResult = $inputValidator->getConstraint()->validate($data);
+        $constraintResult = $this->cachedConstraints->get($inputValidator)->validate($data);
 
         return $this->castJsonSchemaValidationResult($constraintResult, $inputValidator);
     }
diff --git a/src/SingletonProvider/InputValidatorCollectionProvider.php b/src/SingletonProvider/InputValidatorCollectionProvider.php
index 9b2e34d1c6dd5bac4c323be946767a8d42d37602..7cb802cf7f28ccde70bef2e8433c138e5b31ac31 100644
--- a/src/SingletonProvider/InputValidatorCollectionProvider.php
+++ b/src/SingletonProvider/InputValidatorCollectionProvider.php
@@ -8,6 +8,7 @@ use Distantmagic\Resonance\Attribute\RequiresSingletonCollection;
 use Distantmagic\Resonance\Attribute\Singleton;
 use Distantmagic\Resonance\InputValidator;
 use Distantmagic\Resonance\InputValidatorCollection;
+use Distantmagic\Resonance\InputValidatorController;
 use Distantmagic\Resonance\PHPProjectFiles;
 use Distantmagic\Resonance\SingletonCollection;
 use Distantmagic\Resonance\SingletonContainer;
@@ -20,6 +21,10 @@ use Distantmagic\Resonance\SingletonProvider;
 #[Singleton(provides: InputValidatorCollection::class)]
 final readonly class InputValidatorCollectionProvider extends SingletonProvider
 {
+    public function __construct(
+        private InputValidatorController $inputValidatorController,
+    ) {}
+
     public function provide(SingletonContainer $singletons, PHPProjectFiles $phpProjectFiles): InputValidatorCollection
     {
         $inputValidatorCollection = new InputValidatorCollection();
@@ -30,6 +35,11 @@ final readonly class InputValidatorCollectionProvider extends SingletonProvider
                     $singleton::class,
                     $singleton,
                 );
+                $this
+                    ->inputValidatorController
+                    ->cachedConstraints
+                    ->put($singleton, $singleton->getConstraint())
+                ;
             }
         }
 
diff --git a/src/SingletonProvider/WebSocketRPCResponderAggregateProvider.php b/src/SingletonProvider/WebSocketRPCResponderAggregateProvider.php
index 8210877b00c1a46ebbc0cc935abbb54aafa910c1..611752ce17f98b35fa1c5c560b69ab8be321f3ba 100644
--- a/src/SingletonProvider/WebSocketRPCResponderAggregateProvider.php
+++ b/src/SingletonProvider/WebSocketRPCResponderAggregateProvider.php
@@ -27,6 +27,10 @@ final readonly class WebSocketRPCResponderAggregateProvider extends SingletonPro
         $webSocketRPCResponderAggregate = new WebSocketRPCResponderAggregate();
 
         foreach ($this->collectWebSocketRPCResponders($singletons) as $rpcResponderAttribute) {
+            $webSocketRPCResponderAggregate->cachedConstraints->put(
+                $rpcResponderAttribute->singleton,
+                $rpcResponderAttribute->singleton->getConstraint(),
+            );
             $webSocketRPCResponderAggregate->rpcResponders->put(
                 $rpcResponderAttribute->attribute->method,
                 $rpcResponderAttribute->singleton,
diff --git a/src/WebSocketRPCConnectionHandle.php b/src/WebSocketRPCConnectionHandle.php
index 022c632eaeaff0c1b1aabc66be78b3b19167f392..0f8918c13208ff82a7d97a5c18c60e5a080a2005 100644
--- a/src/WebSocketRPCConnectionHandle.php
+++ b/src/WebSocketRPCConnectionHandle.php
@@ -43,8 +43,10 @@ readonly class WebSocketRPCConnectionHandle
             ->selectResponder($rpcMessage)
         ;
 
-        $constraintResult = $responder
-            ->getConstraint()
+        $constraintResult = $this
+            ->webSocketRPCResponderAggregate
+            ->cachedConstraints
+            ->get($responder)
             ->validate($rpcMessage->payload)
         ;
 
diff --git a/src/WebSocketRPCResponderAggregate.php b/src/WebSocketRPCResponderAggregate.php
index 7457d26571f186de5c412d9143e5dd995be54e71..c0ac18d7ae32718b10699391c92278e3290fc008 100644
--- a/src/WebSocketRPCResponderAggregate.php
+++ b/src/WebSocketRPCResponderAggregate.php
@@ -10,6 +10,11 @@ use Ds\Map;
 
 readonly class WebSocketRPCResponderAggregate
 {
+    /**
+     * @var Map<RPCMethodInterface,Constraint>
+     */
+    public Map $cachedConstraints;
+
     /**
      * @var Map<RPCMethodInterface,WebSocketRPCResponderInterface> $rpcResponders
      */
@@ -17,6 +22,7 @@ readonly class WebSocketRPCResponderAggregate
 
     public function __construct()
     {
+        $this->cachedConstraints = new Map();
         $this->rpcResponders = new Map();
     }