Repository: kubernetes-sigs/gateway-api-inference-extension

Issue:
Deprecate inferencepool-resources.yaml manifest
We should only be using the helm charts to manage the inferencepool resources. A quick search pointed to a few places where inferencepool-resources.yaml is still referenced:

1) https://github.com/kubernetes-sigs/gateway-api-inference-extension/blob/main/site-src/api-types/inferencepool.md
2) https://github.com/kubernetes-sigs/gateway-api-inference-extension/blob/main/site-src/implementations/model-servers.md?plain=1
3) https://github.com/kubernetes-sigs/gateway-api-inference-extension/blob/main/hack/release-quickstart.sh#L77
4) https://github.com/kubernetes-sigs/gateway-api-inference-extension/blob/main/site-src/guides/index.md?plain=1#L319
5) https://github.com/kubernetes-sigs/gateway-api-inference-extension/blob/main/site-src/guides/troubleshooting.md?plain=1#L71

Discussion:
@ahg-g: /assign @rahulgurnani @k8s-ci-robot: @ahg-g: GitHub didn't allow me to assign the following users: rahulgurnani.

Note that only [kubernetes-sigs members](https://github.com/orgs/kubernetes-sigs/people) with read permissions, repo collaborators and people who have commented on this issue/PR can be assigned. Additionally, issues/PRs can only have 10 assignees at the same time.
For more information please see [the contributor guide](https://git.k8s.io/community/contributors/guide/first-contribution.md#issue-assignment-in-github)

<details>

In response to [this](https://github.com/kubernetes-sigs/gateway-api-inference-extension/issues/1480#issuecomment-3276770421):

>/assign @rahulgurnani 


Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository.
</details>@rahulgurnani: /assign

Solution patch:
diff --git a/.golangci-kal.yml b/.golangci-kal.yml
index a5d853b..099d81d 100644
--- a/.golangci-kal.yml
+++ b/.golangci-kal.yml
@@ -32,6 +32,8 @@ linters:
                 policy: SuggestFix # SuggestFix | Warn # The policy for pointers in optional fields. Defaults to `SuggestFix`. 
               omitempty:
                 policy: SuggestFix # SuggestFix | Warn | Ignore # The policy for omitempty in optional fields. Defaults to `SuggestFix`.
+              omitzero:
+                policy: Forbid # Enforce the `omitempty` route with a pointer for all optional structs.
   exclusions:
     generated: strict
     paths:
diff --git a/OWNERS b/OWNERS
index ecb73d5..596ad1b 100644
--- a/OWNERS
+++ b/OWNERS
@@ -2,7 +2,6 @@
 
 approvers:
 - gateway-api-inference-extension-maintainers
-- wg-serving-leads
 
 reviewers:
 - gateway-api-inference-extension-reviewers
diff --git a/OWNERS_ALIASES b/OWNERS_ALIASES
index 32a0493..6273d0e 100644
--- a/OWNERS_ALIASES
+++ b/OWNERS_ALIASES
@@ -12,10 +12,3 @@ aliases:
   - liu-cong
   - robscott
   - shaneutt
-
-
-  wg-serving-leads:
-  - ArangoGutierrez
-  - Jeffwan
-  - SergeyKanzhelev
-  - terrytangyuan
diff --git a/README.md b/README.md
index 51aaf28..ff193df 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,9 @@ This is achieved by leveraging Envoy's [External Processing] (ext-proc) to exten
 
 [Inference Gateway]:#concepts-and-definitions
 
+
+> ***NOTE*** : As we prep for our `v1` release, some of our docs may fall out of scope, we are working hard to get these up to date and they will be ready by the time we launch `v1`. Thanks!
+
 ## New!
 Inference Gateway has partnered with vLLM to accelerate LLM serving optimizations with [llm-d](https://llm-d.ai/blog/llm-d-announce)!
 
diff --git a/api/v1/inferencepool_types.go b/api/v1/inferencepool_types.go
index f537816..af94582 100644
--- a/api/v1/inferencepool_types.go
+++ b/api/v1/inferencepool_types.go
@@ -24,7 +24,7 @@ import (
 //
 // +kubebuilder:object:root=true
 // TODO: change the annotation once it gets officially approved
-// +kubebuilder:metadata:annotations="api-approved.kubernetes.io=unapproved, experimental-only"
+// +kubebuilder:metadata:annotations="api-approved.kubernetes.io=https://github.com/kubernetes-sigs/gateway-api-inference-extension/pull/1173"
 // +kubebuilder:resource:shortName=infpool
 // +kubebuilder:subresource:status
 // +kubebuilder:storageversion
@@ -35,17 +35,19 @@ type InferencePool struct {
 	// +optional
 	metav1.ObjectMeta `json:"metadata,omitempty"`
 
+	// Spec defines the desired state of the InferencePool.
+	//
 	// +required
 	Spec InferencePoolSpec `json:"spec,omitzero"`
 
-	// Status defines the observed state of InferencePool.
+	// Status defines the observed state of the InferencePool.
 	//
-	// +kubebuilder:default={parent: {{parentRef: {kind: "Status", name: "default"}, conditions: {{type: "Accepted", status: "Unknown", reason: "Pending", message: "Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"}}}}}
 	// +optional
-	Status InferencePoolStatus `json:"status,omitzero"`
+	//nolint:kubeapilinter // status should not be a pointer.
+	Status InferencePoolStatus `json:"status,omitempty"`
 }
 
-// InferencePoolList contains a list of InferencePool.
+// InferencePoolList contains a list of InferencePools.
 //
 // +kubebuilder:object:root=true
 type InferencePoolList struct {
@@ -54,7 +56,7 @@ type InferencePoolList struct {
 	Items           []InferencePool `json:"items"`
 }
 
-// InferencePoolSpec defines the desired state of InferencePool
+// InferencePoolSpec defines the desired state of the InferencePool.
 type InferencePoolSpec struct {
 	// Selector determines which Pods are members of this inference pool.
 	// It matches Pods by their labels only within the same namespace; cross-namespace
@@ -65,19 +67,22 @@ type InferencePoolSpec struct {
 	// this configuration into a Service resource.
 	//
 	// +required
-	Selector LabelSelector `json:"selector,omitempty,omitzero"`
+	Selector LabelSelector `json:"selector,omitzero"`
 
 	// TargetPorts defines a list of ports that are exposed by this InferencePool.
 	// Currently, the list may only include a single port definition.
+	//
 	// +kubebuilder:validation:MinItems=1
 	// +kubebuilder:validation:MaxItems=1
 	// +listType=atomic
 	// +required
 	TargetPorts []Port `json:"targetPorts,omitempty"`
 
-	// EndpointPickerRef configures an endpoint picker as an extension service.
+	// EndpointPickerRef is a reference to the Endpoint Picker extension and its
+	// associated configuration.
+	//
 	// +required
-	EndpointPickerRef EndpointPickerRef `json:"endpointPickerRef,omitempty,omitzero"`
+	EndpointPickerRef EndpointPickerRef `json:"endpointPickerRef,omitzero"`
 }
 
 // Port defines the network port that will be exposed by this InferencePool.
@@ -89,10 +94,11 @@ type Port struct {
 	Number PortNumber `json:"number,omitempty"`
 }
 
-// Extension specifies how to configure an extension that runs the endpoint picker.
+// EndpointPickerRef specifies a reference to an Endpoint Picker extension and its
+// associated configuration.
 type EndpointPickerRef struct {
-	// Group is the group of the referent.
-	// The default value is "", representing the Core API group.
+	// Group is the group of the referent API object. When unspecified, the default value
+	// is "", representing the Core API group.
 	//
 	// +optional
 	// +kubebuilder:default=""
@@ -100,6 +106,8 @@ type EndpointPickerRef struct {
 
 	// Kind is the Kubernetes resource kind of the referent.
 	//
+	// Required if the referent is ambiguous, e.g. service with multiple ports.
+	//
 	// Defaults to "Service" when not specified.
 	//
 	// ExternalName services can refer to CNAME DNS records that may live
@@ -112,65 +120,67 @@ type EndpointPickerRef struct {
 	// +kubebuilder:default=Service
 	Kind Kind `json:"kind,omitempty"`
 
-	// Name is the name of the referent.
+	// Name is the name of the referent API object.
 	//
 	// +required
 	Name ObjectName `json:"name,omitempty"`
 
-	// The port number on the service running the extension. When unspecified,
-	// implementations SHOULD infer a default value of 9002 when the Kind is
-	// Service.
+	// PortNumber is the port number of the Endpoint Picker extension service. When unspecified,
+	// implementations SHOULD infer a default value of 9002 when the kind field is "Service" or
+	// unspecified (defaults to "Service").
 	//
 	// +optional
-	//nolint:kubeapilinter // ignore kubeapilinter here as we want to use pointer here as 0 usually means all ports.
+	//nolint:kubeapilinter // ignore kubeapilinter here as we want to use pointer as zero means all ports in convention, we don't make to use 0 to indicate not set.
 	PortNumber *PortNumber `json:"portNumber,omitempty"`
 
-	// Configures how the gateway handles the case when the extension is not responsive.
-	// Defaults to failClose.
+	// FailureMode configures how the parent handles the case when the Endpoint Picker extension
+	// is non-responsive. When unspecified, defaults to "FailClose".
 	//
 	// +optional
 	// +kubebuilder:default="FailClose"
-	FailureMode ExtensionFailureMode `json:"failureMode,omitempty"`
+	FailureMode EndpointPickerFailureMode `json:"failureMode,omitempty"`
 }
 
-// ExtensionFailureMode defines the options for how the gateway handles the case when the extension is not
-// responsive.
+// EndpointPickerFailureMode defines the options for how the parent handles the case when the
+// Endpoint Picker extension is non-responsive.
+//
 // +kubebuilder:validation:Enum=FailOpen;FailClose
-type ExtensionFailureMode string
+type EndpointPickerFailureMode string
 
 const (
-	// FailOpen specifies that the proxy should forward the request to an endpoint of its picking when the Endpoint Picker fails.
-	FailOpen ExtensionFailureMode = "FailOpen"
-	// FailClose specifies that the proxy should drop the request when the Endpoint Picker fails.
-	FailClose ExtensionFailureMode = "FailClose"
+	// EndpointPickerFailOpen specifies that the parent should forward the request to an endpoint
+	// of its picking when the Endpoint Picker extension fails.
+	EndpointPickerFailOpen EndpointPickerFailureMode = "FailOpen"
+	// EndpointPickerFailClose specifies that the parent should drop the request when the Endpoint
+	// Picker extension fails.
+	EndpointPickerFailClose EndpointPickerFailureMode = "FailClose"
 )
 
-// InferencePoolStatus defines the observed state of InferencePool.
-// +kubebuilder:validation:MinProperties=1
+// InferencePoolStatus defines the observed state of the InferencePool.
 type InferencePoolStatus struct {
-	// Parents is a list of parent resources (usually Gateways) that are
-	// associated with the InferencePool, and the status of the InferencePool with respect to
-	// each parent.
+	// Parents is a list of parent resources, typically Gateways, that are associated with
+	// the InferencePool, and the status of the InferencePool with respect to each parent.
 	//
-	// A maximum of 32 Gateways will be represented in this list. When the list contains
-	// `kind: Status, name: default`, it indicates that the InferencePool is not
-	// associated with any Gateway and a controller must perform the following:
+	// A controller that manages the InferencePool, must add an entry for each parent it manages
+	// and remove the parent entry when the controller no longer considers the InferencePool to
+	// be associated with that parent.
 	//
-	//  - Remove the parent when setting the "Accepted" condition.
-	//  - Add the parent when the controller will no longer manage the InferencePool
-	//    and no other parents exist.
+	// A maximum of 32 parents will be represented in this list. When the list is empty,
+	// it indicates that the InferencePool is not associated with any parents.
 	//
 	// +kubebuilder:validation:MaxItems=32
 	// +optional
 	// +listType=atomic
-	Parents []PoolStatus `json:"parent,omitempty"`
+	Parents []ParentStatus `json:"parents,omitempty"`
 }
 
-// PoolStatus defines the observed state of InferencePool from a Gateway.
-type PoolStatus struct {
-	// Conditions track the state of the InferencePool.
+// ParentStatus defines the observed state of InferencePool from a Parent, i.e. Gateway.
+type ParentStatus struct {
+	// Conditions is a list of status conditions that provide information about the observed
+	// state of the InferencePool. This field is required to be set by the controller that
+	// manages the InferencePool.
 	//
-	// Known condition types are:
+	// Supported condition types are:
 	//
 	// * "Accepted"
 	// * "ResolvedRefs"
@@ -179,31 +189,33 @@ type PoolStatus struct {
 	// +listType=map
 	// +listMapKey=type
 	// +kubebuilder:validation:MaxItems=8
-	// +kubebuilder:default={{type: "Accepted", status: "Unknown", reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"}}
 	Conditions []metav1.Condition `json:"conditions,omitempty"`
 
-	// GatewayRef indicates the gateway that observed state of InferencePool.
+	// ParentRef is used to identify the parent resource that this status
+	// is associated with. It is used to match the InferencePool with the parent
+	// resource, such as a Gateway.
+	//
 	// +required
-	GatewayRef ParentGatewayReference `json:"parentRef,omitzero"`
+	ParentRef ParentReference `json:"parentRef,omitzero"`
 }
 
-// InferencePoolConditionType is a type of condition for the InferencePool
+// InferencePoolConditionType is a type of status condition for the InferencePool.
 type InferencePoolConditionType string
 
-// InferencePoolReason is the reason for a given InferencePoolConditionType
+// InferencePoolReason is the reason for a type of InferencePool status condition.
 type InferencePoolReason string
 
 const (
-	// This condition indicates whether the InferencePool has been accepted or rejected
-	// by a Gateway, and why.
+	// InferencePoolConditionAccepted is a type of condition that indicates whether
+	// the InferencePool has been accepted or rejected by a Parent, and why.
 	//
 	// Possible reasons for this condition to be True are:
 	//
-	// * "Accepted"
+	// * "SupportedByParent"
 	//
 	// Possible reasons for this condition to be False are:
 	//
-	// * "NotSupportedByGateway"
+	// * "Accepted"
 	// * "HTTPRouteNotAccepted"
 	//
 	// Possible reasons for this condition to be Unknown are:
@@ -214,28 +226,26 @@ const (
 	// prefer to use the reasons listed above to improve interoperability.
 	InferencePoolConditionAccepted InferencePoolConditionType = "Accepted"
 
-	// This reason is used with the "Accepted" condition when the InferencePool has been
-	// accepted by the Gateway.
+	// InferencePoolReasonAccepted is a reason used with the "Accepted" condition
+	// when the InferencePool is accepted by a Parent because the Parent supports
+	// InferencePool as a backend.
 	InferencePoolReasonAccepted InferencePoolReason = "Accepted"
 
-	// This reason is used with the "Accepted" condition when the InferencePool
-	// has not been accepted by a Gateway because the Gateway does not support
-	// InferencePool as a backend.
-	InferencePoolReasonNotSupportedByGateway InferencePoolReason = "NotSupportedByGateway"
+	// InferencePoolReasonNotSupportedByParent is a reason used with the "Accepted"
+	// condition when the InferencePool has not been accepted by a Parent because
+	// the Parent does not support InferencePool as a backend.
+	InferencePoolReasonNotSupportedByParent InferencePoolReason = "NotSupportedByParent"
 
-	// This reason is used with the "Accepted" condition when the InferencePool is
-	// referenced by an HTTPRoute that has been rejected by the Gateway. The user
-	// should inspect the status of the referring HTTPRoute for the specific reason.
+	// InferencePoolReasonHTTPRouteNotAccepted is an optional reason used with the
+	// "Accepted" condition when the InferencePool is referenced by an HTTPRoute that
+	// has been rejected by the Parent. The user should inspect the status of the
+	// referring HTTPRoute for the specific reason.
 	InferencePoolReasonHTTPRouteNotAccepted InferencePoolReason = "HTTPRouteNotAccepted"
-
-	// This reason is used with the "Accepted" when a controller has not yet
-	// reconciled the InferencePool.
-	InferencePoolReasonPending InferencePoolReason = "Pending"
 )
 
 const (
-	// This condition indicates whether the controller was able to resolve all
-	// the object references for the InferencePool.
+	// InferencePoolConditionResolvedRefs is a type of condition that indicates whether
+	// the controller was able to resolve all the object references for the InferencePool.
 	//
 	// Possible reasons for this condition to be True are:
 	//
@@ -249,38 +259,45 @@ const (
 	// prefer to use the reasons listed above to improve interoperability.
 	InferencePoolConditionResolvedRefs InferencePoolConditionType = "ResolvedRefs"
 
-	// This reason is used with the "ResolvedRefs" condition when the condition
-	// is true.
+	// InferencePoolReasonResolvedRefs is a reason used with the "ResolvedRefs"
+	// condition when the condition is true.
 	InferencePoolReasonResolvedRefs InferencePoolReason = "ResolvedRefs"
 
-	// This reason is used with the "ResolvedRefs" condition when the
-	// Extension is invalid in some way. This can include an unsupported kind
-	// or API group, or a reference to a resource that can not be found.
+	// InferencePoolReasonInvalidExtensionRef is a reason used with the "ResolvedRefs"
+	// condition when the Extension is invalid in some way. This can include an
+	// unsupported kind or API group, or a reference to a resource that cannot be found.
 	InferencePoolReasonInvalidExtensionRef InferencePoolReason = "InvalidExtensionRef"
 )
 
-// ParentGatewayReference identifies an API object including its namespace,
-// defaulting to Gateway.
-type ParentGatewayReference struct {
-	// Group is the group of the referent.
+// ParentReference identifies an API object. It is used to associate the InferencePool with a
+// parent resource, such as a Gateway.
+type ParentReference struct {
+	// Group is the group of the referent API object. When unspecified, the referent is assumed
+	// to be in the "gateway.networking.k8s.io" API group.
 	//
 	// +optional
 	// +kubebuilder:default="gateway.networking.k8s.io"
 	Group *Group `json:"group,omitempty"`
 
-	// Kind is kind of the referent. For example "Gateway".
+	// Kind is the kind of the referent API object. When unspecified, the referent is assumed
+	// to be a "Gateway" kind.
 	//
 	// +optional
 	// +kubebuilder:default=Gateway
 	Kind Kind `json:"kind,omitempty"`
 
-	// Name is the name of the referent.
+	// Name is the name of the referent API object.
+	//
 	// +required
 	Name ObjectName `json:"name,omitempty"`
 
-	// Namespace is the namespace of the referent.  If not present,
-	// the namespace of the referent is assumed to be the same as
-	// the namespace of the referring object.
+	// Namespace is the namespace of the referenced object. When unspecified, the local
+	// namespace is inferred.
+	//
+	// Note that when a namespace different than the local namespace is specified,
+	// a ReferenceGrant object is required in the referent namespace to allow that
+	// namespace's owner to accept the reference. See the ReferenceGrant
+	// documentation for details: https://gateway-api.sigs.k8s.io/api-types/referencegrant/
 	//
 	// +optional
 	Namespace Namespace `json:"namespace,omitempty"`
diff --git a/api/v1/shared_types.go b/api/v1/shared_types.go
index 64425e7..bc315fd 100644
--- a/api/v1/shared_types.go
+++ b/api/v1/shared_types.go
@@ -132,11 +132,12 @@ type LabelValue string
 // LabelSelector defines a query for resources based on their labels.
 // This simplified version uses only the matchLabels field.
 type LabelSelector struct {
-	// matchLabels contains a set of required {key,value} pairs.
+	// MatchLabels contains a set of required {key,value} pairs.
 	// An object must match every label in this map to be selected.
 	// The matching logic is an AND operation on all entries.
 	//
 	// +required
+	// +kubebuilder:validation:MinItems=1
 	// +kubebuilder:validation:MaxItems=64
-	MatchLabels map[LabelKey]LabelValue `json:"matchLabels,omitempty" protobuf:"bytes,1,rep,name=matchLabels"`
+	MatchLabels map[LabelKey]LabelValue `json:"matchLabels,omitempty"`
 }
diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go
index 9e90d36..b42573c 100644
--- a/api/v1/zz_generated.deepcopy.go
+++ b/api/v1/zz_generated.deepcopy.go
@@ -136,7 +136,7 @@ func (in *InferencePoolStatus) DeepCopyInto(out *InferencePoolStatus) {
 	*out = *in
 	if in.Parents != nil {
 		in, out := &in.Parents, &out.Parents
-		*out = make([]PoolStatus, len(*in))
+		*out = make([]ParentStatus, len(*in))
 		for i := range *in {
 			(*in)[i].DeepCopyInto(&(*out)[i])
 		}
@@ -176,7 +176,7 @@ func (in *LabelSelector) DeepCopy() *LabelSelector {
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *ParentGatewayReference) DeepCopyInto(out *ParentGatewayReference) {
+func (in *ParentReference) DeepCopyInto(out *ParentReference) {
 	*out = *in
 	if in.Group != nil {
 		in, out := &in.Group, &out.Group
@@ -185,18 +185,18 @@ func (in *ParentGatewayReference) DeepCopyInto(out *ParentGatewayReference) {
 	}
 }
 
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ParentGatewayReference.
-func (in *ParentGatewayReference) DeepCopy() *ParentGatewayReference {
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ParentReference.
+func (in *ParentReference) DeepCopy() *ParentReference {
 	if in == nil {
 		return nil
 	}
-	out := new(ParentGatewayReference)
+	out := new(ParentReference)
 	in.DeepCopyInto(out)
 	return out
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *PoolStatus) DeepCopyInto(out *PoolStatus) {
+func (in *ParentStatus) DeepCopyInto(out *ParentStatus) {
 	*out = *in
 	if in.Conditions != nil {
 		in, out := &in.Conditions, &out.Conditions
@@ -205,15 +205,15 @@ func (in *PoolStatus) DeepCopyInto(out *PoolStatus) {
 			(*in)[i].DeepCopyInto(&(*out)[i])
 		}
 	}
-	in.GatewayRef.DeepCopyInto(&out.GatewayRef)
+	in.ParentRef.DeepCopyInto(&out.ParentRef)
 }
 
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PoolStatus.
-func (in *PoolStatus) DeepCopy() *PoolStatus {
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ParentStatus.
+func (in *ParentStatus) DeepCopy() *ParentStatus {
 	if in == nil {
 		return nil
 	}
-	out := new(PoolStatus)
+	out := new(ParentStatus)
 	in.DeepCopyInto(out)
 	return out
 }
diff --git a/apix/v1alpha2/inferenceobjective_types.go b/apix/v1alpha2/inferenceobjective_types.go
index 07f2c4d..53869d9 100644
--- a/apix/v1alpha2/inferenceobjective_types.go
+++ b/apix/v1alpha2/inferenceobjective_types.go
@@ -69,7 +69,7 @@ type InferenceObjectiveSpec struct {
 	// The higher the value, the more critical the request is; negative values _are_ allowed.
 	// No default value is set for this field, allowing for future additions of new fields that may 'one of' with this field.
 	// However, implementations that consume this field (such as the Endpoint Picker) will treat an unset value as '0'.
-	// Priority is used in flow control, primarily in the event of resource scarcity(reqeusts need to be queued).
+	// Priority is used in flow control, primarily in the event of resource scarcity(requests need to be queued).
 	// All requests will be queued, and flow control will _always_ allow requests of higher priority to be served first.
 	// Fairness is only enforced and tracked between requests of the same priority.
 	//
diff --git a/apix/v1alpha2/inferencepool_conversion.go b/apix/v1alpha2/inferencepool_conversion.go
index b817c47..31ea997 100644
--- a/apix/v1alpha2/inferencepool_conversion.go
+++ b/apix/v1alpha2/inferencepool_conversion.go
@@ -18,10 +18,9 @@ package v1alpha2
 
 import (
 	"errors"
-	"fmt"
 
-	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
-	runtime "k8s.io/apimachinery/pkg/runtime"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/utils/ptr"
 
 	v1 "sigs.k8s.io/gateway-api-inference-extension/api/v1"
 )
@@ -39,11 +38,17 @@ func (src *InferencePool) ConvertTo(dst *v1.InferencePool) error {
 	if err != nil {
 		return err
 	}
-	dst.TypeMeta = src.TypeMeta
+
+	meta := metav1.TypeMeta{
+		Kind:       src.Kind,
+		APIVersion: v1.GroupVersion.String(), // Ensure the API version is set correctly.
+	}
+	dst.TypeMeta = meta
 	dst.ObjectMeta = src.ObjectMeta
 	dst.Spec.TargetPorts = []v1.Port{{Number: v1.PortNumber(src.Spec.TargetPortNumber)}}
 	dst.Spec.EndpointPickerRef = endpointPickRef
 	dst.Status = *v1Status
+
 	if src.Spec.Selector != nil {
 		dst.Spec.Selector.MatchLabels = make(map[v1.LabelKey]v1.LabelValue, len(src.Spec.Selector))
 		for k, v := range src.Spec.Selector {
@@ -66,11 +71,17 @@ func (dst *InferencePool) ConvertFrom(src *v1.InferencePool) error {
 	if err != nil {
 		return err
 	}
-	dst.TypeMeta = src.TypeMeta
+
+	meta := metav1.TypeMeta{
+		Kind:       src.Kind,
+		APIVersion: GroupVersion.String(), // Ensure the API version is set correctly.
+	}
+	dst.TypeMeta = meta
 	dst.ObjectMeta = src.ObjectMeta
 	dst.Spec.TargetPortNumber = int32(src.Spec.TargetPorts[0].Number)
 	dst.Spec.ExtensionRef = extensionRef
 	dst.Status = *status
+
 	if src.Spec.Selector.MatchLabels != nil {
 		dst.Spec.Selector = make(map[LabelKey]LabelValue, len(src.Spec.Selector.MatchLabels))
 		for k, v := range src.Spec.Selector.MatchLabels {
@@ -84,22 +95,150 @@ func convertStatusToV1(src *InferencePoolStatus) (*v1.InferencePoolStatus, error
 	if src == nil {
 		return nil, errors.New("src cannot be nil")
 	}
-	u, err := toUnstructured(src)
-	if err != nil {
-		return nil, err
+	if len(src.Parents) == 0 {
+		return &v1.InferencePoolStatus{}, nil
+	}
+	out := &v1.InferencePoolStatus{
+		Parents: make([]v1.ParentStatus, 0, len(src.Parents)),
+	}
+	for _, p := range src.Parents {
+		// Drop the synthetic "status/default" parent entirely.
+		if isV1Alpha2DefaultParent(p) {
+			continue
+		}
+		ps := v1.ParentStatus{
+			ParentRef:  toV1ParentRef(p.GatewayRef),
+			Conditions: nil, // start nil; only allocate if we actually keep any
+		}
+		for _, c := range p.Conditions {
+			// Drop the synthetic default condition.
+			if isV1Alpha2DefaultCondition(c) {
+				continue
+			}
+			cc := c
+			if cc.Type == string(v1.InferencePoolConditionAccepted) {
+				cc.Reason = mapAcceptedReasonToV1(cc.Reason)
+			}
+			ps.Conditions = append(ps.Conditions, cc)
+		}
+
+		// If no real conditions remain, leave nil (omitted in JSON).
+		out.Parents = append(out.Parents, ps)
 	}
-	return convert[v1.InferencePoolStatus](u)
+
+	// If all parents were synthetic and were dropped, normalize to empty status.
+	if len(out.Parents) == 0 {
+		return &v1.InferencePoolStatus{}, nil
+	}
+	return out, nil
 }
 
 func convertStatusFromV1(src *v1.InferencePoolStatus) (*InferencePoolStatus, error) {
 	if src == nil {
 		return nil, errors.New("src cannot be nil")
 	}
-	u, err := toUnstructured(src)
-	if err != nil {
-		return nil, err
+	if len(src.Parents) == 0 {
+		// Do not synthesize the default parent here; v1alpha2 CRD defaults cover creation-time,
+		// and conversion should reflect the true empty set.
+		return &InferencePoolStatus{}, nil
+	}
+	out := &InferencePoolStatus{
+		Parents: make([]PoolStatus, 0, len(src.Parents)),
+	}
+	for _, p := range src.Parents {
+		ps := PoolStatus{
+			GatewayRef: fromV1ParentRef(p.ParentRef),
+		}
+		if n := len(p.Conditions); n > 0 {
+			ps.Conditions = make([]metav1.Condition, 0, n)
+			for _, c := range p.Conditions {
+				cc := c
+				if cc.Type == string(v1.InferencePoolConditionAccepted) {
+					cc.Reason = mapAcceptedReasonFromV1(cc.Reason)
+				}
+				ps.Conditions = append(ps.Conditions, cc)
+			}
+		}
+		out.Parents = append(out.Parents, ps)
+	}
+	return out, nil
+}
+
+// isV1Alpha2DefaultParent returns true for the synthetic "no parents yet" entry.
+func isV1Alpha2DefaultParent(p PoolStatus) bool {
+	if p.GatewayRef.Kind == nil || p.GatewayRef.Name == "" {
+		return false
+	}
+	return *p.GatewayRef.Kind == "Status" && p.GatewayRef.Name == "default"
+}
+
+// Map v1alpha2 -> v1 reasons for the "Accepted" condition.
+func mapAcceptedReasonToV1(r string) string {
+	switch InferencePoolReason(r) {
+	case InferencePoolReasonAccepted:
+		return string(v1.InferencePoolReasonAccepted)
+	case InferencePoolReasonNotSupportedByGateway:
+		return string(v1.InferencePoolReasonNotSupportedByParent)
+	default:
+		// Keep other reasons like "HTTPRouteNotAccepted" or "Pending" as-is.
+		return r
+	}
+}
+
+// Map v1 -> v1alpha2 reasons for the "Accepted" condition.
+func mapAcceptedReasonFromV1(r string) string {
+	switch v1.InferencePoolReason(r) {
+	case v1.InferencePoolReasonAccepted:
+		return string(InferencePoolReasonAccepted)
+	case v1.InferencePoolReasonNotSupportedByParent:
+		return string(InferencePoolReasonNotSupportedByGateway)
+	default:
+		return r
 	}
-	return convert[InferencePoolStatus](u)
+}
+
+func isV1Alpha2DefaultCondition(c metav1.Condition) bool {
+	return InferencePoolConditionType(c.Type) == InferencePoolConditionAccepted &&
+		c.Status == metav1.ConditionUnknown &&
+		InferencePoolReason(c.Reason) == InferencePoolReasonPending
+}
+
+func toV1ParentRef(in ParentGatewayReference) v1.ParentReference {
+	out := v1.ParentReference{
+		Name: v1.ObjectName(in.Name),
+	}
+	if in.Group != nil {
+		g := v1.Group(*in.Group)
+		out.Group = &g
+	}
+	if in.Kind != nil {
+		k := v1.Kind(*in.Kind)
+		out.Kind = k
+	}
+	if in.Namespace != nil {
+		ns := v1.Namespace(*in.Namespace)
+		out.Namespace = ns
+	}
+	return out
+}
+
+func fromV1ParentRef(in v1.ParentReference) ParentGatewayReference {
+	out := ParentGatewayReference{
+		Name: ObjectName(in.Name),
+	}
+	if in.Group != nil {
+		g := Group(*in.Group)
+		out.Group = &g
+	}
+	if in.Kind != "" {
+		k := Kind(in.Kind)
+		out.Kind = &k
+	}
+	if in.Namespace != "" {
+		ns := Namespace(in.Namespace)
+		out.Namespace = &ns
+	}
+	return out
 }
 
 func convertExtensionRefToV1(src *Extension) (v1.EndpointPickerRef, error) {
@@ -108,19 +247,17 @@ func convertExtensionRefToV1(src *Extension) (v1.EndpointPickerRef, error) {
 		return endpointPickerRef, errors.New("src cannot be nil")
 	}
 	if src.Group != nil {
-		v1Group := v1.Group(*src.Group)
-		endpointPickerRef.Group = &v1Group
+		endpointPickerRef.Group = ptr.To(v1.Group(*src.Group))
 	}
 	if src.Kind != nil {
 		endpointPickerRef.Kind = v1.Kind(*src.Kind)
 	}
 	endpointPickerRef.Name = v1.ObjectName(src.Name)
 	if src.PortNumber != nil {
-		v1PortNumber := v1.PortNumber(*src.PortNumber)
-		endpointPickerRef.PortNumber = &v1PortNumber
+		endpointPickerRef.PortNumber = ptr.To(v1.PortNumber(*src.PortNumber))
 	}
 	if src.FailureMode != nil {
-		endpointPickerRef.FailureMode = v1.ExtensionFailureMode(*src.FailureMode)
+		endpointPickerRef.FailureMode = v1.EndpointPickerFailureMode(*src.FailureMode)
 	}
 
 	return endpointPickerRef, nil
@@ -132,37 +269,17 @@ func convertEndpointPickerRefFromV1(src *v1.EndpointPickerRef) (Extension, error
 		return extension, errors.New("src cannot be nil")
 	}
 	if src.Group != nil {
-		group := Group(*src.Group)
-		extension.Group = &group
+		extension.Group = ptr.To(Group(*src.Group))
 	}
 	if src.Kind != "" {
-		kind := Kind(src.Kind)
-		extension.Kind = &kind
+		extension.Kind = ptr.To(Kind(src.Kind))
 	}
 	extension.Name = ObjectName(src.Name)
 	if src.PortNumber != nil {
-		portNumber := PortNumber(*src.PortNumber)
-		extension.PortNumber = &portNumber
+		extension.PortNumber = ptr.To(PortNumber(*src.PortNumber))
 	}
 	if src.FailureMode != "" {
-		extensionFailureMode := ExtensionFailureMode(src.FailureMode)
-		extension.FailureMode = &extensionFailureMode
+		extension.FailureMode = ptr.To(ExtensionFailureMode(src.FailureMode))
 	}
 	return extension, nil
 }
-
-func toUnstructured(obj any) (*unstructured.Unstructured, error) {
-	u, err := runtime.DefaultUnstructuredConverter.ToUnstructured(obj)
-	if err != nil {
-		return nil, err
-	}
-	return &unstructured.Unstructured{Object: u}, nil
-}
-
-func convert[T any](u *unstructured.Unstructured) (*T, error) {
-	var res T
-	if err := runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, &res); err != nil {
-		return nil, fmt.Errorf("error converting unstructured to T: %v", err)
-	}
-	return &res, nil
-}
diff --git a/apix/v1alpha2/zz_generated.deepcopy.go b/apix/v1alpha2/zz_generated.deepcopy.go
index 5a71e75..0249d44 100644
--- a/apix/v1alpha2/zz_generated.deepcopy.go
+++ b/apix/v1alpha2/zz_generated.deepcopy.go
@@ -22,7 +22,7 @@ package v1alpha2
 
 import (
 	"k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/runtime"
+	runtime "k8s.io/apimachinery/pkg/runtime"
 )
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
diff --git a/client-go/applyconfiguration/api/v1/endpointpickerref.go b/client-go/applyconfiguration/api/v1/endpointpickerref.go
index 8e82230..8a9991b 100644
--- a/client-go/applyconfiguration/api/v1/endpointpickerref.go
+++ b/client-go/applyconfiguration/api/v1/endpointpickerref.go
@@ -25,11 +25,11 @@ import (
 // EndpointPickerRefApplyConfiguration represents a declarative configuration of the EndpointPickerRef type for use
 // with apply.
 type EndpointPickerRefApplyConfiguration struct {
-	Group       *apiv1.Group                `json:"group,omitempty"`
-	Kind        *apiv1.Kind                 `json:"kind,omitempty"`
-	Name        *apiv1.ObjectName           `json:"name,omitempty"`
-	PortNumber  *apiv1.PortNumber           `json:"portNumber,omitempty"`
-	FailureMode *apiv1.ExtensionFailureMode `json:"failureMode,omitempty"`
+	Group       *apiv1.Group                     `json:"group,omitempty"`
+	Kind        *apiv1.Kind                      `json:"kind,omitempty"`
+	Name        *apiv1.ObjectName                `json:"name,omitempty"`
+	PortNumber  *apiv1.PortNumber                `json:"portNumber,omitempty"`
+	FailureMode *apiv1.EndpointPickerFailureMode `json:"failureMode,omitempty"`
 }
 
 // EndpointPickerRefApplyConfiguration constructs a declarative configuration of the EndpointPickerRef type for use with
@@ -73,7 +73,7 @@ func (b *EndpointPickerRefApplyConfiguration) WithPortNumber(value apiv1.PortNum
 // WithFailureMode sets the FailureMode field in the declarative configuration to the given value
 // and returns the receiver, so that objects can be built by chaining "With" function invocations.
 // If called multiple times, the FailureMode field is set to the value of the last call.
-func (b *EndpointPickerRefApplyConfiguration) WithFailureMode(value apiv1.ExtensionFailureMode) *EndpointPickerRefApplyConfiguration {
+func (b *EndpointPickerRefApplyConfiguration) WithFailureMode(value apiv1.EndpointPickerFailureMode) *EndpointPickerRefApplyConfiguration {
 	b.FailureMode = &value
 	return b
 }
diff --git a/client-go/applyconfiguration/api/v1/inferencepoolstatus.go b/client-go/applyconfiguration/api/v1/inferencepoolstatus.go
index 5c66e34..499b771 100644
--- a/client-go/applyconfiguration/api/v1/inferencepoolstatus.go
+++ b/client-go/applyconfiguration/api/v1/inferencepoolstatus.go
@@ -21,7 +21,7 @@ package v1
 // InferencePoolStatusApplyConfiguration represents a declarative configuration of the InferencePoolStatus type for use
 // with apply.
 type InferencePoolStatusApplyConfiguration struct {
-	Parents []PoolStatusApplyConfiguration `json:"parent,omitempty"`
+	Parents []ParentStatusApplyConfiguration `json:"parents,omitempty"`
 }
 
 // InferencePoolStatusApplyConfiguration constructs a declarative configuration of the InferencePoolStatus type for use with
@@ -33,7 +33,7 @@ func InferencePoolStatus() *InferencePoolStatusApplyConfiguration {
 // WithParents adds the given value to the Parents field in the declarative configuration
 // and returns the receiver, so that objects can be build by chaining "With" function invocations.
 // If called multiple times, values provided by each call will be appended to the Parents field.
-func (b *InferencePoolStatusApplyConfiguration) WithParents(values ...*PoolStatusApplyConfiguration) *InferencePoolStatusApplyConfiguration {
+func (b *InferencePoolStatusApplyConfiguration) WithParents(values ...*ParentStatusApplyConfiguration) *InferencePoolStatusApplyConfiguration {
 	for i := range values {
 		if values[i] == nil {
 			panic("nil value passed to WithParents")
diff --git a/client-go/applyconfiguration/api/v1/parentgatewayreference.go b/client-go/applyconfiguration/api/v1/parentreference.go
similarity index 69%
rename from client-go/applyconfiguration/api/v1/parentgatewayreference.go
rename to client-go/applyconfiguration/api/v1/parentreference.go
index 5e23aeb..2798f02 100644
--- a/client-go/applyconfiguration/api/v1/parentgatewayreference.go
+++ b/client-go/applyconfiguration/api/v1/parentreference.go
@@ -22,25 +22,25 @@ import (
 	apiv1 "sigs.k8s.io/gateway-api-inference-extension/api/v1"
 )
 
-// ParentGatewayReferenceApplyConfiguration represents a declarative configuration of the ParentGatewayReference type for use
+// ParentReferenceApplyConfiguration represents a declarative configuration of the ParentReference type for use
 // with apply.
-type ParentGatewayReferenceApplyConfiguration struct {
+type ParentReferenceApplyConfiguration struct {
 	Group     *apiv1.Group      `json:"group,omitempty"`
 	Kind      *apiv1.Kind       `json:"kind,omitempty"`
 	Name      *apiv1.ObjectName `json:"name,omitempty"`
 	Namespace *apiv1.Namespace  `json:"namespace,omitempty"`
 }
 
-// ParentGatewayReferenceApplyConfiguration constructs a declarative configuration of the ParentGatewayReference type for use with
+// ParentReferenceApplyConfiguration constructs a declarative configuration of the ParentReference type for use with
 // apply.
-func ParentGatewayReference() *ParentGatewayReferenceApplyConfiguration {
-	return &ParentGatewayReferenceApplyConfiguration{}
+func ParentReference() *ParentReferenceApplyConfiguration {
+	return &ParentReferenceApplyConfiguration{}
 }
 
 // WithGroup sets the Group field in the declarative configuration to the given value
 // and returns the receiver, so that objects can be built by chaining "With" function invocations.
 // If called multiple times, the Group field is set to the value of the last call.
-func (b *ParentGatewayReferenceApplyConfiguration) WithGroup(value apiv1.Group) *ParentGatewayReferenceApplyConfiguration {
+func (b *ParentReferenceApplyConfiguration) WithGroup(value apiv1.Group) *ParentReferenceApplyConfiguration {
 	b.Group = &value
 	return b
 }
@@ -48,7 +48,7 @@ func (b *ParentGatewayReferenceApplyConfiguration) WithGroup(value apiv1.Group)
 // WithKind sets the Kind field in the declarative configuration to the given value
 // and returns the receiver, so that objects can be built by chaining "With" function invocations.
 // If called multiple times, the Kind field is set to the value of the last call.
-func (b *ParentGatewayReferenceApplyConfiguration) WithKind(value apiv1.Kind) *ParentGatewayReferenceApplyConfiguration {
+func (b *ParentReferenceApplyConfiguration) WithKind(value apiv1.Kind) *ParentReferenceApplyConfiguration {
 	b.Kind = &value
 	return b
 }
@@ -56,7 +56,7 @@ func (b *ParentGatewayReferenceApplyConfiguration) WithKind(value apiv1.Kind) *P
 // WithName sets the Name field in the declarative configuration to the given value
 // and returns the receiver, so that objects can be built by chaining "With" function invocations.
 // If called multiple times, the Name field is set to the value of the last call.
-func (b *ParentGatewayReferenceApplyConfiguration) WithName(value apiv1.ObjectName) *ParentGatewayReferenceApplyConfiguration {
+func (b *ParentReferenceApplyConfiguration) WithName(value apiv1.ObjectName) *ParentReferenceApplyConfiguration {
 	b.Name = &value
 	return b
 }
@@ -64,7 +64,7 @@ func (b *ParentGatewayReferenceApplyConfiguration) WithName(value apiv1.ObjectNa
 // WithNamespace sets the Namespace field in the declarative configuration to the given value
 // and returns the receiver, so that objects can be built by chaining "With" function invocations.
 // If called multiple times, the Namespace field is set to the value of the last call.
-func (b *ParentGatewayReferenceApplyConfiguration) WithNamespace(value apiv1.Namespace) *ParentGatewayReferenceApplyConfiguration {
+func (b *ParentReferenceApplyConfiguration) WithNamespace(value apiv1.Namespace) *ParentReferenceApplyConfiguration {
 	b.Namespace = &value
 	return b
 }
diff --git a/client-go/applyconfiguration/api/v1/poolstatus.go b/client-go/applyconfiguration/api/v1/parentstatus.go
similarity index 57%
rename from client-go/applyconfiguration/api/v1/poolstatus.go
rename to client-go/applyconfiguration/api/v1/parentstatus.go
index 6c582d8..5accb0f 100644
--- a/client-go/applyconfiguration/api/v1/poolstatus.go
+++ b/client-go/applyconfiguration/api/v1/parentstatus.go
@@ -22,23 +22,23 @@ import (
 	metav1 "k8s.io/client-go/applyconfigurations/meta/v1"
 )
 
-// PoolStatusApplyConfiguration represents a declarative configuration of the PoolStatus type for use
+// ParentStatusApplyConfiguration represents a declarative configuration of the ParentStatus type for use
 // with apply.
-type PoolStatusApplyConfiguration struct {
-	Conditions []metav1.ConditionApplyConfiguration      `json:"conditions,omitempty"`
-	GatewayRef *ParentGatewayReferenceApplyConfiguration `json:"parentRef,omitempty"`
+type ParentStatusApplyConfiguration struct {
+	Conditions []metav1.ConditionApplyConfiguration `json:"conditions,omitempty"`
+	ParentRef  *ParentReferenceApplyConfiguration   `json:"parentRef,omitempty"`
 }
 
-// PoolStatusApplyConfiguration constructs a declarative configuration of the PoolStatus type for use with
+// ParentStatusApplyConfiguration constructs a declarative configuration of the ParentStatus type for use with
 // apply.
-func PoolStatus() *PoolStatusApplyConfiguration {
-	return &PoolStatusApplyConfiguration{}
+func ParentStatus() *ParentStatusApplyConfiguration {
+	return &ParentStatusApplyConfiguration{}
 }
 
 // WithConditions adds the given value to the Conditions field in the declarative configuration
 // and returns the receiver, so that objects can be build by chaining "With" function invocations.
 // If called multiple times, values provided by each call will be appended to the Conditions field.
-func (b *PoolStatusApplyConfiguration) WithConditions(values ...*metav1.ConditionApplyConfiguration) *PoolStatusApplyConfiguration {
+func (b *ParentStatusApplyConfiguration) WithConditions(values ...*metav1.ConditionApplyConfiguration) *ParentStatusApplyConfiguration {
 	for i := range values {
 		if values[i] == nil {
 			panic("nil value passed to WithConditions")
@@ -48,10 +48,10 @@ func (b *PoolStatusApplyConfiguration) WithConditions(values ...*metav1.Conditio
 	return b
 }
 
-// WithGatewayRef sets the GatewayRef field in the declarative configuration to the given value
+// WithParentRef sets the ParentRef field in the declarative configuration to the given value
 // and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the GatewayRef field is set to the value of the last call.
-func (b *PoolStatusApplyConfiguration) WithGatewayRef(value *ParentGatewayReferenceApplyConfiguration) *PoolStatusApplyConfiguration {
-	b.GatewayRef = value
+// If called multiple times, the ParentRef field is set to the value of the last call.
+func (b *ParentStatusApplyConfiguration) WithParentRef(value *ParentReferenceApplyConfiguration) *ParentStatusApplyConfiguration {
+	b.ParentRef = value
 	return b
 }
diff --git a/client-go/applyconfiguration/utils.go b/client-go/applyconfiguration/utils.go
index 8a3b6b3..0662699 100644
--- a/client-go/applyconfiguration/utils.go
+++ b/client-go/applyconfiguration/utils.go
@@ -44,10 +44,10 @@ func ForKind(kind schema.GroupVersionKind) interface{} {
 		return &apiv1.InferencePoolStatusApplyConfiguration{}
 	case v1.SchemeGroupVersion.WithKind("LabelSelector"):
 		return &apiv1.LabelSelectorApplyConfiguration{}
-	case v1.SchemeGroupVersion.WithKind("ParentGatewayReference"):
-		return &apiv1.ParentGatewayReferenceApplyConfiguration{}
-	case v1.SchemeGroupVersion.WithKind("PoolStatus"):
-		return &apiv1.PoolStatusApplyConfiguration{}
+	case v1.SchemeGroupVersion.WithKind("ParentReference"):
+		return &apiv1.ParentReferenceApplyConfiguration{}
+	case v1.SchemeGroupVersion.WithKind("ParentStatus"):
+		return &apiv1.ParentStatusApplyConfiguration{}
 	case v1.SchemeGroupVersion.WithKind("Port"):
 		return &apiv1.PortApplyConfiguration{}
 
diff --git a/cmd/epp/runner/runner.go b/cmd/epp/runner/runner.go
index ea0fe56..7d147e5 100644
--- a/cmd/epp/runner/runner.go
+++ b/cmd/epp/runner/runner.go
@@ -25,6 +25,7 @@ import (
 	"net/http"
 	"net/http/pprof"
 	"os"
+	"runtime"
 	"sync/atomic"
 
 	"github.com/go-logr/logr"
@@ -228,6 +229,8 @@ func (r *Runner) Run(ctx context.Context) error {
 			setupLog.Error(err, "Failed to setup pprof handlers")
 			return err
 		}
+		runtime.SetMutexProfileFraction(1)
+		runtime.SetBlockProfileRate(1)
 	}
 
 	err = r.parsePluginsConfiguration(ctx)
@@ -247,7 +250,7 @@ func (r *Runner) Run(ctx context.Context) error {
 
 	scheduler := scheduling.NewSchedulerWithConfig(r.schedulerConfig)
 
-	saturationDetector := saturationdetector.NewDetector(sdConfig, datastore, setupLog)
+	saturationDetector := saturationdetector.NewDetector(sdConfig, setupLog)
 
 	director := requestcontrol.NewDirectorWithConfig(datastore, scheduler, saturationDetector, r.requestControlConfig)
 
diff --git a/config/charts/inferencepool/README.md b/config/charts/inferencepool/README.md
index 3bac9b6..5bbbac7 100644
--- a/config/charts/inferencepool/README.md
+++ b/config/charts/inferencepool/README.md
@@ -83,18 +83,18 @@ $ helm install triton-llama3-8b-instruct \
 
 To deploy the EndpointPicker in a high-availability (HA) active-passive configuration, you can enable leader election. When enabled, the EPP deployment will have multiple replicas, but only one "leader" replica will be active and ready to process traffic at any given time. If the leader pod fails, another pod will be elected as the new leader, ensuring service continuity.
 
-To enable HA, set `inferenceExtension.enableLeaderElection` to `true` and increase the number of replicas in your `values.yaml` file:
+To enable HA, set `inferenceExtension.flags.has-enable-leader-election` to `true` and increase the number of replicas in your `values.yaml` file:
 
 ```yaml
 inferenceExtension:
   replicas: 3
-  enableLeaderElection: true
+  has-enable-leader-election: true
 ```
 
 Then apply it with:
 
 ```txt
-helm install vllm-llama3-8b-instruct ./config/charts/inferencepool -f values.yaml \
+helm install vllm-llama3-8b-instruct ./config/charts/inferencepool -f values.yaml
 ```
 
 ## Uninstall
@@ -122,10 +122,9 @@ The following table list the configurable parameters of the chart.
 | `inferenceExtension.env`                    | List of environment variables to set in the endpoint picker container as free-form YAML. Defaults to `[]`.             |
 | `inferenceExtension.extraContainerPorts`    | List of additional container ports to expose. Defaults to `[]`.                                                        |
 | `inferenceExtension.extraServicePorts`      | List of additional service ports to expose. Defaults to `[]`.                                                          |
-| `inferenceExtension.flags`                  | List of flags which are passed through to endpoint picker.                                                             |
+| `inferenceExtension.flags`                  | List of flags which are passed through to endpoint picker. Example flags, enable-pprof, grpc-port etc. Refer [runner.go](https://github.com/kubernetes-sigs/gateway-api-inference-extension/blob/main/cmd/epp/runner/runner.go) for complete list.                                                            |
+| `inferenceExtension.flags.has-enable-leader-election` | Enable leader election for high availability. When enabled, only one EPP pod (the leader) will be ready to serve traffic.       |
 | `provider.name`                             | Name of the Inference Gateway implementation being used. Possible values: `gke`. Defaults to `none`.                   |
-| `inferenceExtension.enableLeaderElection`   | Enable leader election for high availability. When enabled, only one EPP pod (the leader) will be ready to serve traffic. It is recommended to set `inferenceExtension.replicas` to a value greater than 1 when this is set to `true`. Defaults to `false`. |
-
 
 ## Notes
 
diff --git a/config/charts/inferencepool/templates/epp-deployment.yaml b/config/charts/inferencepool/templates/epp-deployment.yaml
index c262329..3d210fc 100644
--- a/config/charts/inferencepool/templates/epp-deployment.yaml
+++ b/config/charts/inferencepool/templates/epp-deployment.yaml
@@ -29,6 +29,8 @@ spec:
         - {{ .Release.Namespace }}
         - --zap-encoder
         - "json"
+        - --config-file
+        - "/config/default-plugins.yaml"
         {{- range .Values.inferenceExtension.flags }}
         - "--{{ .name }}={{ .value }}"
         {{- end }}
diff --git a/config/charts/inferencepool/values.yaml b/config/charts/inferencepool/values.yaml
index 8d48365..443085e 100644
--- a/config/charts/inferencepool/values.yaml
+++ b/config/charts/inferencepool/values.yaml
@@ -32,51 +32,9 @@ inferenceExtension:
   #   ENABLE_EXPERIMENTAL_FEATURE: "true"
 
   flags:
-    - name: grpc-port
-      value: 9002
-    - name: grpc-health-port
-      value: 9003
-    - name: metrics-port
-      value: 9090
-    - name: enable-pprof
-      value: "true"  # Enable pprof handlers for profiling and debugging
-    - name: pool-group
-      value: "inference.networking.k8s.io"
     # Log verbosity
     - name: v
       value: 1
-    - name: secure-serving
-      value: "true"
-    - name: health-checking
-      value: "false"
-    - name: cert-path
-      value: ""
-    - name: total-queued-requests-metric
-      value: "vllm:num_requests_waiting"
-    - name: kv-cache-usage-percentage-metric
-      value: "vllm:gpu_cache_usage_perc"
-    - name: lora-info-metric
-      value: "vllm:lora_requests_info"
-    - name: refresh-metrics-interval
-      value: "50ms"
-    - name: refresh-prometheus-metrics-interval
-      value: "5s"
-    - name: metrics-staleness-threshold
-      value: "2s"
-    - name: config-file
-      value: ""
-    - name: config-text
-      value: ""
-    - name: model-server-metrics-port
-      value: 0
-    - name: model-server-metrics-path
-      value: "/metrics"
-    - name: model-server-metrics-scheme
-      value: "http"
-    - name: model-server-metrics-https-insecure-skip-verify
-      value: "true"
-    - name: has-enable-leader-election
-      value: false
 
 inferencePool:
   targetPorts:
diff --git a/config/crd/bases/inference.networking.k8s.io_inferencepools.yaml b/config/crd/bases/inference.networking.k8s.io_inferencepools.yaml
index 11ae469..66cbcec 100644
--- a/config/crd/bases/inference.networking.k8s.io_inferencepools.yaml
+++ b/config/crd/bases/inference.networking.k8s.io_inferencepools.yaml
@@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    api-approved.kubernetes.io: unapproved, experimental-only
+    api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api-inference-extension/pull/1173
     inference.networking.k8s.io/bundle-version: main-dev
   creationTimestamp: null
   name: inferencepools.inference.networking.k8s.io
@@ -41,17 +41,18 @@ spec:
           metadata:
             type: object
           spec:
-            description: InferencePoolSpec defines the desired state of InferencePool
+            description: Spec defines the desired state of the InferencePool.
             properties:
               endpointPickerRef:
-                description: EndpointPickerRef configures an endpoint picker as an
-                  extension service.
+                description: |-
+                  EndpointPickerRef is a reference to the Endpoint Picker extension and its
+                  associated configuration.
                 properties:
                   failureMode:
                     default: FailClose
                     description: |-
-                      Configures how the gateway handles the case when the extension is not responsive.
-                      Defaults to failClose.
+                      FailureMode configures how the parent handles the case when the Endpoint Picker extension
+                      is non-responsive. When unspecified, defaults to "FailClose".
                     enum:
                     - FailOpen
                     - FailClose
@@ -59,8 +60,8 @@ spec:
                   group:
                     default: ""
                     description: |-
-                      Group is the group of the referent.
-                      The default value is "", representing the Core API group.
+                      Group is the group of the referent API object. When unspecified, the default value
+                      is "", representing the Core API group.
                     maxLength: 253
                     minLength: 0
                     pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
@@ -70,6 +71,8 @@ spec:
                     description: |-
                       Kind is the Kubernetes resource kind of the referent.
 
+                      Required if the referent is ambiguous, e.g. service with multiple ports.
+
                       Defaults to "Service" when not specified.
 
                       ExternalName services can refer to CNAME DNS records that may live
@@ -82,15 +85,15 @@ spec:
                     pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
                     type: string
                   name:
-                    description: Name is the name of the referent.
+                    description: Name is the name of the referent API object.
                     maxLength: 253
                     minLength: 1
                     type: string
                   portNumber:
                     description: |-
-                      The port number on the service running the extension. When unspecified,
-                      implementations SHOULD infer a default value of 9002 when the Kind is
-                      Service.
+                      PortNumber is the port number of the Endpoint Picker extension service. When unspecified,
+                      implementations SHOULD infer a default value of 9002 when the kind field is "Service" or
+                      unspecified (defaults to "Service").
                     format: int32
                     maximum: 65535
                     minimum: 1
@@ -127,7 +130,7 @@ spec:
                       pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$
                       type: string
                     description: |-
-                      matchLabels contains a set of required {key,value} pairs.
+                      MatchLabels contains a set of required {key,value} pairs.
                       An object must match every label in this map to be selected.
                       The matching logic is an AND operation on all entries.
                     type: object
@@ -163,48 +166,30 @@ spec:
             - targetPorts
             type: object
           status:
-            default:
-              parent:
-              - conditions:
-                - lastTransitionTime: "1970-01-01T00:00:00Z"
-                  message: Waiting for controller
-                  reason: Pending
-                  status: Unknown
-                  type: Accepted
-                parentRef:
-                  kind: Status
-                  name: default
-            description: Status defines the observed state of InferencePool.
-            minProperties: 1
+            description: Status defines the observed state of the InferencePool.
             properties:
-              parent:
+              parents:
                 description: |-
-                  Parents is a list of parent resources (usually Gateways) that are
-                  associated with the InferencePool, and the status of the InferencePool with respect to
-                  each parent.
+                  Parents is a list of parent resources, typically Gateways, that are associated with
+                  the InferencePool, and the status of the InferencePool with respect to each parent.
 
-                  A maximum of 32 Gateways will be represented in this list. When the list contains
-                  `kind: Status, name: default`, it indicates that the InferencePool is not
-                  associated with any Gateway and a controller must perform the following:
+                  A controller that manages the InferencePool, must add an entry for each parent it manages
+                  and remove the parent entry when the controller no longer considers the InferencePool to
+                  be associated with that parent.
 
-                   - Remove the parent when setting the "Accepted" condition.
-                   - Add the parent when the controller will no longer manage the InferencePool
-                     and no other parents exist.
+                  A maximum of 32 parents will be represented in this list. When the list is empty,
+                  it indicates that the InferencePool is not associated with any parents.
                 items:
-                  description: PoolStatus defines the observed state of InferencePool
-                    from a Gateway.
+                  description: ParentStatus defines the observed state of InferencePool
+                    from a Parent, i.e. Gateway.
                   properties:
                     conditions:
-                      default:
-                      - lastTransitionTime: "1970-01-01T00:00:00Z"
-                        message: Waiting for controller
-                        reason: Pending
-                        status: Unknown
-                        type: Accepted
                       description: |-
-                        Conditions track the state of the InferencePool.
+                        Conditions is a list of status conditions that provide information about the observed
+                        state of the InferencePool. This field is required to be set by the controller that
+                        manages the InferencePool.
 
-                        Known condition types are:
+                        Supported condition types are:
 
                         * "Accepted"
                         * "ResolvedRefs"
@@ -269,33 +254,43 @@ spec:
                       - type
                       x-kubernetes-list-type: map
                     parentRef:
-                      description: GatewayRef indicates the gateway that observed
-                        state of InferencePool.
+                      description: |-
+                        ParentRef is used to identify the parent resource that this status
+                        is associated with. It is used to match the InferencePool with the parent
+                        resource, such as a Gateway.
                       properties:
                         group:
                           default: gateway.networking.k8s.io
-                          description: Group is the group of the referent.
+                          description: |-
+                            Group is the group of the referent API object. When unspecified, the referent is assumed
+                            to be in the "gateway.networking.k8s.io" API group.
                           maxLength: 253
                           minLength: 0
                           pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
                           type: string
                         kind:
                           default: Gateway
-                          description: Kind is kind of the referent. For example "Gateway".
+                          description: |-
+                            Kind is the kind of the referent API object. When unspecified, the referent is assumed
+                            to be a "Gateway" kind.
                           maxLength: 63
                           minLength: 1
                           pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
                           type: string
                         name:
-                          description: Name is the name of the referent.
+                          description: Name is the name of the referent API object.
                           maxLength: 253
                           minLength: 1
                           type: string
                         namespace:
                           description: |-
-                            Namespace is the namespace of the referent.  If not present,
-                            the namespace of the referent is assumed to be the same as
-                            the namespace of the referring object.
+                            Namespace is the namespace of the referenced object. When unspecified, the local
+                            namespace is inferred.
+
+                            Note that when a namespace different than the local namespace is specified,
+                            a ReferenceGrant object is required in the referent namespace to allow that
+                            namespace's owner to accept the reference. See the ReferenceGrant
+                            documentation for details: https://gateway-api.sigs.k8s.io/api-types/referencegrant/
                           maxLength: 63
                           minLength: 1
                           pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
diff --git a/config/crd/bases/inference.networking.x-k8s.io_inferenceobjectives.yaml b/config/crd/bases/inference.networking.x-k8s.io_inferenceobjectives.yaml
index 7f0968f..27ad4e5 100644
--- a/config/crd/bases/inference.networking.x-k8s.io_inferenceobjectives.yaml
+++ b/config/crd/bases/inference.networking.x-k8s.io_inferenceobjectives.yaml
@@ -100,7 +100,7 @@ spec:
                   The higher the value, the more critical the request is; negative values _are_ allowed.
                   No default value is set for this field, allowing for future additions of new fields that may 'one of' with this field.
                   However, implementations that consume this field (such as the Endpoint Picker) will treat an unset value as '0'.
-                  Priority is used in flow control, primarily in the event of resource scarcity(reqeusts need to be queued).
+                  Priority is used in flow control, primarily in the event of resource scarcity(requests need to be queued).
                   All requests will be queued, and flow control will _always_ allow requests of higher priority to be served first.
                   Fairness is only enforced and tracked between requests of the same priority.
 
diff --git a/conformance/utils/kubernetes/helpers.go b/conformance/utils/kubernetes/helpers.go
index 39301e3..b4018a7 100644
--- a/conformance/utils/kubernetes/helpers.go
+++ b/conformance/utils/kubernetes/helpers.go
@@ -105,7 +105,9 @@ func InferencePoolMustHaveCondition(t *testing.T, c client.Reader, poolNN types.
 			}
 
 			for _, parentStatus := range pool.Status.Parents {
-				if string(parentStatus.GatewayRef.Namespace) == gateway.Namespace && string(parentStatus.GatewayRef.Name) == gateway.Name {
+				if parentStatus.ParentRef.Namespace != "" &&
+					string(parentStatus.ParentRef.Namespace) == gateway.Namespace &&
+					string(parentStatus.ParentRef.Name) == gateway.Name {
 					if checkCondition(t, parentStatus.Conditions, expectedCondition) {
 						conditionFound = true
 						return true, nil
@@ -130,8 +132,11 @@ func InferencePoolMustHaveCondition(t *testing.T, c client.Reader, poolNN types.
 				debugMsg += " (No parent statuses reported)"
 			}
 			for i, parentStatus := range lastObservedPool.Status.Parents {
-				namespace := parentStatus.GatewayRef.Namespace
-				debugMsg += fmt.Sprintf("\n  Parent %d (Gateway: %s/%s):", i, namespace, parentStatus.GatewayRef.Name)
+				namespace := parentStatus.ParentRef.Namespace
+				if namespace == "" {
+					namespace = inferenceapi.Namespace(poolNN.Namespace) // Fallback to the pool's namespace
+				}
+				debugMsg += fmt.Sprintf("\n  Parent %d (Gateway: %s/%s):", i, namespace, parentStatus.ParentRef.Name)
 				if len(parentStatus.Conditions) == 0 {
 					debugMsg += " (No conditions reported for this parent)"
 				}
diff --git a/go.mod b/go.mod
index f43559a..77129f8 100644
--- a/go.mod
+++ b/go.mod
@@ -10,7 +10,7 @@ require (
 	github.com/google/go-cmp v0.7.0
 	github.com/google/uuid v1.6.0
 	github.com/hashicorp/golang-lru/v2 v2.0.7
-	github.com/onsi/ginkgo/v2 v2.24.0
+	github.com/onsi/ginkgo/v2 v2.25.1
 	github.com/onsi/gomega v1.38.0
 	github.com/prometheus/client_golang v1.23.0
 	github.com/prometheus/client_model v0.6.2
diff --git a/go.sum b/go.sum
index 5a2d94c..95d8062 100644
--- a/go.sum
+++ b/go.sum
@@ -196,8 +196,8 @@ github.com/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s=
 github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
 github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
 github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
-github.com/onsi/ginkgo/v2 v2.24.0 h1:obZz8LAnHicNdbBqvG3ytAFx8fgza+i1IDpBVcHT2YE=
-github.com/onsi/ginkgo/v2 v2.24.0/go.mod h1:ppTWQ1dh9KM/F1XgpeRqelR+zHVwV81DGRSDnFxK7Sk=
+github.com/onsi/ginkgo/v2 v2.25.1 h1:Fwp6crTREKM+oA6Cz4MsO8RhKQzs2/gOIVOUscMAfZY=
+github.com/onsi/ginkgo/v2 v2.25.1/go.mod h1:ppTWQ1dh9KM/F1XgpeRqelR+zHVwV81DGRSDnFxK7Sk=
 github.com/onsi/gomega v1.38.0 h1:c/WX+w8SLAinvuKKQFh77WEucCnPk4j2OTUr7lt7BeY=
 github.com/onsi/gomega v1.38.0/go.mod h1:OcXcwId0b9QsE7Y49u+BTrL4IdKOBOKnD6VQNTJEB6o=
 github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
diff --git a/mkdocs.yml b/mkdocs.yml
index 4bb94f5..982efbf 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -72,6 +72,7 @@ nav:
       - Configuration Guide:
           - Configuring the plugins via configuration files or text: guides/epp-configuration/config-text.md    
           - Prefix Cache Aware Plugin: guides/epp-configuration/prefix-aware.md
+      - Troubleshooting Guide: guides/troubleshooting.md
     - Implementer Guides:
       - Getting started: guides/implementers.md
       - Conformance Tests: guides/conformance-tests.md
diff --git a/pkg/epp/flowcontrol/contracts/doc.go b/pkg/epp/flowcontrol/contracts/doc.go
new file mode 100644
index 0000000..554f54e
--- /dev/null
+++ b/pkg/epp/flowcontrol/contracts/doc.go
@@ -0,0 +1,29 @@
+/*
+Copyright 2025 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Package contracts defines the boundaries and service interfaces for the Flow Control system.
+//
+// Adhering to a "Ports and Adapters" (Hexagonal) architectural style, these interfaces decouple the core
+// `controller.FlowController` engine from its dependencies. They establish the required behaviors and system invariants
+// that concrete implementations must uphold.
+//
+// The primary contracts are:
+//
+//   - `FlowRegistry`: The interface for the stateful control plane that manages the lifecycle of flows, queues, and
+//     policies.
+//
+//   - `SaturationDetector`: The interface for a component that provides real-time load signals.
+package contracts
diff --git a/pkg/epp/flowcontrol/contracts/errors.go b/pkg/epp/flowcontrol/contracts/errors.go
index fd46ec7..38af370 100644
--- a/pkg/epp/flowcontrol/contracts/errors.go
+++ b/pkg/epp/flowcontrol/contracts/errors.go
@@ -18,18 +18,19 @@ package contracts
 
 import "errors"
 
-// Registry Errors
 var (
-	// ErrFlowInstanceNotFound indicates that a requested flow instance (a `ManagedQueue`) does not exist in the registry
-	// shard, either because the flow is not registered or the specific instance (e.g., a draining queue at a particular
-	// priority) is not present.
+	// ErrFlowInstanceNotFound indicates that a requested flow instance (a `ManagedQueue`) does not exist.
 	ErrFlowInstanceNotFound = errors.New("flow instance not found")
 
-	// ErrPriorityBandNotFound indicates that a requested priority band does not exist in the registry because it was not
-	// part of the initial configuration.
+	// ErrFlowIDEmpty indicates that a flow specification was provided with an empty flow ID.
+	ErrFlowIDEmpty = errors.New("flow ID cannot be empty")
+
+	// ErrPriorityBandNotFound indicates that a requested priority band does not exist in the registry configuration.
 	ErrPriorityBandNotFound = errors.New("priority band not found")
 
-	// ErrPolicyQueueIncompatible indicates that a selected policy is not compatible with the capabilities of the queue it
-	// is intended to operate on. For example, a policy requiring priority-based peeking is used with a simple FIFO queue.
+	// ErrPolicyQueueIncompatible indicates that a selected policy is not compatible with the capabilities of the queue.
 	ErrPolicyQueueIncompatible = errors.New("policy is not compatible with queue capabilities")
+
+	// ErrInvalidShardCount indicates that an invalid shard count was provided (e.g., zero or negative).
+	ErrInvalidShardCount = errors.New("invalid shard count")
 )
diff --git a/pkg/epp/flowcontrol/contracts/registry.go b/pkg/epp/flowcontrol/contracts/registry.go
index b823ae0..1b788d9 100644
--- a/pkg/epp/flowcontrol/contracts/registry.go
+++ b/pkg/epp/flowcontrol/contracts/registry.go
@@ -14,12 +14,6 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-// Package contracts defines the service interfaces that decouple the core `controller.FlowController` engine from its
-// primary dependencies. In alignment with a "Ports and Adapters" (or "Hexagonal") architectural style, these
-// interfaces represent the "ports" through which the engine communicates.
-//
-// This package contains the primary service contracts for the Flow Registry, which acts as the control plane for all
-// flow state and configuration.
 package contracts
 
 import (
@@ -27,10 +21,100 @@ import (
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/types"
 )
 
-// RegistryShard defines the read-oriented interface that a `controller.FlowController` worker uses to access its
-// specific slice (shard) of the `FlowRegistry's` state. It provides a concurrent-safe view of all flow instances, which
-// are uniquely identified by their composite `types.FlowKey`. It is the primary contract for performing dispatch
-// operations.
+// FlowRegistry is the complete interface for the global control plane. An implementation of this interface is the single
+// source of truth for all flow control state and configuration.
+//
+// # Conformance
+//
+// All methods MUST be goroutine-safe. Implementations are expected to perform complex updates (e.g.,
+// `RegisterOrUpdateFlow`) atomically.
+//
+// # System Invariants
+//
+// Concrete implementations MUST uphold the following invariants:
+//  1. Shard Consistency: All configured priority bands and registered flow instances must exist on every Active shard.
+//     Plugin instance types must be consistent for a given flow across all shards.
+//  2. Flow Instance Uniqueness: Each unique `types.FlowKey` (`ID` + `Priority`) corresponds to exactly one managed flow
+//     instance.
+//  3. Capacity Partitioning: Global and per-band capacity limits must be uniformly partitioned across all Active
+//     shards.
+//
+// # Flow Lifecycle
+//
+// A flow instance (identified by its immutable `FlowKey`) has a simple lifecycle:
+//
+//   - Registered: Known to the `FlowRegistry` via `RegisterOrUpdateFlow`.
+//   - Idle: Queues are empty across all Active and Draining shards.
+//   - Garbage Collected (Unregistered): The registry automatically garbage collects flows after they have remained Idle
+//     for a configurable duration.
+//
+// # Shard Lifecycle
+//
+// When a shard is decommissioned, it is marked inactive (`IsActive() == false`) to prevent new enqueues. The shard
+// continues to drain and is deleted only after it is empty.
+type FlowRegistry interface {
+	FlowRegistryAdmin
+	ShardProvider
+}
+
+// FlowRegistryAdmin defines the administrative interface for the global control plane.
+//
+// # Dynamic Update Strategies
+//
+// The contract specifies behaviors for handling dynamic updates, prioritizing stability and correctness:
+//
+//   - Immutable Flow Identity (`types.FlowKey`): The system treats the `FlowKey` (`ID` + `Priority`) as the immutable
+//     identifier. Changing the priority of traffic requires registering a new `FlowKey`. The old flow instance is
+//     automatically garbage collected when Idle. This design eliminates complex priority migration logic.
+//
+//   - Graceful Draining (Shard Scale-Down): Decommissioned shards enter a Draining state. They stop accepting new
+//     requests but continue to be processed for dispatch until empty.
+//
+//   - Self-Balancing (Shard Scale-Up): When new shards are added, the `controller.FlowController`'s distribution logic
+//     naturally utilizes them, funneling new requests to the less-loaded shards. Existing queued items are not
+//     migrated.
+type FlowRegistryAdmin interface {
+	// RegisterOrUpdateFlow handles the registration of a new flow instance or the update of an existing instance's
+	// specification (for the same `types.FlowKey`). The operation is atomic across all shards.
+	//
+	// Since the `FlowKey` (including `Priority`) is immutable, this method cannot change a flow's priority.
+	// To change priority, the caller should simply register the new `FlowKey`; the old flow instance will be
+	// automatically garbage collected when it becomes Idle.
+	//
+	// Returns errors wrapping `ErrFlowIDEmpty`, `ErrPriorityBandNotFound`, or internal errors if plugin instantiation
+	// fails.
+	RegisterOrUpdateFlow(spec types.FlowSpecification) error
+
+	// UpdateShardCount dynamically adjusts the number of internal state shards.
+	//
+	// The implementation MUST atomically re-partition capacity allocations across all active shards.
+	// Returns an error wrapping `ErrInvalidShardCount` if `n` is not positive.
+	UpdateShardCount(n int) error
+
+	// Stats returns globally aggregated statistics for the entire `FlowRegistry`.
+	Stats() AggregateStats
+
+	// ShardStats returns a slice of statistics, one for each internal shard. This provides visibility for debugging and
+	// monitoring per-shard behavior (e.g., identifying hot or stuck shards).
+	ShardStats() []ShardStats
+}
+
+// ShardProvider defines the interface for discovering available shards.
+//
+// A "shard" is an internal, parallel execution unit that allows the `controller.FlowController`'s core dispatch logic
+// to be parallelized, preventing a CPU bottleneck at high request rates. The `FlowRegistry`'s state is sharded to
+// support this parallelism by reducing lock contention.
+//
+// Consumers MUST check `RegistryShard.IsActive()` before routing new work to a shard to avoid sending requests to a
+// Draining shard.
+type ShardProvider interface {
+	// Shards returns a slice of accessors, one for each internal state shard (Active and Draining).
+	// Callers should not modify the returned slice.
+	Shards() []RegistryShard
+}
+
+// RegistryShard defines the interface for accessing a specific slice (shard) of the `FlowRegistry's` state.
+// It provides a concurrent-safe view for `controller.FlowController` workers.
 //
 // # Conformance
 //
@@ -46,12 +130,12 @@ type RegistryShard interface {
 	// ManagedQueue retrieves the managed queue for the given, unique `types.FlowKey`. This is the primary method for
 	// accessing a specific flow's queue for either enqueueing or dispatching requests.
 	//
-	// Returns an error wrapping `ErrPriorityBandNotFound` if the priority specified in the key is not configured, or
+	// Returns an error wrapping `ErrPriorityBandNotFound` if the priority specified in the `key` is not configured, or
 	// `ErrFlowInstanceNotFound` if no instance exists for the given `key`.
 	ManagedQueue(key types.FlowKey) (ManagedQueue, error)
 
 	// IntraFlowDispatchPolicy retrieves a flow's configured `framework.IntraFlowDispatchPolicy` for this shard,
-	// identified by its unique `FlowKey`.
+	// identified by its unique `types.FlowKey`.
 	// The registry guarantees that a non-nil default policy (as configured at the priority-band level) is returned if
 	// none is specified for the flow.
 	// Returns an error wrapping `ErrFlowInstanceNotFound` if the flow instance does not exist.
@@ -63,8 +147,8 @@ type RegistryShard interface {
 	InterFlowDispatchPolicy(priority uint) (framework.InterFlowDispatchPolicy, error)
 
 	// PriorityBandAccessor retrieves a read-only accessor for a given priority level, providing a view of the band's
-	// state as seen by this specific shard. This is the primary entry point for inter-flow dispatch policies that
-	// need to inspect and compare multiple flow queues within the same priority band.
+	// state as seen by this specific shard. This is the primary entry point for inter-flow dispatch policies that need to
+	// inspect and compare multiple flow queues within the same priority band.
 	// Returns an error wrapping `ErrPriorityBandNotFound` if the priority level is not configured.
 	PriorityBandAccessor(priority uint) (framework.PriorityBandAccessor, error)
 
@@ -80,24 +164,33 @@ type RegistryShard interface {
 }
 
 // ManagedQueue defines the interface for a flow's queue instance on a specific shard.
-// It wraps an underlying `framework.SafeQueue`, augmenting it with lifecycle validation against the `FlowRegistry` and
-// integrating atomic statistics updates.
+// It acts as a stateful decorator around an underlying `framework.SafeQueue`.
 //
 // # Conformance
 //
-//   - All methods (including those embedded from `framework.SafeQueue`) MUST be goroutine-safe.
-//   - All mutating methods (`Add()`, `Remove()`, `Cleanup()`, `Drain()`) MUST atomically update relevant statistics
-//     (e.g., queue length, byte size).
+//   - All methods MUST be goroutine-safe.
+//   - All mutating methods (`Add()`, `Remove()`, etc.) MUST ensure that the underlying queue state and the statistics
+//     (`Len`, `ByteSize`) are updated atomically relative to each other.
 type ManagedQueue interface {
 	framework.SafeQueue
 
-	// FlowQueueAccessor returns a read-only, flow-aware accessor for this queue.
-	// This accessor is primarily used by policy plugins to inspect the queue's state in a structured way.
-	//
+	// FlowQueueAccessor returns a read-only, flow-aware accessor for this queue, used by policy plugins.
 	// Conformance: This method MUST NOT return nil.
 	FlowQueueAccessor() framework.FlowQueueAccessor
 }
 
+// AggregateStats holds globally aggregated statistics for the entire `FlowRegistry`.
+type AggregateStats struct {
+	// TotalCapacityBytes is the globally configured maximum total byte size limit across all priority bands and shards.
+	TotalCapacityBytes uint64
+	// TotalByteSize is the total byte size of all items currently queued across the entire system.
+	TotalByteSize uint64
+	// TotalLen is the total number of items currently queued across the entire system.
+	TotalLen uint64
+	// PerPriorityBandStats maps each configured priority level to its globally aggregated statistics.
+	PerPriorityBandStats map[uint]PriorityBandStats
+}
+
 // ShardStats holds statistics for a single internal shard within the `FlowRegistry`.
 type ShardStats struct {
 	// TotalCapacityBytes is the optional, maximum total byte size limit aggregated across all priority bands within this
@@ -110,35 +203,22 @@ type ShardStats struct {
 	// TotalLen is the total number of items currently queued across all priority bands within this shard.
 	TotalLen uint64
 	// PerPriorityBandStats maps each configured priority level to its statistics within this shard.
+	// The capacity values within represent this shard's partition of the global band capacity.
 	// The key is the numerical priority level.
 	// All configured priority levels are guaranteed to be represented.
 	PerPriorityBandStats map[uint]PriorityBandStats
 }
 
-// DeepCopy returns a deep copy of the `ShardStats`.
-func (s *ShardStats) DeepCopy() ShardStats {
-	if s == nil {
-		return ShardStats{}
-	}
-	newStats := *s
-	if s.PerPriorityBandStats != nil {
-		newStats.PerPriorityBandStats = make(map[uint]PriorityBandStats, len(s.PerPriorityBandStats))
-		for k, v := range s.PerPriorityBandStats {
-			newStats.PerPriorityBandStats[k] = v.DeepCopy()
-		}
-	}
-	return newStats
-}
-
 // PriorityBandStats holds aggregated statistics for a single priority band.
 type PriorityBandStats struct {
 	// Priority is the numerical priority level this struct describes.
 	Priority uint
-	// PriorityName is an optional, human-readable name for the priority level (e.g., "Critical", "Sheddable").
+	// PriorityName is a human-readable name for the priority band (e.g., "Critical", "Sheddable").
+	// The registry configuration requires this field, so it is guaranteed to be non-empty.
 	PriorityName string
-	// CapacityBytes is the configured maximum total byte size for this priority band, aggregated across all items in
-	// all flow queues within this band. If scoped to a shard, its value represents the configured band limit for the
-	// `FlowRegistry` partitioned for this shard.
+	// CapacityBytes is the configured maximum total byte size for this priority band.
+	// When viewed via `AggregateStats`, this is the global limit. When viewed via `ShardStats`, this is the partitioned
+	// value for that specific shard.
 	// The `controller.FlowController` enforces this limit.
 	// A default non-zero value is guaranteed if not configured.
 	CapacityBytes uint64
@@ -147,11 +227,3 @@ type PriorityBandStats struct {
 	// Len is the total number of items currently queued in this priority band.
 	Len uint64
 }
-
-// DeepCopy returns a deep copy of the `PriorityBandStats`.
-func (s *PriorityBandStats) DeepCopy() PriorityBandStats {
-	if s == nil {
-		return PriorityBandStats{}
-	}
-	return *s
-}
diff --git a/pkg/epp/flowcontrol/registry/config.go b/pkg/epp/flowcontrol/registry/config.go
index ed98ab8..d404e78 100644
--- a/pkg/epp/flowcontrol/registry/config.go
+++ b/pkg/epp/flowcontrol/registry/config.go
@@ -19,6 +19,7 @@ package registry
 import (
 	"errors"
 	"fmt"
+	"time"
 
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/contracts"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework"
@@ -30,67 +31,213 @@ import (
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/plugins/queue/listqueue"
 )
 
-// Config holds the master configuration for the entire `FlowRegistry`. It serves as the top-level blueprint, defining
-// global capacity limits and the structure of its priority bands.
+// =============================================================================
+// Default Values
+// =============================================================================
+
+const (
+	// defaultPriorityBandMaxBytes is the default global capacity for a priority band if not explicitly configured.
+	// It is set to 1 GB.
+	defaultPriorityBandMaxBytes uint64 = 1_000_000_000
+	// defaultIntraFlowDispatchPolicy is the default policy for selecting items within a single flow's queue.
+	defaultIntraFlowDispatchPolicy intra.RegisteredPolicyName = fcfs.FCFSPolicyName
+	// defaultInterFlowDispatchPolicy is the default policy for selecting which flow's queue to service next.
+	defaultInterFlowDispatchPolicy inter.RegisteredPolicyName = besthead.BestHeadPolicyName
+	// defaultQueue is the default queue implementation for flows.
+	defaultQueue queue.RegisteredQueueName = listqueue.ListQueueName
+	// defaultInitialShardCount is the default number of parallel shards to create when the registry is initialized.
+	defaultInitialShardCount int = 1
+	// defaultFlowGCTimeout is the default duration of inactivity after which an idle flow is garbage collected.
+	// This also serves as the interval for the periodic garbage collection scan.
+	defaultFlowGCTimeout time.Duration = 5 * time.Minute
+	// defaultEventChannelBufferSize is the default size of the buffered channel for control plane events.
+	defaultEventChannelBufferSize int = 4096
+)
+
+// =============================================================================
+// Global Configuration (FlowRegistry)
+// =============================================================================
+
+// Config holds the master configuration for the entire `FlowRegistry`.
+// It serves as the top-level blueprint, defining global settings and the templates for its priority bands.
 //
-// This master configuration is validated and defaulted once at startup. It is then partitioned and distributed to each
-// internal `registryShard`, ensuring a consistent and predictable state across the system.
+// This configuration is validated and defaulted once at startup. It is then used to generate partitioned `ShardConfig`
+// instances for each internal `registryShard`.
 type Config struct {
 	// MaxBytes defines an optional, global maximum total byte size limit aggregated across all priority bands and shards.
 	// The `controller.FlowController` enforces this limit in addition to per-band capacity limits.
-	//
-	// Optional: Defaults to 0, which signifies that the global limit is ignored.
+	// A value of 0 signifies that this global limit is ignored, and only per-band limits apply.
+	// Optional: Defaults to 0.
 	MaxBytes uint64
 
-	// PriorityBands defines the set of priority bands managed by the `FlowRegistry`. The configuration for each band,
-	// including its default policies and queue types, is specified here.
-	//
+	// PriorityBands defines the set of priority band templates managed by the `FlowRegistry`.
+	// The configuration for each band, including its default policies and queue types, is specified here.
+	// These templates are used to generate partitioned `ShardPriorityBandConfig`s.
 	// Required: At least one `PriorityBandConfig` must be provided for a functional registry.
 	PriorityBands []PriorityBandConfig
+
+	// InitialShardCount specifies the number of parallel shards to create when the registry is initialized.
+	// This value must be greater than zero.
+	// Optional: Defaults to `defaultInitialShardCount` (1).
+	InitialShardCount int
+
+	// FlowGCTimeout defines the interval at which the registry scans for and garbage collects idle flows. A flow is
+	// collected if it has been observed to be Idle for at least one full scan interval.
+	// Optional: Defaults to `defaultFlowGCTimeout` (5 minutes).
+	FlowGCTimeout time.Duration
+
+	// EventChannelBufferSize defines the size of the buffered channel used for internal control plane events.
+	// A larger buffer can absorb larger bursts of events (e.g., from many queues becoming non-empty simultaneously)
+	// without blocking the data path, but consumes more memory.
+	// This value must be greater than zero.
+	// Optional: Defaults to `defaultEventChannelBufferSize` (4096).
+	EventChannelBufferSize int
+
+	// priorityBandMap provides O(1) lookups of `PriorityBandConfig` by priority level.
+	// Crucially, this map serves as a correctness mechanism. It ensures that accessors return a safe, stable pointer to
+	// the correct element within this specific configuration instance, preventing common "pointer-to-loop-variable"
+	// errors, especially across deep copies or partitioning.
+	// It is populated during validation and when the config is copied or partitioned.
+	priorityBandMap map[uint]*PriorityBandConfig
+
+	// Factory functions used for plugin instantiation during configuration validation.
+	// These enable dependency injection for unit testing the validation logic.
+	interFlowDispatchPolicyFactory interFlowDispatchPolicyFactory
+	intraFlowDispatchPolicyFactory intraFlowDispatchPolicyFactory
+	queueFactory                   queueFactory
 }
 
-// partition calculates and returns a new `Config` with capacity values partitioned for a specific shard.
-// This method ensures that the total capacity is distributed as evenly as possible across all shards.
-func (c *Config) partition(shardIndex, totalShards int) (*Config, error) {
-	if totalShards <= 0 || shardIndex < 0 || shardIndex >= totalShards {
-		return nil, fmt.Errorf("invalid shard partitioning arguments: shardIndex=%d, totalShards=%d",
-			shardIndex, totalShards)
-	}
+// PriorityBandConfig defines the configuration template for a single priority band.
+// It establishes the default behaviors (such as queueing and dispatch policies) and total capacity limits for all flows
+// that operate at this priority level.
+type PriorityBandConfig struct {
+	// Priority is the unique numerical priority level for this band.
+	// Convention: Lower numerical values indicate higher priority (e.g., 0 is highest).
+	// Required.
+	Priority uint
 
-	partitionValue := func(total uint64) uint64 {
-		if total == 0 {
-			return 0
-		}
-		base := total / uint64(totalShards)
-		remainder := total % uint64(totalShards)
-		if uint64(shardIndex) < remainder {
-			return base + 1
-		}
-		return base
-	}
+	// PriorityName is a human-readable name for this priority band (e.g., "Critical", "Standard").
+	// It must be unique across all priority bands in the configuration.
+	// Required.
+	PriorityName string
 
-	newCfg := &Config{
-		MaxBytes:      partitionValue(c.MaxBytes),
-		PriorityBands: make([]PriorityBandConfig, len(c.PriorityBands)),
-	}
+	// IntraFlowDispatchPolicy specifies the default name of the policy used to select a request from within a single
+	// flow's queue in this band.
+	// Optional: Defaults to `defaultIntraFlowDispatchPolicy` ("FCFS").
+	IntraFlowDispatchPolicy intra.RegisteredPolicyName
 
-	for i, band := range c.PriorityBands {
-		newBand := band                                  // Copy the original config
-		newBand.MaxBytes = partitionValue(band.MaxBytes) // Overwrite with the partitioned value
-		newCfg.PriorityBands[i] = newBand
-	}
+	// InterFlowDispatchPolicy specifies the name of the policy used to select which flow's queue to service next from
+	// this band.
+	// Optional: Defaults to `defaultInterFlowDispatchPolicy` ("BestHead").
+	InterFlowDispatchPolicy inter.RegisteredPolicyName
+
+	// Queue specifies the default name of the `framework.SafeQueue` implementation for flow queues in this band.
+	// Optional: Defaults to `defaultQueue` ("ListQueue").
+	Queue queue.RegisteredQueueName
 
+	// MaxBytes defines the maximum total byte size for this priority band, aggregated across all shards.
+	// Optional: Defaults to `defaultPriorityBandMaxBytes` (1 GB).
+	MaxBytes uint64
+}
+
+// NewConfig performs validation and initialization, returning a guaranteed-valid `Config` object.
+// This is the required constructor for creating a new configuration. It applies provided functional options (primarily
+// for testing) and does not mutate the input `cfg`.
+func NewConfig(cfg Config, opts ...configOption) (*Config, error) {
+	newCfg := cfg.deepCopy()
+	for _, opt := range opts {
+		opt(newCfg)
+	}
+	if err := newCfg.validateAndApplyDefaults(); err != nil {
+		return nil, err
+	}
 	return newCfg, nil
 }
 
-// validateAndApplyDefaults checks the configuration for validity and populates any empty fields with system defaults.
-// This method should be called once by the registry before it initializes any shards.
+// =============================================================================
+// Shard-Level Configuration
+// =============================================================================
+
+// ShardConfig holds the partitioned configuration for a single `registryShard`.
+// It contains only the data relevant to that shard and is derived from the global `Config`.
+type ShardConfig struct {
+	// MaxBytes is this shard's partitioned portion of the global `Config.MaxBytes` limit.
+	MaxBytes uint64
+
+	// PriorityBands holds the partitioned configuration for each priority band managed by this shard.
+	PriorityBands []ShardPriorityBandConfig
+
+	// priorityBandMap provides O(1) lookups of `ShardPriorityBandConfig` by priority level.
+	// It serves as a correctness mechanism, ensuring that accessors return a safe, stable pointer to the correct element
+	// within this specific shard configuration instance.
+	priorityBandMap map[uint]*ShardPriorityBandConfig
+}
+
+// ShardPriorityBandConfig holds the partitioned configuration for a single priority band within a single shard.
+type ShardPriorityBandConfig struct {
+	// Priority is the unique numerical priority level for this band.
+	Priority uint
+	// PriorityName is a unique human-readable name for this priority band.
+	PriorityName string
+	// IntraFlowDispatchPolicy is the name of the policy for dispatch within a flow's queue.
+	IntraFlowDispatchPolicy intra.RegisteredPolicyName
+	// InterFlowDispatchPolicy is the name of the policy for dispatch between flow queues.
+	InterFlowDispatchPolicy inter.RegisteredPolicyName
+	// Queue is the name of the queue implementation to use.
+	Queue queue.RegisteredQueueName
+	// MaxBytes is this shard's partitioned portion of this band's global capacity limit.
+	// The `controller.FlowController` enforces this limit for this specific shard.
+	MaxBytes uint64
+}
+
+// getBandConfig finds and returns the shard-level configuration for a specific priority level.
+// Returns an error wrapping `contracts.ErrPriorityBandNotFound` if the priority is not configured.
+func (sc *ShardConfig) getBandConfig(priority uint) (*ShardPriorityBandConfig, error) {
+	if band, ok := sc.priorityBandMap[priority]; ok {
+		return band, nil
+	}
+	return nil, fmt.Errorf("shard config for priority %d not found: %w", priority, contracts.ErrPriorityBandNotFound)
+}
+
+// =============================================================================
+// Internal Methods and Helpers
+// =============================================================================
+
+// --- Validation and Defaulting ---
+
+// validateAndApplyDefaults checks the global configuration for validity (including plugin compatibility) and mutates
+// the receiver to populate any empty fields with system defaults. It also initializes internal lookup maps.
 func (c *Config) validateAndApplyDefaults() error {
+	// Apply defaults to top-level fields.
+	if c.InitialShardCount <= 0 {
+		c.InitialShardCount = defaultInitialShardCount
+	}
+	if c.FlowGCTimeout <= 0 {
+		c.FlowGCTimeout = defaultFlowGCTimeout
+	}
+	if c.EventChannelBufferSize <= 0 {
+		c.EventChannelBufferSize = defaultEventChannelBufferSize
+	}
+
+	// Ensure the DI factories are initialized for production use if `NewConfig` was called without options.
+	if c.interFlowDispatchPolicyFactory == nil {
+		c.interFlowDispatchPolicyFactory = inter.NewPolicyFromName
+	}
+	if c.intraFlowDispatchPolicyFactory == nil {
+		c.intraFlowDispatchPolicyFactory = intra.NewPolicyFromName
+	}
+	if c.queueFactory == nil {
+		c.queueFactory = queue.NewQueueFromName
+	}
+
 	if len(c.PriorityBands) == 0 {
 		return errors.New("config validation failed: at least one priority band must be defined")
 	}
 
-	priorities := make(map[uint]struct{}) // Keep track of seen priorities
+	// Validate and default each priority band.
+	priorities := make(map[uint]struct{})
+	priorityNames := make(map[string]struct{})
+	c.priorityBandMap = make(map[uint]*PriorityBandConfig, len(c.PriorityBands))
 
 	for i := range c.PriorityBands {
 		band := &c.PriorityBands[i]
@@ -100,29 +247,37 @@ func (c *Config) validateAndApplyDefaults() error {
 		priorities[band.Priority] = struct{}{}
 
 		if band.PriorityName == "" {
-			return errors.New("config validation failed: PriorityName is required for all priority bands")
+			return fmt.Errorf("config validation failed: PriorityName is required for priority band %d", band.Priority)
+		}
+		if _, exists := priorityNames[band.PriorityName]; exists {
+			return fmt.Errorf("config validation failed: duplicate priority name %q found", band.PriorityName)
 		}
+		priorityNames[band.PriorityName] = struct{}{}
+
 		if band.IntraFlowDispatchPolicy == "" {
-			band.IntraFlowDispatchPolicy = fcfs.FCFSPolicyName
+			band.IntraFlowDispatchPolicy = defaultIntraFlowDispatchPolicy
 		}
 		if band.InterFlowDispatchPolicy == "" {
-			band.InterFlowDispatchPolicy = besthead.BestHeadPolicyName
+			band.InterFlowDispatchPolicy = defaultInterFlowDispatchPolicy
 		}
 		if band.Queue == "" {
-			band.Queue = listqueue.ListQueueName
+			band.Queue = defaultQueue
+		}
+		if band.MaxBytes == 0 {
+			band.MaxBytes = defaultPriorityBandMaxBytes
 		}
 
-		// After defaulting, validate that the chosen plugins are compatible.
-		if err := validateBandCompatibility(*band); err != nil {
+		if err := c.validateBandCompatibility(*band); err != nil {
 			return err
 		}
+		c.priorityBandMap[band.Priority] = band
 	}
 	return nil
 }
 
-// validateBandCompatibility verifies that a band's default policy is compatible with its default queue type.
-func validateBandCompatibility(band PriorityBandConfig) error {
-	policy, err := intra.NewPolicyFromName(band.IntraFlowDispatchPolicy)
+// validateBandCompatibility verifies that a band's configured queue type has the necessary capabilities.
+func (c *Config) validateBandCompatibility(band PriorityBandConfig) error {
+	policy, err := c.intraFlowDispatchPolicyFactory(band.IntraFlowDispatchPolicy)
 	if err != nil {
 		return fmt.Errorf("failed to validate policy %q for priority band %d: %w",
 			band.IntraFlowDispatchPolicy, band.Priority, err)
@@ -130,23 +285,22 @@ func validateBandCompatibility(band PriorityBandConfig) error {
 
 	requiredCapabilities := policy.RequiredQueueCapabilities()
 	if len(requiredCapabilities) == 0 {
-		return nil // Policy has no specific requirements.
+		return nil // The policy is compatible with any queue type.
 	}
 
 	// Create a temporary queue instance to inspect its capabilities.
-	tempQueue, err := queue.NewQueueFromName(band.Queue, nil)
+	tempQueue, err := c.queueFactory(band.Queue, nil)
 	if err != nil {
-		return fmt.Errorf("failed to inspect queue type %q for priority band %d: %w", band.Queue, band.Priority, err)
+		return fmt.Errorf("failed to instantiate queue type %q for capability inspection (priority band %d): %w",
+			band.Queue, band.Priority, err)
 	}
 	queueCapabilities := tempQueue.Capabilities()
 
-	// Build a set of the queue's capabilities for efficient lookup.
 	capabilitySet := make(map[framework.QueueCapability]struct{}, len(queueCapabilities))
 	for _, cap := range queueCapabilities {
 		capabilitySet[cap] = struct{}{}
 	}
 
-	// Check if all required capabilities are present.
 	for _, req := range requiredCapabilities {
 		if _, ok := capabilitySet[req]; !ok {
 			return fmt.Errorf(
@@ -160,45 +314,151 @@ func validateBandCompatibility(band PriorityBandConfig) error {
 			)
 		}
 	}
-
 	return nil
 }
 
-// PriorityBandConfig defines the configuration for a single priority band within the `FlowRegistry`. It establishes the
-// default behaviors (such as queueing and dispatch policies) and capacity limits for all flows that operate at this
-// priority level.
-type PriorityBandConfig struct {
-	// Priority is the numerical priority level for this band.
-	// Convention: Lower numerical values indicate higher priority (e.g., 0 is highest).
-	//
-	// Required.
-	Priority uint
+// --- Partitioning Logic ---
 
-	// PriorityName is a human-readable name for this priority band (e.g., "Critical", "Standard", "Sheddable").
-	//
-	// Required.
-	PriorityName string
+// partition derives a `ShardConfig` from the master `Config` for a specific shard index.
+// It calculates the capacity distribution, ensuring that the total global capacity is distributed completely and
+// evenly.
+func (c *Config) partition(shardIndex, totalShards int) *ShardConfig {
+	shardCfg := &ShardConfig{
+		MaxBytes:        partitionUint64(c.MaxBytes, shardIndex, totalShards),
+		PriorityBands:   make([]ShardPriorityBandConfig, len(c.PriorityBands)),
+		priorityBandMap: make(map[uint]*ShardPriorityBandConfig, len(c.PriorityBands)),
+	}
 
-	// IntraFlowDispatchPolicy specifies the default name of the registered policy used to select a specific request to
-	// dispatch next from within a single flow's queue in this band. This default can be overridden on a per-flow basis.
-	//
-	// Optional: If empty, a system default (e.g., "FCFS") is used.
-	IntraFlowDispatchPolicy intra.RegisteredPolicyName
+	for i, template := range c.PriorityBands {
+		shardBandCfg := ShardPriorityBandConfig{
+			Priority:                template.Priority,
+			PriorityName:            template.PriorityName,
+			IntraFlowDispatchPolicy: template.IntraFlowDispatchPolicy,
+			InterFlowDispatchPolicy: template.InterFlowDispatchPolicy,
+			Queue:                   template.Queue,
+			MaxBytes:                partitionUint64(template.MaxBytes, shardIndex, totalShards),
+		}
+		shardCfg.PriorityBands[i] = shardBandCfg
 
-	// InterFlowDispatchPolicy specifies the name of the registered policy used to select which flow's queue to service
-	// next from this band.
-	//
-	// Optional: If empty, a system default (e.g., "BestHead") is used.
-	InterFlowDispatchPolicy inter.RegisteredPolicyName
+		// Crucial: We must take the address of the element within the new slice (`shardCfg.PriorityBands`) to ensure the
+		// map pointers are correct for the newly created ShardConfig instance.
+		shardCfg.priorityBandMap[shardBandCfg.Priority] = &shardCfg.PriorityBands[i]
+	}
+	return shardCfg
+}
 
-	// Queue specifies the default name of the registered SafeQueue implementation to be used for flow queues within this
-	// band.
-	//
-	// Optional: If empty, a system default (e.g., "ListQueue") is used.
-	Queue queue.RegisteredQueueName
+// partitionUint64 distributes a total uint64 value across a number of partitions.
+// It distributes the remainder of the division one by one to the first few partitions.
+func partitionUint64(total uint64, partitionIndex, totalPartitions int) uint64 {
+	if totalPartitions <= 0 {
+		panic(fmt.Sprintf("invariant violation: cannot partition into %d partitions", totalPartitions))
+	}
+	if total == 0 {
+		return 0
+	}
+	base := total / uint64(totalPartitions)
+	remainder := total % uint64(totalPartitions)
+	// Distribute the remainder. The first `remainder` partitions get one extra from the total.
+	// For example, if total=10 and partitions=3, base=3, remainder=1. Partition 0 gets 3+1=4, partitions 1 and 2 get 3.
+	if uint64(partitionIndex) < remainder {
+		base++
+	}
+	return base
+}
 
-	// MaxBytes defines the maximum total byte size for this specific priority band, aggregated across all shards.
-	//
-	// Optional: If not set, a system default (e.g., 1 GB) is applied.
-	MaxBytes uint64
+// --- Test-Only Dependency Injection ---
+
+// configOption is a function that applies a configuration change to a `Config` object.
+// This is used exclusively for dependency injection in tests and should not be used in production code.
+type configOption func(*Config)
+
+// interFlowDispatchPolicyFactory defines the signature for a function that creates an
+// `framework.InterFlowDispatchPolicy` instance from its registered name.
+// It serves as an abstraction over the concrete `inter.NewPolicyFromName` factory, enabling dependency injection for
+// testing validation logic.
+type interFlowDispatchPolicyFactory func(name inter.RegisteredPolicyName) (framework.InterFlowDispatchPolicy, error)
+
+// intraFlowDispatchPolicyFactory defines the signature for a function that creates an
+// `framework.IntraFlowDispatchPolicy` instance from its registered name.
+// It serves as an abstraction over the concrete `intra.NewPolicyFromName` factory, enabling dependency injection for
+// testing validation logic.
+type intraFlowDispatchPolicyFactory func(name intra.RegisteredPolicyName) (framework.IntraFlowDispatchPolicy, error)
+
+// queueFactory defines the signature for a function that creates a `framework.SafeQueue` instance from its registered
+// name and a given `framework.ItemComparator`.
+// It serves as an abstraction over the concrete `queue.NewQueueFromName` factory, enabling dependency injection for
+// testing validation logic.
+type queueFactory func(
+	name queue.RegisteredQueueName,
+	comparator framework.ItemComparator,
+) (framework.SafeQueue, error)
+
+// withInterFlowDispatchPolicyFactory returns a test-only `configOption` that overrides the factory function for
+// creating `framework.InterFlowDispatchPolicy` instances.
+// This is used exclusively for testing validation logic.
+// test-only
+func withInterFlowDispatchPolicyFactory(factory interFlowDispatchPolicyFactory) configOption {
+	return func(c *Config) {
+		c.interFlowDispatchPolicyFactory = factory
+	}
+}
+
+// withIntraFlowDispatchPolicyFactory returns a test-only `configOption` that overrides the factory function for
+// creating `framework.IntraFlowDispatchPolicy` instances.
+// This is used exclusively for testing validation logic.
+// test-only
+func withIntraFlowDispatchPolicyFactory(factory intraFlowDispatchPolicyFactory) configOption {
+	return func(c *Config) {
+		c.intraFlowDispatchPolicyFactory = factory
+	}
+}
+
+// withQueueFactory returns a test-only `configOption` that overrides the factory function for creating
+// `framework.SafeQueue` instances.
+// This is used exclusively for testing validation logic.
+// test-only
+func withQueueFactory(factory queueFactory) configOption {
+	return func(c *Config) {
+		c.queueFactory = factory
+	}
+}
+
+// --- Internal Utilities ---
+
+// deepCopy creates a deep copy of the `Config` object.
+func (c *Config) deepCopy() *Config {
+	if c == nil {
+		return nil
+	}
+	newCfg := &Config{
+		MaxBytes:                       c.MaxBytes,
+		InitialShardCount:              c.InitialShardCount,
+		FlowGCTimeout:                  c.FlowGCTimeout,
+		EventChannelBufferSize:         c.EventChannelBufferSize,
+		PriorityBands:                  make([]PriorityBandConfig, len(c.PriorityBands)),
+		priorityBandMap:                make(map[uint]*PriorityBandConfig, len(c.PriorityBands)),
+		interFlowDispatchPolicyFactory: c.interFlowDispatchPolicyFactory,
+		intraFlowDispatchPolicyFactory: c.intraFlowDispatchPolicyFactory,
+		queueFactory:                   c.queueFactory,
+	}
+
+	// PriorityBandConfig contains only value types, so a slice copy is sufficient for a deep copy.
+	copy(newCfg.PriorityBands, c.PriorityBands)
+
+	// Crucial: We must rebuild the map and take the address of the elements within the new slice (`newCfg.PriorityBands`)
+	// to ensure the map pointers are correct for the newly created `Config` instance.
+	for i := range newCfg.PriorityBands {
+		band := &newCfg.PriorityBands[i]
+		newCfg.priorityBandMap[band.Priority] = band
+	}
+	return newCfg
+}
+
+// getBandConfig finds and returns the global configuration template for a specific priority level.
+// Returns an error wrapping `contracts.ErrPriorityBandNotFound` if the priority is not configured.
+func (c *Config) getBandConfig(priority uint) (*PriorityBandConfig, error) {
+	if band, ok := c.priorityBandMap[priority]; ok {
+		return band, nil
+	}
+	return nil, fmt.Errorf("global config for priority %d not found: %w", priority, contracts.ErrPriorityBandNotFound)
 }
diff --git a/pkg/epp/flowcontrol/registry/doc.go b/pkg/epp/flowcontrol/registry/doc.go
index a038d3d..3355c77 100644
--- a/pkg/epp/flowcontrol/registry/doc.go
+++ b/pkg/epp/flowcontrol/registry/doc.go
@@ -14,27 +14,116 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-// Package registry provides the concrete implementation of the Flow Registry.
+// Package registry provides the concrete implementation of the `contracts.FlowRegistry`.
 //
-// As the stateful control plane for the entire Flow Control system, this package is responsible for managing the
-// lifecycle of all flows, queues, and policies. It serves as the "adapter" that implements the service "ports"
-// (interfaces) defined in the `contracts` package. It provides a sharded, concurrent-safe view of its state to the
-// `controller.FlowController` workers, enabling scalable, parallel request processing.
+// As the stateful control plane, this package manages the lifecycle of all flows, queues, and policies. It provides a
+// sharded, concurrent-safe view of its state to the `controller.FlowController` workers, enabling scalable, parallel
+// request processing.
 //
-// # Key Components
+// # Architecture: Composite, Sharded, and Separated Concerns
 //
-//   - `FlowRegistry`: The future top-level administrative object that will manage the entire system, including shard
-//     lifecycles and flow registration. (Not yet implemented).
+// The registry separates the control plane (orchestration) from the data plane (request processing state).
 //
-//   - `registryShard`: A concrete implementation of the `contracts.RegistryShard` interface. It represents a single,
-//     concurrent-safe slice of the registry's state, containing a set of priority bands and the flow queues within
-//     them. This is the primary object a `controller.FlowController` worker interacts with.
+//   - `FlowRegistry`: The Control Plane. The top-level orchestrator and single source of truth. It centralizes complex
+//     operations: flow registration, garbage collection (GC) coordination, and shard scaling.
 //
-//   - `managedQueue`: A concrete implementation of the `contracts.ManagedQueue` interface. It acts as a stateful
-//     decorator around a `framework.SafeQueue`, adding critical registry-level functionality such as atomic statistics
-//     tracking.
+//   - `registryShard`: The Data Plane Slice. A concurrent-safe "slice" of the registry's total state. It provides a
+//     read-optimized view for `FlowController` workers.
 //
-//   - `Config`: The top-level configuration object that defines the structure and default behaviors of the registry,
-//     including the definition of priority bands and default policy selections. This configuration is partitioned and
-//     distributed to each `registryShard`.
+//   - `managedQueue`: The Stateful Decorator. A wrapper around a `framework.SafeQueue`. It augments the queue with
+//     atomic statistics tracking and signaling state transitions to the control plane.
+//
+// # Data Flow and Interaction Model
+//
+// The data path (Enqueue/Dispatch) is optimized for minimal latency and maximum concurrency.
+//
+// Enqueue Path:
+//  1. The `FlowController`'s distributor selects an active `registryShard`.
+//  2. The distributor calls `shard.ManagedQueue(flowKey)` (acquires `RLock`).
+//  3. The distributor calls `managedQueue.Add(item)`.
+//  4. `managedQueue` atomically updates the queue and its stats and signals the control plane.
+//
+// Dispatch Path:
+//  1. A `FlowController` worker iterates over its assigned `registryShard`.
+//  2. The worker uses policies and accessors to select the next item (acquires `RLock`).
+//  3. The worker calls `managedQueue.Remove(handle)`.
+//  4. `managedQueue` atomically updates the queue and its stats and signals the control plane.
+//
+// # Concurrency Strategy: Multi-Tiered and Optimized
+//
+// The registry maximizes performance on the hot path while ensuring strict correctness for complex state transitions:
+//
+//   - Serialized Control Plane (Actor Model): The `FlowRegistry` uses a single background goroutine to process all
+//     state change events serially, eliminating race conditions in the control plane.
+//
+//   - Sharding (Data Plane Parallelism): State is partitioned across multiple `registryShard` instances, allowing the
+//     data path to scale linearly.
+//
+//   - Lock-Free Data Path (Atomics): Statistics aggregation (Shard/Registry level) uses lock-free atomics.
+//
+//   - Strict Consistency (Hybrid Locking): `managedQueue` uses a hybrid locking model (Mutex for writes, Atomics for
+//     reads) to guarantee strict consistency between queue contents and statistics, which is required for GC
+//     correctness.
+//
+// (See the `FlowRegistry` struct documentation for detailed locking rules).
+//
+// # Garbage Collection: The "Trust but Verify" Pattern
+//
+// The registry handles the race condition between asynchronous data path activity and synchronous GC. The control plane
+// maintains an eventually consistent cache (`flowState`).
+//
+// The registry uses a periodic, generational "Trust but Verify" pattern. It identifies candidate flows using the cache.
+// Before deletion, it performs a "Verify" step: it synchronously acquires write locks on ALL shards and queries the
+// ground truth (live queue counters). This provides strong consistency when needed.
+//
+// (See the `garbageCollectFlowLocked` function documentation for detailed steps).
+//
+// # Scalability Characteristics and Trade-offs
+//
+// The architecture prioritizes data path throughput and correctness, introducing specific trade-offs:
+//
+//   - Data Path Throughput (Excellent): Scales linearly with the number of shards and benefits from lock-free
+//     statistics updates.
+//
+//   - GC Latency Impact (Trade-off): The GC "Verify" step requires locking all shards (O(N)). This briefly pauses the
+//     data path. As the shard count (N) increases, this may impact P99 latency. This trade-off guarantees correctness.
+//
+//   - Control Plane Responsiveness during Scale-Up (Trade-off): Scaling up requires synchronizing all existing flows
+//     (M) onto the new shards (K). This O(M*K) operation occurs under the main control plane lock. If M is large, this
+//     operation may block the control plane.
+//
+// # Event-Driven State Machine and Lifecycle Scenarios
+//
+// The system relies on atomic state transitions to generate reliable, edge-triggered signals. These signals are sent
+// reliably; if the event channel is full, the sender blocks, applying necessary backpressure to ensure no events are
+// lost, preventing state divergence.
+//
+// The following scenarios detail how the registry handles lifecycle events:
+//
+// New Flow Registration: A new flow instance `F1` (`FlowKey{ID: "A", Priority: 10}`) is registered.
+//
+//  1. `managedQueue` instances are created for `F1` on all shards.
+//  2. The `flowState` cache marks `F1` as Idle. If it remains Idle, it will eventually be garbage collected.
+//
+// Flow Activity/Inactivity:
+//
+//  1. When the first request for `F1` is enqueued, the queue signals `BecameNonEmpty`. The control plane marks `F1`
+//     as Active, protecting it from GC.
+//  2. When the last request is dispatched globally, the queues signal `BecameEmpty`. The control plane updates the
+//     cache, and `F1` is now considered Idle by the GC scanner.
+//
+// "Changing" Flow Priority: Traffic for `ID: "A"` needs to shift from `Priority: 10` to `Priority: 20`.
+//
+//  1. The caller registers a new flow instance, `F2` (`FlowKey{ID: "A", Priority: 20}`).
+//  2. The system treats `F1` and `F2` as independent entities (Immutable `FlowKey` design).
+//  3. As `F1` becomes Idle, it is automatically garbage collected. This achieves the outcome gracefully without complex
+//     state migration logic.
+//
+// Shard Scaling:
+//
+//   - Scale-Up: New shards are created and marked Active. Existing flows are synchronized onto the new shards.
+//     Configuration is re-partitioned.
+//   - Scale-Down: Targeted shards transition to Draining (stop accepting new work). Configuration is re-partitioned
+//     across remaining active shards. When a Draining shard is empty, it signals `BecameDrained` and is removed by the
+//     control plane.
 package registry
diff --git a/pkg/epp/flowcontrol/registry/events.go b/pkg/epp/flowcontrol/registry/events.go
new file mode 100644
index 0000000..c76a38e
--- /dev/null
+++ b/pkg/epp/flowcontrol/registry/events.go
@@ -0,0 +1,127 @@
+/*
+Copyright 2025 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package registry
+
+import (
+	"fmt"
+
+	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/types"
+)
+
+// =============================================================================
+// Control Plane Events (Transport)
+// =============================================================================
+
+// event is a marker interface for internal state machine events processed by the `FlowRegistry`'s event loop.
+type event interface {
+	isEvent()
+}
+
+// queueStateChangedEvent is sent when a `managedQueue`'s state changes, carrying a `queueStateSignal`.
+type queueStateChangedEvent struct {
+	shardID string
+	key     types.FlowKey
+	signal  queueStateSignal
+}
+
+func (queueStateChangedEvent) isEvent() {}
+
+// shardStateChangedEvent is sent when a `registryShard`'s state changes, carrying a `shardStateSignal`.
+type shardStateChangedEvent struct {
+	shardID string
+	signal  shardStateSignal
+}
+
+func (shardStateChangedEvent) isEvent() {}
+
+// syncEvent is used exclusively for testing to synchronize test execution with the `FlowRegistry`'s event loop.
+// It allows tests to wait until all preceding events have been processed, eliminating the need for polling.
+// test-only
+type syncEvent struct {
+	// doneCh is used by the event loop to signal back to the sender that the sync event has been processed.
+	doneCh chan struct{}
+}
+
+func (syncEvent) isEvent() {}
+
+// =============================================================================
+// Control Plane Signals and Callbacks
+// =============================================================================
+
+// --- Queue Signals ---
+
+// queueStateSignal is an enum describing the edge-triggered state change events emitted by a `managedQueue`.
+type queueStateSignal int
+
+const (
+	// queueStateSignalBecameEmpty is sent when a queue transitions from non-empty to empty.
+	// Trigger: Len > 0 -> Len == 0. Used for inactivity GC tracking.
+	queueStateSignalBecameEmpty queueStateSignal = iota
+
+	// queueStateSignalBecameNonEmpty is sent when a queue transitions from empty to non-empty.
+	// Trigger: Len == 0 -> Len > 0. Used for inactivity GC tracking.
+	queueStateSignalBecameNonEmpty
+)
+
+func (s queueStateSignal) String() string {
+	switch s {
+	case queueStateSignalBecameEmpty:
+		return "QueueBecameEmpty"
+	case queueStateSignalBecameNonEmpty:
+		return "QueueBecameNonEmpty"
+	default:
+		return fmt.Sprintf("Unknown(%d)", s)
+	}
+}
+
+// signalQueueStateFunc defines the callback function that a `managedQueue` uses to signal lifecycle events.
+// Implementations should avoid blocking on internal locks or I/O. However, they are expected to block if the
+// `FlowRegistry`'s event channel is full; this behavior is required to apply backpressure and ensure reliable event
+// delivery for the GC system.
+type signalQueueStateFunc func(key types.FlowKey, signal queueStateSignal)
+
+// --- Shard Signals ---
+
+// shardStateSignal is an enum describing the edge-triggered state change events emitted by a `registryShard`.
+type shardStateSignal int
+
+const (
+	// shardStateSignalBecameDrained is sent when a Draining shard transitions to empty.
+	// Trigger: Transition from `componentStatusDraining` -> `componentStatusDrained`. Used for final GC of the shard.
+	shardStateSignalBecameDrained shardStateSignal = iota
+)
+
+func (s shardStateSignal) String() string {
+	switch s {
+	case shardStateSignalBecameDrained:
+		return "ShardBecameDrained"
+	default:
+		return fmt.Sprintf("Unknown(%d)", s)
+	}
+}
+
+// signalShardStateFunc defines the callback function that a `registryShard` uses to signal its own state changes.
+// Implementations should avoid blocking on internal locks or I/O. However, they are expected to block if the
+// `FlowRegistry`'s event channel is full (see `signalQueueStateFunc` for rationale).
+type signalShardStateFunc func(shardID string, signal shardStateSignal)
+
+// --- Statistics Propagation ---
+
+// propagateStatsDeltaFunc defines the callback function used to propagate statistics changes (deltas) up the hierarchy
+// (Queue -> Shard -> Registry).
+// Implementations MUST be non-blocking (relying on atomics).
+type propagateStatsDeltaFunc func(priority uint, lenDelta, byteSizeDelta int64)
diff --git a/pkg/epp/flowcontrol/registry/flowstate.go b/pkg/epp/flowcontrol/registry/flowstate.go
new file mode 100644
index 0000000..b515d8f
--- /dev/null
+++ b/pkg/epp/flowcontrol/registry/flowstate.go
@@ -0,0 +1,105 @@
+/*
+Copyright 2025 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package registry
+
+import (
+	"fmt"
+
+	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/types"
+)
+
+// flowState holds all tracking state for a single flow instance within the registry.
+//
+// # Role: The Eventually Consistent Cache for GC
+//
+// This structure is central to the GC logic. It acts as an eventually consistent, cached view of a flow's emptiness
+// status across all shards. It is updated asynchronously via events from the data path.
+//
+// # Concurrency and Consistency Model
+//
+// `flowState` is a passive, non-thread-safe data structure. Access to `flowState` is serialized by `FlowRegistry.mu`.
+//
+// Invariant: Because this state is eventually consistent, it must not be the sole source of truth for destructive
+// operations (like garbage collection). All destructive actions must first verify the live state of the system by
+// consulting the atomic counters on the `managedQueue` instances directly (the "Trust but Verify" pattern).
+type flowState struct {
+	// spec is the desired state of the flow instance, uniquely identified by its immutable `spec.Key`.
+	spec types.FlowSpecification
+	// emptyOnShards tracks the empty status of the flow's queue across all shards.
+	// The key is the shard ID.
+	emptyOnShards map[string]bool
+	// lastActiveGeneration tracks the GC generation number in which this flow was last observed to be Active.
+	// This is used by the periodic GC scanner to identify flows that have been Idle for at least one GC cycle.
+	lastActiveGeneration uint64
+}
+
+// newFlowState creates the initial state for a newly registered flow instance.
+// It initializes the state based on the current set of all shards.
+func newFlowState(spec types.FlowSpecification, allShards []*registryShard) *flowState {
+	s := &flowState{
+		spec:          spec,
+		emptyOnShards: make(map[string]bool, len(allShards)),
+		// A new flow starts at generation 0. This sentinel value indicates to the GC "Mark" phase that the flow is brand
+		// new and should be granted a grace period of one cycle.
+		lastActiveGeneration: gcGenerationNewFlow,
+	}
+	// A new flow instance starts with an empty queue on all shards.
+	for _, shard := range allShards {
+		s.emptyOnShards[shard.id] = true
+	}
+	return s
+}
+
+// update synchronizes the flow's specification. This is a forward-looking method for when non-key fields on the spec
+// become mutable (e.g., a per-flow policy override). It enforces the invariant that the `FlowKey` cannot change.
+func (s *flowState) update(newSpec types.FlowSpecification) {
+	if s.spec.Key != newSpec.Key {
+		// This should be impossible if the FlowRegistry's logic is correct, as flowStates are keyed by FlowKey.
+		panic(fmt.Sprintf("invariant violation: attempted to update flowState for key %v with a new key %v",
+			s.spec.Key, newSpec.Key))
+	}
+	s.spec = newSpec
+}
+
+// handleQueueSignal updates the flow's internal emptiness state based on a signal from one of its queues.
+func (s *flowState) handleQueueSignal(shardID string, signal queueStateSignal) {
+	switch signal {
+	case queueStateSignalBecameEmpty:
+		s.emptyOnShards[shardID] = true
+	case queueStateSignalBecameNonEmpty:
+		s.emptyOnShards[shardID] = false
+	}
+}
+
+// isIdle checks if the flow's queues are empty across the provided set of shards (active and draining).
+//
+// The `shards` parameter defines the scope of the check (the current ground truth). We only verify the state against
+// this list because the internal `emptyOnShards` map might contain stale entries for shards that have been garbage
+// collected by the registry but not yet purged from this specific `flowState`.
+func (s *flowState) isIdle(shards []*registryShard) bool {
+	for _, shard := range shards {
+		if !s.emptyOnShards[shard.id] {
+			return false
+		}
+	}
+	return true
+}
+
+// purgeShard removes a decommissioned shard's ID from the tracking map to prevent memory leaks.
+func (s *flowState) purgeShard(shardID string) {
+	delete(s.emptyOnShards, shardID)
+}
diff --git a/pkg/epp/flowcontrol/registry/lifecycle.go b/pkg/epp/flowcontrol/registry/lifecycle.go
new file mode 100644
index 0000000..8b5ba6e
--- /dev/null
+++ b/pkg/epp/flowcontrol/registry/lifecycle.go
@@ -0,0 +1,56 @@
+/*
+Copyright 2025 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package registry
+
+import (
+	"fmt"
+)
+
+// =============================================================================
+// Component Lifecycle State Machine
+// =============================================================================
+
+// componentStatus represents the lifecycle state of a `registryShard`.
+// It is manipulated using atomic operations (e.g., `atomic.Int32`) to ensure robust, atomic state transitions.
+type componentStatus int32
+
+const (
+	// componentStatusActive indicates the component is fully operational and accepting new work.
+	componentStatusActive componentStatus = iota
+
+	// componentStatusDraining indicates the component is shutting down. It is not accepting new work, but is still
+	// processing existing work.
+	componentStatusDraining
+
+	// componentStatusDrained indicates the component has finished draining and is empty.
+	// The transition into this state (from `Draining`) occurs exactly once via `CompareAndSwap` and triggers the
+	// `BecameDrained` signal. This acts as an atomic latch for GC.
+	componentStatusDrained
+)
+
+func (s componentStatus) String() string {
+	switch s {
+	case componentStatusActive:
+		return "Active"
+	case componentStatusDraining:
+		return "Draining"
+	case componentStatusDrained:
+		return "Drained"
+	default:
+		return fmt.Sprintf("Unknown(%d)", s)
+	}
+}
diff --git a/pkg/epp/flowcontrol/registry/managedqueue.go b/pkg/epp/flowcontrol/registry/managedqueue.go
index b52adb1..5d3a670 100644
--- a/pkg/epp/flowcontrol/registry/managedqueue.go
+++ b/pkg/epp/flowcontrol/registry/managedqueue.go
@@ -17,6 +17,8 @@ limitations under the License.
 package registry
 
 import (
+	"fmt"
+	"sync"
 	"sync/atomic"
 
 	"github.com/go-logr/logr"
@@ -27,67 +29,101 @@ import (
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/logging"
 )
 
-// parentStatsReconciler defines the callback function that a `managedQueue` uses to propagate its statistics changes up
-// to its parent `registryShard`.
-type parentStatsReconciler func(lenDelta, byteSizeDelta int64)
+// managedQueueCallbacks groups the callback functions that a `managedQueue` uses to communicate with its parent shard.
+type managedQueueCallbacks struct {
+	// propagateStatsDelta is called to propagate statistics changes (e.g., queue length, byte size) up to the parent.
+	propagateStatsDelta propagateStatsDeltaFunc
+	// signalQueueState is called to signal important lifecycle events, such as becoming empty, which are used by the
+	// garbage collector.
+	signalQueueState signalQueueStateFunc
+}
 
-// managedQueue implements `contracts.ManagedQueue`. It is a stateful decorator that wraps a `framework.SafeQueue`,
-// augmenting it with atomic statistics tracking. This allows the parent `registryShard` to aggregate statistics across
-// many queues without locks.
+// managedQueue implements `contracts.ManagedQueue`. It acts as a stateful decorator around a `framework.SafeQueue`.
+//
+// # Role: The Stateful Decorator
+//
+// Its primary responsibility is to augment a generic queue implementation with critical registry features: strictly
+// consistent statistics tracking and exactly-once, edge-triggered signaling of state changes (e.g., becoming empty) to
+// the control plane for garbage collection.
+//
+// # Concurrency Model: Hybrid Locking (Mutex + Atomics + `SafeQueue`)
+//
+// The `managedQueue` employs a hybrid locking strategy to guarantee strict consistency between the queue contents and
+// its statistics, while maintaining high performance.
+//
+//  1. Mutex-Protected Writes (`sync.Mutex`): A single mutex protects all mutating operations (Add, Remove, etc.).
+//     This ensures that the update to the underlying queue and the update to the internal counters occur as a single,
+//     atomic transaction. This strict consistency is required for GC correctness.
+//
+//  2. Synchronous Propagation and Ordering: The propagation of statistics deltas (both `Len` and `ByteSize`) occurs
+//     synchronously within this critical section. This strict ordering (`Add` propagation before `Remove` propagation
+//     for the same item) guarantees the non-negative invariant across the entire system (Shard/Registry aggregates).
+//
+//  3. Lock-Free Statistics Reads (Atomics): The counters use `atomic.Int64`. This allows high-frequency accessors
+//     (`Len()`, `ByteSize()`) to read the statistics without acquiring the Mutex.
+//
+//  4. Concurrent Reads (`SafeQueue`): Read operations (e.g., `PeekHead`/`PeekTail` used by policies) rely on the
+//     underlying `framework.SafeQueue`'s concurrency control and do not acquire the `managedQueue`'s write lock.
 //
-// # Statistical Integrity
+// # Statistical Integrity and Invariant Protection
 //
-// For performance, `managedQueue` maintains its own `len` and `byteSize` fields using atomic operations. This provides
-// O(1) access for the parent `registryShard`'s aggregated statistics without needing to lock the underlying queue.
+//  1. Exclusive Access: All mutations on the underlying `SafeQueue` MUST be performed exclusively through this wrapper.
 //
-// This design is predicated on two critical assumptions:
-//  1. Exclusive Access: All mutating operations on the underlying `framework.SafeQueue` MUST be performed exclusively
-//     through this `managedQueue` wrapper. Direct access to the underlying queue will cause statistical drift.
-//  2. In-Process Queue: The `framework.SafeQueue` implementation is an in-process data structure (e.g., a list or
-//     heap). Its state MUST NOT change through external mechanisms. For example, a queue implementation backed by a
-//     distributed cache like Redis with its own TTL-based eviction policy would violate this assumption and lead to
-//     state inconsistency, as items could be removed without notifying the `managedQueue`.
+//  2. Non-Autonomous State: The underlying queue implementation must not change state autonomously (e.g., no internal
+//     TTL eviction).
 //
-// This approach avoids the need for the `framework.SafeQueue` interface to return state deltas on each operation,
-// keeping its contract simpler.
+//  3. Read-Only Proxy: To prevent policy plugins from bypassing statistics tracking, the read-only view is provided via
+//     the `flowQueueAccessor` wrapper. This enforces the read-only contract at the type system level.
 type managedQueue struct {
-	// Note: There is no mutex here. Concurrency control is delegated to the underlying `framework.SafeQueue` and the
-	// atomic operations on the stats fields.
-	queue               framework.SafeQueue
-	dispatchPolicy      framework.IntraFlowDispatchPolicy
-	flowKey             types.FlowKey
-	byteSize            atomic.Uint64
-	len                 atomic.Uint64
-	reconcileShardStats parentStatsReconciler
-	logger              logr.Logger
+	// mu protects all mutating operations (writes) on the queue. It ensures that the underlying queue's state and the
+	// atomic counters are updated atomically. Read operations (like `Peek`) do not acquire this lock.
+	mu sync.Mutex
+
+	// queue is the underlying, concurrency-safe queue implementation that this `managedQueue` decorates.
+	queue framework.SafeQueue
+
+	// dispatchPolicy is the intra-flow policy used to select items from this specific queue.
+	dispatchPolicy framework.IntraFlowDispatchPolicy
+
+	// key uniquely identifies the flow instance this queue belongs to.
+	key types.FlowKey
+
+	// Queue-level statistics. Updated under the protection of the `mu` lock, but read lock-free.
+	// Guaranteed to be non-negative.
+	byteSize atomic.Int64
+	len      atomic.Int64
+
+	// parentCallbacks provides the communication channels back to the parent shard.
+	parentCallbacks managedQueueCallbacks
+	logger          logr.Logger
 }
 
+var _ contracts.ManagedQueue = &managedQueue{}
+
 // newManagedQueue creates a new instance of a `managedQueue`.
 func newManagedQueue(
 	queue framework.SafeQueue,
 	dispatchPolicy framework.IntraFlowDispatchPolicy,
-	flowKey types.FlowKey,
+	key types.FlowKey,
 	logger logr.Logger,
-	reconcileShardStats parentStatsReconciler,
+	parentCallbacks managedQueueCallbacks,
 ) *managedQueue {
 	mqLogger := logger.WithName("managed-queue").WithValues(
-		"flowKey", flowKey,
-		"flowID", flowKey.ID,
-		"priority", flowKey.Priority,
+		"flowKey", key,
 		"queueType", queue.Name(),
 	)
 	mq := &managedQueue{
-		queue:               queue,
-		dispatchPolicy:      dispatchPolicy,
-		flowKey:             flowKey,
-		reconcileShardStats: reconcileShardStats,
-		logger:              mqLogger,
+		queue:           queue,
+		dispatchPolicy:  dispatchPolicy,
+		key:             key,
+		parentCallbacks: parentCallbacks,
+		logger:          mqLogger,
 	}
 	return mq
 }
 
-// FlowQueueAccessor returns a new `flowQueueAccessor` instance, which provides a read-only, policy-facing view of the
-// queue.
+// FlowQueueAccessor returns a read-only, flow-aware view of this queue.
+// This accessor is primarily used by policy plugins to inspect the queue's state in a structured way.
 func (mq *managedQueue) FlowQueueAccessor() framework.FlowQueueAccessor {
 	return &flowQueueAccessor{mq: mq}
 }
@@ -95,10 +131,13 @@ func (mq *managedQueue) FlowQueueAccessor() framework.FlowQueueAccessor {
 // Add wraps the underlying `framework.SafeQueue.Add` call and atomically updates the queue's and the parent shard's
 // statistics.
 func (mq *managedQueue) Add(item types.QueueItemAccessor) error {
+	mq.mu.Lock()
+	defer mq.mu.Unlock()
+
 	if err := mq.queue.Add(item); err != nil {
 		return err
 	}
-	mq.reconcileStats(1, int64(item.OriginalRequest().ByteSize()))
+	mq.propagateStatsDelta(1, int64(item.OriginalRequest().ByteSize()))
 	mq.logger.V(logging.TRACE).Info("Request added to queue", "requestID", item.OriginalRequest().ID())
 	return nil
 }
@@ -106,11 +145,14 @@ func (mq *managedQueue) Add(item types.QueueItemAccessor) error {
 // Remove wraps the underlying `framework.SafeQueue.Remove` call and atomically updates statistics upon successful
 // removal.
 func (mq *managedQueue) Remove(handle types.QueueItemHandle) (types.QueueItemAccessor, error) {
+	mq.mu.Lock()
+	defer mq.mu.Unlock()
+
 	removedItem, err := mq.queue.Remove(handle)
 	if err != nil {
 		return nil, err
 	}
-	mq.reconcileStats(-1, -int64(removedItem.OriginalRequest().ByteSize()))
+	mq.propagateStatsDelta(-1, -int64(removedItem.OriginalRequest().ByteSize()))
 	mq.logger.V(logging.TRACE).Info("Request removed from queue", "requestID", removedItem.OriginalRequest().ID())
 	return removedItem, nil
 }
@@ -118,110 +160,114 @@ func (mq *managedQueue) Remove(handle types.QueueItemHandle) (types.QueueItemAcc
 // Cleanup wraps the underlying `framework.SafeQueue.Cleanup` call and atomically updates statistics for all removed
 // items.
 func (mq *managedQueue) Cleanup(predicate framework.PredicateFunc) (cleanedItems []types.QueueItemAccessor, err error) {
+	mq.mu.Lock()
+	defer mq.mu.Unlock()
+
 	cleanedItems, err = mq.queue.Cleanup(predicate)
-	if err != nil || len(cleanedItems) == 0 {
-		return cleanedItems, err
+	if err != nil {
+		return nil, err
 	}
-
-	var lenDelta int64
-	var byteSizeDelta int64
-	for _, item := range cleanedItems {
-		lenDelta--
-		byteSizeDelta -= int64(item.OriginalRequest().ByteSize())
+	if len(cleanedItems) == 0 {
+		return cleanedItems, nil
 	}
-	mq.reconcileStats(lenDelta, byteSizeDelta)
-	mq.logger.V(logging.DEBUG).Info("Cleaned up queue", "removedItemCount", len(cleanedItems),
-		"lenDelta", lenDelta, "byteSizeDelta", byteSizeDelta)
+	mq.propagateStatsDeltaForRemovedItems(cleanedItems)
+	mq.logger.V(logging.DEBUG).Info("Cleaned up queue", "removedItemCount", len(cleanedItems))
 	return cleanedItems, nil
 }
 
 // Drain wraps the underlying `framework.SafeQueue.Drain` call and atomically updates statistics for all removed items.
 func (mq *managedQueue) Drain() ([]types.QueueItemAccessor, error) {
+	mq.mu.Lock()
+	defer mq.mu.Unlock()
+
 	drainedItems, err := mq.queue.Drain()
-	if err != nil || len(drainedItems) == 0 {
-		return drainedItems, err
+	if err != nil {
+		return nil, err
 	}
-
-	var lenDelta int64
-	var byteSizeDelta int64
-	for _, item := range drainedItems {
-		lenDelta--
-		byteSizeDelta -= int64(item.OriginalRequest().ByteSize())
+	if len(drainedItems) == 0 {
+		return drainedItems, nil
 	}
-	mq.reconcileStats(lenDelta, byteSizeDelta)
-	mq.logger.V(logging.DEBUG).Info("Drained queue", "itemCount", len(drainedItems),
-		"lenDelta", lenDelta, "byteSizeDelta", byteSizeDelta)
+	mq.propagateStatsDeltaForRemovedItems(drainedItems)
+	mq.logger.V(logging.DEBUG).Info("Drained queue", "itemCount", len(drainedItems))
 	return drainedItems, nil
 }
 
-// reconcileStats atomically updates the queue's own statistics and calls the parent shard's reconciler to ensure
-// aggregated stats remain consistent.
-func (mq *managedQueue) reconcileStats(lenDelta, byteSizeDelta int64) {
-	// The use of Add with a negative number on a Uint64 is the standard Go atomic way to perform subtraction, leveraging
-	// two's complement arithmetic.
-	mq.len.Add(uint64(lenDelta))
-	mq.byteSize.Add(uint64(byteSizeDelta))
-	if mq.reconcileShardStats != nil {
-		mq.reconcileShardStats(lenDelta, byteSizeDelta)
-	}
-}
-
-// --- Pass-through and accessor methods ---
-
-// Name returns the name of the underlying queue implementation.
-func (mq *managedQueue) Name() string { return mq.queue.Name() }
-
-// Capabilities returns the capabilities of the underlying queue implementation.
-func (mq *managedQueue) Capabilities() []framework.QueueCapability { return mq.queue.Capabilities() }
+// --- Pass-through and Accessor Methods ---
 
-// Len returns the number of items in the queue.
-func (mq *managedQueue) Len() int { return int(mq.len.Load()) }
-
-// ByteSize returns the total byte size of all items in the queue.
-func (mq *managedQueue) ByteSize() uint64 { return mq.byteSize.Load() }
-
-// PeekHead returns the item at the front of the queue without removing it.
+func (mq *managedQueue) Name() string                               { return mq.queue.Name() }
+func (mq *managedQueue) Capabilities() []framework.QueueCapability  { return mq.queue.Capabilities() }
+func (mq *managedQueue) Len() int                                   { return int(mq.len.Load()) }
+func (mq *managedQueue) ByteSize() uint64                           { return uint64(mq.byteSize.Load()) }
 func (mq *managedQueue) PeekHead() (types.QueueItemAccessor, error) { return mq.queue.PeekHead() }
-
-// PeekTail returns the item at the back of the queue without removing it.
 func (mq *managedQueue) PeekTail() (types.QueueItemAccessor, error) { return mq.queue.PeekTail() }
+func (mq *managedQueue) Comparator() framework.ItemComparator       { return mq.dispatchPolicy.Comparator() }
 
-// Comparator returns the `framework.ItemComparator` that defines this queue's item ordering logic, as dictated by its
-// configured dispatch policy.
-func (mq *managedQueue) Comparator() framework.ItemComparator { return mq.dispatchPolicy.Comparator() }
+// --- Internal Methods ---
 
-var _ contracts.ManagedQueue = &managedQueue{}
-
-// --- flowQueueAccessor ---
+// propagateStatsDelta updates the queue's statistics, signals emptiness events, and propagates the delta.
+//
+// Invariant Check: This function panics if a statistic becomes negative. Because all updates are protected by the
+// `managedQueue.mu` lock, a negative value indicates a critical logic error (e.g., double-counting a removal).
+// This check enforces the non-negative invariant locally, which mathematically guarantees that the aggregated
+// statistics (Shard/Registry level) also remain non-negative.
+func (mq *managedQueue) propagateStatsDelta(lenDelta, byteSizeDelta int64) {
+	// Note: We rely on the caller (Add/Remove/etc.) to hold the `managedQueue.mu` lock.
+
+	newLen := mq.len.Add(lenDelta)
+	if newLen < 0 {
+		panic(fmt.Sprintf("invariant violation: managedQueue length for flow %s became negative (%d)", mq.key, newLen))
+	}
+	mq.byteSize.Add(byteSizeDelta)
+
+	// Evaluate and signal our own state change *before* propagating the statistics to the parent shard. This ensures a
+	// strict, bottom-up event ordering, preventing race conditions where the parent might process its own state change
+	// before the child's signal is handled.
+	// 1. Evaluate GC signals based on the strictly consistent local state.
+	// 2. Propagate the delta up to the Shard/Registry. This propagation is lock-free and eventually consistent.
+	mq.evaluateEmptinessState(newLen-lenDelta, newLen)
+	mq.parentCallbacks.propagateStatsDelta(mq.key.Priority, lenDelta, byteSizeDelta)
+}
 
-// flowQueueAccessor implements `framework.FlowQueueAccessor`. It provides a read-only, policy-facing view of a
-// `managedQueue`.
-type flowQueueAccessor struct {
-	mq *managedQueue
+// evaluateEmptinessState checks if the queue has transitioned between non-empty <-> empty and signals the parent if so.
+func (mq *managedQueue) evaluateEmptinessState(oldLen, newLen int64) {
+	if oldLen > 0 && newLen == 0 {
+		mq.parentCallbacks.signalQueueState(mq.key, queueStateSignalBecameEmpty)
+	} else if oldLen == 0 && newLen > 0 {
+		mq.parentCallbacks.signalQueueState(mq.key, queueStateSignalBecameNonEmpty)
+	}
 }
 
-// Name returns the name of the queue.
-func (a *flowQueueAccessor) Name() string { return a.mq.Name() }
+// propagateStatsDeltaForRemovedItems calculates the total stat changes for a slice of removed items and applies them.
+func (mq *managedQueue) propagateStatsDeltaForRemovedItems(items []types.QueueItemAccessor) {
+	var lenDelta int64
+	var byteSizeDelta int64
+	for _, item := range items {
+		lenDelta--
+		byteSizeDelta -= int64(item.OriginalRequest().ByteSize())
+	}
+	mq.propagateStatsDelta(lenDelta, byteSizeDelta)
+}
 
-// Capabilities returns the capabilities of the queue.
-func (a *flowQueueAccessor) Capabilities() []framework.QueueCapability { return a.mq.Capabilities() }
+// --- `flowQueueAccessor` ---
 
-// Len returns the number of items in the queue.
-func (a *flowQueueAccessor) Len() int { return a.mq.Len() }
+// flowQueueAccessor implements `framework.FlowQueueAccessor`. It provides a read-only, policy-facing view.
+//
+// # Role: The Read-Only Proxy
+//
+// This wrapper protects system invariants. It acts as a proxy that exposes only the read-only methods.
+// This prevents policy plugins from using type assertions to access the concrete `*managedQueue` and calling mutation
+// methods, which would bypass statistics tracking and signaling.
+type flowQueueAccessor struct {
+	mq *managedQueue
+}
 
-// ByteSize returns the total byte size of all items in the queue.
-func (a *flowQueueAccessor) ByteSize() uint64 { return a.mq.ByteSize() }
+var _ framework.FlowQueueAccessor = &flowQueueAccessor{}
 
-// PeekHead returns the item at the front of the queue without removing it.
+func (a *flowQueueAccessor) Name() string                               { return a.mq.Name() }
+func (a *flowQueueAccessor) Capabilities() []framework.QueueCapability  { return a.mq.Capabilities() }
+func (a *flowQueueAccessor) Len() int                                   { return a.mq.Len() }
+func (a *flowQueueAccessor) ByteSize() uint64                           { return a.mq.ByteSize() }
 func (a *flowQueueAccessor) PeekHead() (types.QueueItemAccessor, error) { return a.mq.PeekHead() }
-
-// PeekTail returns the item at the back of the queue without removing it.
 func (a *flowQueueAccessor) PeekTail() (types.QueueItemAccessor, error) { return a.mq.PeekTail() }
-
-// Comparator returns the `framework.ItemComparator` that defines this queue's item ordering logic.
-func (a *flowQueueAccessor) Comparator() framework.ItemComparator { return a.mq.Comparator() }
-
-// FlowKey returns the `types.FlowKey` of the flow this queue accessor is associated with.
-func (a *flowQueueAccessor) FlowKey() types.FlowKey { return a.mq.flowKey }
-
-var _ framework.FlowQueueAccessor = &flowQueueAccessor{}
+func (a *flowQueueAccessor) Comparator() framework.ItemComparator       { return a.mq.Comparator() }
+func (a *flowQueueAccessor) FlowKey() types.FlowKey                     { return a.mq.key }
diff --git a/pkg/epp/flowcontrol/registry/registry.go b/pkg/epp/flowcontrol/registry/registry.go
new file mode 100644
index 0000000..34ed8fc
--- /dev/null
+++ b/pkg/epp/flowcontrol/registry/registry.go
@@ -0,0 +1,746 @@
+/*
+Copyright 2025 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package registry
+
+import (
+	"context"
+	"fmt"
+	"sync"
+	"sync/atomic"
+
+	"github.com/go-logr/logr"
+	"k8s.io/utils/clock"
+	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/contracts"
+	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework"
+	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/types"
+	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/logging"
+)
+
+// bandStats holds the aggregated atomic statistics for a single priority band across all shards.
+type bandStats struct {
+	byteSize atomic.Int64
+	len      atomic.Int64
+}
+
+// FlowRegistry is the concrete implementation of the `contracts.FlowRegistry` interface.
+//
+// # Role: The Central Orchestrator
+//
+// The `FlowRegistry` is the single source of truth for all configuration and the lifecycle manager for all shards and
+// flow instances (identified by `types.FlowKey`). It is responsible for complex, multi-step operations such as flow
+// registration, dynamic shard scaling, and coordinating garbage collection across all shards.
+//
+// # Concurrency Model: The Serialized Control Plane (Actor Model)
+//
+// To ensure correctness during complex state transitions, the `FlowRegistry` employs an Actor-like pattern. All
+// administrative operations and internal state change events are serialized.
+//
+// A single background goroutine (the `Run` loop) processes events from the `events` channel and a periodic `gcTicker`.
+// This event loop acquires the main `mu` lock before processing any event. External administrative methods (like
+// `RegisterOrUpdateFlow`) also acquire this lock. This strict serialization eliminates race conditions in the control
+// plane, simplifying the complex logic of the distributed state machine.
+//
+// # Detailed Concurrency Strategy and Locking Rules
+//
+// The registry employs a multi-tiered concurrency strategy:
+//
+//  1. Serialized Control Plane (Actor Model): Implemented by the `Run` loop and the `mu` lock.
+//
+//  2. Coarse-Grained Admin Lock (`FlowRegistry.mu`): Protects the core control plane state.
+//
+//  3. Shard-Level R/W Lock (`registryShard.mu`): Protects a single shard's metadata.
+//
+//  4. Queue-Level Write Lock (`managedQueue.mu`): Each `managedQueue` uses a `sync.Mutex` to protect writes, ensuring
+//     strict consistency between queue contents and statistics (required for GC correctness).
+//
+//  5. Lock-Free Data Path (Atomics): Statistics aggregation (Shard/Registry level) uses lock-free atomics. Statistics
+//     reads at the queue level are also lock-free.
+//
+//  6. Strict Lock Hierarchy: To prevent deadlocks, a strict acquisition hierarchy is enforced:
+//     `FlowRegistry.mu` -> `registryShard.mu` -> `managedQueue.mu`
+//     If multiple locks are required, they MUST be acquired in this order.
+//
+//  7. Blocking Rules: Goroutines MUST NOT hold the `FlowRegistry.mu` lock while attempting to send to the `events`
+//     channel. Sends block if the channel is full. Blocking while holding the lock would deadlock the event loop.
+//     (e.g., use the `deferredActions` pattern).
+type FlowRegistry struct {
+	logger logr.Logger
+
+	// config holds the master configuration for the entire system. It is validated and defaulted at startup and used as
+	// the template for creating partitioned `ShardConfig`s.
+	config *Config
+
+	// clock provides the time abstraction for the registry and its components (like `gcTracker`).
+	clock clock.WithTickerAndDelayedExecution
+
+	// mu protects administrative operations and the internal state (shard lists, `flowState`s, etc.).
+	// Acquired by both external administrative methods and the internal event loop (`Run`), ensuring serialization.
+	mu sync.Mutex
+
+	// activeShards contains shards that are operational (Active).
+	// A slice is used to maintain a deterministic order, which is crucial for consistent configuration partitioning
+	// during scaling events.
+	activeShards []*registryShard
+
+	// drainingShards contains shards that are being gracefully shut down.
+	// A map is used for efficient O(1) removal of a shard by its ID when its draining process completes.
+	drainingShards map[string]*registryShard
+
+	// allShards is a cached, combined slice of active and draining shards.
+	// This cache is updated only when the set of shards changes, optimizing read-heavy operations that need to iterate
+	// over all shards.
+	allShards []*registryShard
+
+	// nextShardID is a monotonically increasing counter used to generate unique, stable IDs for shards throughout the
+	// lifetime of the process.
+	nextShardID uint64
+
+	// flowStates tracks the desired state and GC state of all flow instances, keyed by the immutable `types.FlowKey`.
+	flowStates map[types.FlowKey]*flowState
+
+	// gcTicker drives the periodic garbage collection cycle.
+	gcTicker clock.Ticker
+
+	// gcGeneration is a monotonically increasing counter for GC cycles, used for the "mark-and-sweep" algorithm.
+	gcGeneration uint64
+
+	// events is a channel for all internal state change events from shards and queues.
+	//
+	// Note: The GC system relies on exactly-once delivery of edge-triggered events; therefore, sends to this channel must
+	// not be dropped. If the buffer fills, the data path will block, applying necessary backpressure to the control
+	// plane.
+	events chan event
+
+	// Globally aggregated statistics. Updated atomically via lock-free propagation.
+	totalByteSize atomic.Int64
+	totalLen      atomic.Int64
+
+	// perPriorityBandStats stores *bandStats, keyed by priority (`uint`).
+	// The map structure is immutable after initialization; values are updated atomically.
+	perPriorityBandStats map[uint]*bandStats
+}
+
+var _ contracts.FlowRegistry = &FlowRegistry{}
+
+// RegistryOption allows configuring the `FlowRegistry` during initialization using functional options.
+type RegistryOption func(*FlowRegistry)
+
+// WithClock sets the clock abstraction used by the registry (primarily for GC timers).
+// This is essential for deterministic testing. If `clk` is nil, the option is ignored.
+func WithClock(clk clock.WithTickerAndDelayedExecution) RegistryOption {
+	return func(fr *FlowRegistry) {
+		if clk != nil {
+			fr.clock = clk
+		}
+	}
+}
+
+// NewFlowRegistry creates and initializes a new `FlowRegistry` instance.
+func NewFlowRegistry(config Config, logger logr.Logger, opts ...RegistryOption) (*FlowRegistry, error) {
+	validatedConfig, err := NewConfig(config)
+	if err != nil {
+		return nil, fmt.Errorf("master configuration is invalid: %w", err)
+	}
+
+	// Buffered channel to absorb bursts of events. See comment on the struct field for concurrency notes.
+	events := make(chan event, config.EventChannelBufferSize)
+
+	fr := &FlowRegistry{
+		config:               validatedConfig,
+		logger:               logger.WithName("flow-registry"),
+		flowStates:           make(map[types.FlowKey]*flowState),
+		events:               events,
+		activeShards:         []*registryShard{},
+		drainingShards:       make(map[string]*registryShard),
+		perPriorityBandStats: make(map[uint]*bandStats, len(validatedConfig.PriorityBands)),
+		// Initialize `generation` to 1. A generation value of 0 in `flowState` is reserved as a sentinel value to indicate a
+		// brand new flow that has not yet been processed by the GC loop.
+		gcGeneration: 1,
+	}
+
+	for _, opt := range opts {
+		opt(fr)
+	}
+
+	if fr.clock == nil {
+		fr.clock = &clock.RealClock{}
+	}
+
+	fr.gcTicker = fr.clock.NewTicker(fr.config.FlowGCTimeout)
+
+	for i := range config.PriorityBands {
+		band := &config.PriorityBands[i]
+		fr.perPriorityBandStats[band.Priority] = &bandStats{}
+	}
+
+	// `UpdateShardCount` handles the initial creation and populates `activeShards`.
+	if err := fr.UpdateShardCount(validatedConfig.InitialShardCount); err != nil {
+		fr.gcTicker.Stop()
+		return nil, fmt.Errorf("failed to initialize shards: %w", err)
+	}
+
+	fr.logger.V(logging.DEFAULT).Info("FlowRegistry initialized successfully")
+	return fr, nil
+}
+
+// Run starts the registry's background event processing loop. It blocks until the provided context is cancelled.
+// This loop implements the serialized control plane (Actor model), handling both asynchronous signals from data plane
+// components and periodic ticks for garbage collection.
+func (fr *FlowRegistry) Run(ctx context.Context) {
+	fr.logger.Info("Starting FlowRegistry event loop")
+	defer fr.logger.Info("FlowRegistry event loop stopped")
+	defer fr.gcTicker.Stop()
+
+	for {
+		select {
+		case <-ctx.Done():
+			return
+		case <-fr.gcTicker.C():
+			fr.mu.Lock()
+			fr.onGCTick()
+			fr.mu.Unlock()
+		case evt := <-fr.events:
+			fr.mu.Lock()
+			switch e := evt.(type) {
+			case *queueStateChangedEvent:
+				fr.onQueueStateChanged(e)
+			case *shardStateChangedEvent:
+				fr.onShardStateChanged(e)
+			case *syncEvent:
+				close(e.doneCh) // Signal synchronization point reached.
+			}
+			fr.mu.Unlock()
+		}
+	}
+}
+
+// RegisterOrUpdateFlow handles the registration of a new flow instance or the update of an existing instance's
+// specification (for the same `types.FlowKey`). It orchestrates the creation or update atomically across all managed
+// shards.
+func (fr *FlowRegistry) RegisterOrUpdateFlow(spec types.FlowSpecification) error {
+	if spec.Key.ID == "" {
+		return fmt.Errorf("invalid flow specification: %w", contracts.ErrFlowIDEmpty)
+	}
+
+	fr.mu.Lock()
+	defer fr.mu.Unlock()
+
+	totalShardCount := len(fr.activeShards) + len(fr.drainingShards)
+	components, err := fr.buildFlowComponents(spec, totalShardCount)
+	if err != nil {
+		return err
+	}
+
+	fr.applyFlowSynchronizationLocked(spec, components)
+	return nil
+}
+
+// UpdateShardCount dynamically adjusts the number of internal state shards.
+func (fr *FlowRegistry) UpdateShardCount(n int) error {
+	if n <= 0 {
+		return fmt.Errorf("%w: shard count must be a positive integer, but got %d", contracts.ErrInvalidShardCount, n)
+	}
+
+	fr.mu.Lock()
+	currentActiveShards := len(fr.activeShards)
+	if n == currentActiveShards {
+		fr.mu.Unlock()
+		return nil
+	}
+
+	// deferredActions holds functions to be executed after the lock is released. This pattern is used to cleanly separate
+	// state mutations (under lock) from side effects that might block (like sending to the `events` channel).
+	var deferredActions []func()
+
+	if n > currentActiveShards {
+		if err := fr.executeScaleUpLocked(n); err != nil {
+			fr.mu.Unlock()
+			return err
+		}
+	} else {
+		fr.executeScaleDownLocked(n, &deferredActions)
+	}
+	fr.mu.Unlock()
+
+	// Execute all deferred side effects outside the lock.
+	for _, action := range deferredActions {
+		action()
+	}
+	return nil
+}
+
+// Stats returns globally aggregated statistics for the entire `FlowRegistry`.
+//
+// Note on Concurrency and Consistency: Statistics are aggregated using high-performance, lock-free atomic updates.
+// The returned stats represent a near-consistent snapshot of the system's state. It is not perfectly atomic because the
+// various counters are loaded independently without a global lock.
+func (fr *FlowRegistry) Stats() contracts.AggregateStats {
+	// Casts from `int64` to `uint64` are safe because the non-negative invariant is strictly enforced at the
+	// `managedQueue` level.
+	stats := contracts.AggregateStats{
+		TotalCapacityBytes:   fr.config.MaxBytes,
+		TotalByteSize:        uint64(fr.totalByteSize.Load()),
+		TotalLen:             uint64(fr.totalLen.Load()),
+		PerPriorityBandStats: make(map[uint]contracts.PriorityBandStats, len(fr.config.PriorityBands)),
+	}
+
+	for p, s := range fr.perPriorityBandStats {
+		bandCfg, err := fr.config.getBandConfig(p)
+		if err != nil {
+			// The stats map was populated from the config, so the config must exist for this priority.
+			// This indicates severe state corruption.
+			panic(fmt.Sprintf("invariant violation: priority band config (%d) missing during stats aggregation: %v", p, err))
+		}
+		stats.PerPriorityBandStats[p] = contracts.PriorityBandStats{
+			Priority:      p,
+			PriorityName:  bandCfg.PriorityName,
+			CapacityBytes: bandCfg.MaxBytes,
+			ByteSize:      uint64(s.byteSize.Load()),
+			Len:           uint64(s.len.Load()),
+		}
+	}
+	return stats
+}
+
+// updateAllShardsCacheLocked recalculates and updates the cached `allShards` slice.
+// It must be called any time the `activeShards` or `drainingShards` collections are modified.
+// It expects the registry's lock to be held.
+func (fr *FlowRegistry) updateAllShardsCacheLocked() {
+	allShards := make([]*registryShard, 0, len(fr.activeShards)+len(fr.drainingShards))
+	allShards = append(allShards, fr.activeShards...)
+
+	// Note: Iteration over a map is non-deterministic. However, the order of Draining shards in the combined slice does
+	// not impact correctness. Active shards are always first and in a stable order.
+	for _, shard := range fr.drainingShards {
+		allShards = append(allShards, shard)
+	}
+	fr.allShards = allShards
+}
+
+// ShardStats returns a slice of statistics, one for each internal shard (Active and Draining).
+func (fr *FlowRegistry) ShardStats() []contracts.ShardStats {
+	// To minimize lock contention, we acquire the lock just long enough to get the combined list of shards.
+	// Iterating and gathering stats (which involves reading shard-level atomics/locks) is done outside the critical
+	// section.
+	fr.mu.Lock()
+	allShards := fr.allShards
+	fr.mu.Unlock()
+
+	shardStats := make([]contracts.ShardStats, len(allShards))
+	for i, s := range allShards {
+		shardStats[i] = s.Stats()
+	}
+	return shardStats
+}
+
+// Shards returns a slice of accessors for all internal shards (active and draining).
+// Active shards always precede draining shards in the returned slice.
+func (fr *FlowRegistry) Shards() []contracts.RegistryShard {
+	// Similar to `ShardStats`, minimize lock contention by getting the list under lock.
+	fr.mu.Lock()
+	allShards := fr.allShards
+	fr.mu.Unlock()
+
+	shardContracts := make([]contracts.RegistryShard, len(allShards))
+	for i, s := range allShards {
+		shardContracts[i] = s
+	}
+	return shardContracts
+}
+
+// --- Internal Methods ---
+
+// executeScaleUpLocked handles adding new shards using a "prepare-commit" pattern.
+//
+// First, in a "prepare" phase, all new shards are fully created and initialized in a temporary slice. This includes
+// all fallible work. If any part of this phase fails, the operation is aborted without modifying the `FlowRegistry`'s
+// state. If preparation succeeds, a "commit" phase atomically applies the changes to the registry.
+//
+// # Scalability Considerations
+//
+// The preparation phase synchronizes all existing flows onto the new shards. This requires O(M*K) operations
+// (M=flows, K=new shards) performed while holding the main control plane lock. If M is large, this operation will block
+// the control plane (including event processing) for a significant duration.
+//
+// Expects the registry's write lock to be held.
+func (fr *FlowRegistry) executeScaleUpLocked(newTotalActive int) error {
+	currentActive := len(fr.activeShards)
+	numToAdd := newTotalActive - currentActive
+
+	fr.logger.Info("Scaling up shards", "currentActive", currentActive, "newTotalActive", newTotalActive)
+
+	// --- Prepare Phase ---
+	// Create all new shards in a temporary slice. This phase is fallible and performs no mutations on the
+	// `FlowRegistry`'s state.
+	preparedShards := make([]*registryShard, numToAdd)
+	for i := range numToAdd {
+		shardID := fmt.Sprintf("shard-%d", fr.nextShardID+uint64(i))
+		shardIndex := currentActive + i
+		partitionedConfig := fr.config.partition(shardIndex, newTotalActive)
+
+		callbacks := shardCallbacks{
+			propagateStatsDelta: fr.propagateStatsDelta,
+			signalQueueState:    fr.handleQueueStateSignal,
+			signalShardState:    fr.handleShardStateSignal,
+		}
+		shard, err := newShard(shardID, partitionedConfig, fr.logger, callbacks, fr.config.interFlowDispatchPolicyFactory)
+		if err != nil {
+			return fmt.Errorf("failed to create new shard %s: %w", shardID, err)
+		}
+
+		// Synchronize all existing flows onto this newly created shard.
+		for _, state := range fr.flowStates {
+			components, err := fr.buildFlowComponents(state.spec, 1)
+			if err != nil {
+				// This is unlikely as the flow was already validated, but we handle it defensively.
+				return fmt.Errorf("failed to prepare synchronization for flow %s on new shard %s: %w",
+					state.spec.Key, shardID, err)
+			}
+			shard.synchronizeFlow(state.spec, components[0].policy, components[0].queue)
+		}
+		preparedShards[i] = shard
+	}
+
+	// --- Commit Phase ---
+	// Preparation succeeded. Atomically apply all changes to the registry's state.
+	// This phase must be infallible.
+	fr.activeShards = append(fr.activeShards, preparedShards...)
+
+	for _, shard := range preparedShards {
+		for _, state := range fr.flowStates {
+			state.emptyOnShards[shard.id] = true
+		}
+	}
+
+	fr.nextShardID += uint64(numToAdd)
+	fr.repartitionShardConfigsLocked()
+	fr.updateAllShardsCacheLocked()
+	return nil
+}
+
+// executeScaleDownLocked handles marking shards for graceful draining and re-partitioning.
+// It appends the necessary draining actions to the `deferredActions` slice. These actions MUST be executed by the
+// caller after the registry lock is released to prevent deadlocks.
+// It expects the registry's write lock to be held.
+func (fr *FlowRegistry) executeScaleDownLocked(newTotalActive int, deferredActions *[]func()) {
+	currentActive := len(fr.activeShards)
+	fr.logger.Info("Scaling down shards", "currentActive", currentActive, "newTotalActive", newTotalActive)
+
+	// Identify the shards to drain. These are the ones at the end of the Active list.
+	shardsToDrain := fr.activeShards[newTotalActive:]
+	fr.activeShards = fr.activeShards[:newTotalActive]
+	for _, shard := range shardsToDrain {
+		fr.drainingShards[shard.id] = shard
+	}
+
+	// Defer the `markAsDraining` calls, which may block if the `events` channel is full.
+	for _, shard := range shardsToDrain {
+		s := shard
+		*deferredActions = append(*deferredActions, func() {
+			s.markAsDraining()
+		})
+	}
+
+	fr.repartitionShardConfigsLocked()
+	fr.updateAllShardsCacheLocked()
+}
+
+// applyFlowSynchronizationLocked is the "commit" step of `RegisterOrUpdateFlow`.
+// It updates the central `flowState` and propagates the changes to all shards.
+// It expects the registry's write lock to be held.
+func (fr *FlowRegistry) applyFlowSynchronizationLocked(spec types.FlowSpecification, components []flowComponents) {
+	key := spec.Key
+	state, exists := fr.flowStates[key]
+	allShards := fr.allShards
+	if !exists {
+		// This is a new flow instance.
+		state = newFlowState(spec, allShards)
+		fr.flowStates[key] = state
+	} else {
+		// This is an update to an existing flow instance (e.g., policy change, when supported).
+		state.update(spec)
+	}
+
+	if len(allShards) != len(components) {
+		// This indicates a severe logic error during the prepare/commit phase synchronization (a race in
+		// `RegisterOrUpdateFlow`).
+		panic(fmt.Sprintf("invariant violation: shard/queue/policy count mismatch during commit for flow %s", spec.Key))
+	}
+
+	// Propagate the update to all shards (Active and Draining), giving each its own dedicated policy and queue instance.
+	for i, shard := range allShards {
+		shard.synchronizeFlow(spec, components[i].policy, components[i].queue)
+	}
+	fr.logger.Info("Successfully registered or updated flow instance", "flowKey", key)
+}
+
+// repartitionShardConfigsLocked updates the partitioned configuration for all active shards.
+// It expects the registry's write lock to be held.
+func (fr *FlowRegistry) repartitionShardConfigsLocked() {
+	numActive := len(fr.activeShards)
+	for i, shard := range fr.activeShards {
+		newPartitionedConfig := fr.config.partition(i, numActive)
+		shard.updateConfig(newPartitionedConfig)
+	}
+}
+
+// flowComponents holds the set of plugin instances created for a single shard.
+type flowComponents struct {
+	policy framework.IntraFlowDispatchPolicy
+	queue  framework.SafeQueue
+}
+
+// buildFlowComponents instantiates the necessary plugin components for a new flow instance.
+// It creates a distinct instance of each component for each shard to ensure state isolation.
+func (fr *FlowRegistry) buildFlowComponents(spec types.FlowSpecification, numInstances int) ([]flowComponents, error) {
+	priority := spec.Key.Priority
+	bandConfig, err := fr.config.getBandConfig(priority)
+	if err != nil {
+		return nil, fmt.Errorf("failed to get configuration for priority %d: %w", priority, err)
+	}
+
+	// TODO: When flow-level queue/policy overrides are implemented, check `spec` first.
+	policyName := bandConfig.IntraFlowDispatchPolicy
+	queueName := bandConfig.Queue
+	allComponents := make([]flowComponents, numInstances)
+
+	for i := range numInstances {
+		policy, err := fr.config.intraFlowDispatchPolicyFactory(policyName)
+		if err != nil {
+			return nil, fmt.Errorf("failed to instantiate intra-flow policy %s for flow %s: %w", policyName, spec.Key, err)
+		}
+
+		q, err := fr.config.queueFactory(queueName, policy.Comparator())
+		if err != nil {
+			return nil, fmt.Errorf("failed to instantiate queue %s for flow %s: %w", queueName, spec.Key, err)
+		}
+		allComponents[i] = flowComponents{policy: policy, queue: q}
+	}
+
+	return allComponents, nil
+}
+
+// garbageCollectFlowLocked orchestrates the "Trust but Verify" garbage collection of a
+// single flow instance. It implements the three steps of the pattern:
+// 1. Trust the eventually consistent cache.
+// 2. Verify the ground truth with a "stop-the-world" pause.
+// 3. Act to delete the flow if confirmed Idle.
+//
+// It acquires no locks itself but expects the caller to hold the main registry lock.
+func (fr *FlowRegistry) garbageCollectFlowLocked(key types.FlowKey) bool {
+	state, exists := fr.flowStates[key]
+	if !exists {
+		return false // Already deleted. Benign race.
+	}
+
+	if !state.isIdle(fr.allShards) {
+		return false
+	}
+
+	logger := fr.logger.WithValues("flowKey", key, "flowID", key.ID, "priority", key.Priority)
+	if !fr.verifyFlowIsTrulyIdleLocked(key, logger) {
+		return false
+	}
+
+	fr.deleteFlowLocked(key, logger)
+	return true
+}
+
+// verifyFlowIsTrulyIdleLocked performs the "stop-the-world" verification step of GC.
+// It acquires a write lock on ALL shards, briefly pausing the data path to get a strongly consistent view of all queue
+// lengths for a given flow.
+//
+// # Scalability Considerations
+//
+// This "Verify" step requires acquiring write locks on all shards (O(N)). As the shard count (N) increases, this pause
+// duration may grow, potentially impacting P99 latency. This trade-off is made explicitly to guarantee correctness and
+// prevent data loss.
+//
+// Returns true if the flow is confirmed to be empty everywhere, false otherwise.
+func (fr *FlowRegistry) verifyFlowIsTrulyIdleLocked(key types.FlowKey, logger logr.Logger) bool {
+	allShards := fr.allShards
+	for _, shard := range allShards {
+		shard.mu.Lock()
+	}
+	defer func() {
+		for _, shard := range allShards {
+			shard.mu.Unlock()
+		}
+	}()
+
+	for _, shard := range allShards {
+		mq, err := shard.managedQueueLocked(key)
+		if err != nil {
+			panic(fmt.Sprintf("invariant violation: managed queue for flow %s not found on shard %s during GC: %v",
+				key, shard.ID(), err))
+		}
+		if mq.Len() > 0 {
+			logger.V(logging.DEBUG).Info("GC aborted: Live check revealed flow instance is active", "shardID", shard.ID)
+			return false
+		}
+	}
+	return true
+}
+
+// deleteFlowLocked performs the destructive step of GC. It removes the flow's queues from all shards and deletes its
+// state from the central registry map.
+func (fr *FlowRegistry) deleteFlowLocked(key types.FlowKey, logger logr.Logger) {
+	logger.V(logging.VERBOSE).Info("Garbage collecting inactive flow instance")
+	for _, shard := range fr.allShards {
+		shard.garbageCollectLocked(key)
+	}
+	delete(fr.flowStates, key)
+	logger.V(logging.VERBOSE).Info("Successfully garbage collected flow instance")
+}
+
+// --- Event Handling (The Control Plane Loop) ---
+
+const gcGenerationNewFlow uint64 = 0
+
+// onGCTick implements the periodic "mark and sweep" garbage collection cycle.
+//
+// # Algorithm: Generational Mark-and-Sweep
+//
+// The GC uses a generational algorithm to ensure any idle flow survives for at least one full GC cycle before being
+// collected.
+//
+//  1. Mark: Any flow that is either actively serving requests OR is brand new (identified by a sentinel
+//     `lastActiveGeneration` value of `gcGenerationNewFlow`) is "marked" by updating its generation timestamp. This
+//     design choice keeps the `flowState` object decoupled from the GC engine's internal clock.
+//
+//  2. Sweep: Any flow that is Idle AND was last marked before the *previous* GC cycle is eligible for collection.
+//
+// It expects the registry's write lock to be held.
+func (fr *FlowRegistry) onGCTick() {
+	previousGeneration := fr.gcGeneration
+	currentGeneration := previousGeneration + 1
+	logger := fr.logger.WithValues("gcGeneration", currentGeneration)
+	logger.V(logging.DEBUG).Info("Starting periodic GC cycle")
+
+	// --- Mark Phase ---
+	// A flow is "marked" for survival by updating its `lastActiveGeneration`.
+	for _, state := range fr.flowStates {
+		if !state.isIdle(fr.allShards) {
+			// If a flow is currently Active, mark it with the current generation.
+			// This protects it from collection in the next cycle.
+			state.lastActiveGeneration = currentGeneration
+		} else if state.lastActiveGeneration == gcGenerationNewFlow {
+			// If a flow is new and Idle, mark it with the *previous* generation.
+			// This grants it a grace period for the *current* sweep, but correctly identifies it as a candidate for the
+			// *next* sweep if it remains Idle.
+			state.lastActiveGeneration = previousGeneration
+		}
+	}
+
+	// --- Sweep Phase ---
+	// A flow is a candidate for collection if it is Idle AND its `lastActiveGeneration` is from before the previous
+	// cycle.
+	var candidates []types.FlowKey
+	for key, state := range fr.flowStates {
+		if state.isIdle(fr.allShards) && state.lastActiveGeneration < previousGeneration {
+			candidates = append(candidates, key)
+		}
+	}
+
+	if len(candidates) > 0 {
+		logger.V(logging.DEBUG).Info("Found Idle flow instances for GC verification", "count", len(candidates))
+		for _, key := range candidates {
+			fr.garbageCollectFlowLocked(key)
+		}
+	}
+
+	// Finalize the cycle by updating the registry's generation.
+	fr.gcGeneration = currentGeneration
+}
+
+// onQueueStateChanged handles a state change signal from a `managedQueue`. It updates the control plane's cached view
+// of the flow's Idle state.
+func (fr *FlowRegistry) onQueueStateChanged(e *queueStateChangedEvent) {
+	fr.logger.V(logging.DEBUG).Info("Processing queue state signal",
+		"shardID", e.shardID,
+		"flowKey", e.key,
+		"flowID", e.key.ID,
+		"priority", e.key.Priority,
+		"signal", e.signal,
+	)
+
+	state, ok := fr.flowStates[e.key]
+	if !ok {
+		return // Flow was likely already garbage collected.
+	}
+	state.handleQueueSignal(e.shardID, e.signal)
+}
+
+// onShardStateChanged handles a state change signal from a `registryShard`.
+func (fr *FlowRegistry) onShardStateChanged(e *shardStateChangedEvent) {
+	if e.signal == shardStateSignalBecameDrained {
+		logger := fr.logger.WithValues("shardID", e.shardID, "signal", e.signal)
+		logger.Info("Draining shard is now empty, finalizing garbage collection")
+
+		if _, ok := fr.drainingShards[e.shardID]; !ok {
+			// A shard signaled Drained but wasn't in the Draining list (e.g., it was Active, or the signal was somehow
+			// processed twice despite the atomic latch).
+			// The system state is potentially corrupted.
+			panic(fmt.Sprintf("invariant violation: shard %s not found in draining map during GC", e.shardID))
+		}
+		delete(fr.drainingShards, e.shardID)
+
+		for _, flowState := range fr.flowStates {
+			flowState.purgeShard(e.shardID)
+		}
+		fr.updateAllShardsCacheLocked()
+	}
+}
+
+// --- Callbacks (Data Plane -> Control Plane Communication) ---
+
+// handleQueueStateSignal is the callback passed to shards to allow them to signal queue state changes.
+// It sends an event to the event channel for serialized processing by the control plane.
+func (fr *FlowRegistry) handleQueueStateSignal(shardID string, key types.FlowKey, signal queueStateSignal) {
+	// This must block if the channel is full. Dropping events would cause state divergence and memory leaks, as the GC
+	// system is edge-triggered. Blocking provides necessary backpressure from the data plane to the control plane.
+	fr.events <- &queueStateChangedEvent{
+		shardID: shardID,
+		key:     key,
+		signal:  signal,
+	}
+}
+
+// handleShardStateSignal is the callback passed to shards to allow them to signal their own state changes.
+func (fr *FlowRegistry) handleShardStateSignal(shardID string, signal shardStateSignal) {
+	// This must also block (see `handleQueueStateSignal`).
+	fr.events <- &shardStateChangedEvent{
+		shardID: shardID,
+		signal:  signal,
+	}
+}
+
+// propagateStatsDelta is the top-level, lock-free aggregator for all statistics changes from all shards.
+// It uses atomic operations to maintain high performance under concurrent updates from multiple shards.
+// As a result, its counters are eventually consistent and may be transiently inaccurate during high-contention races.
+func (fr *FlowRegistry) propagateStatsDelta(priority uint, lenDelta, byteSizeDelta int64) {
+	stats, ok := fr.perPriorityBandStats[priority]
+	if !ok {
+		// Stats are being propagated for a priority that wasn't initialized.
+		panic(fmt.Sprintf("invariant violation: priority band (%d) stats missing during propagation", priority))
+	}
+
+	stats.len.Add(lenDelta)
+	stats.byteSize.Add(byteSizeDelta)
+	fr.totalLen.Add(lenDelta)
+	fr.totalByteSize.Add(byteSizeDelta)
+}
diff --git a/pkg/epp/flowcontrol/registry/shard.go b/pkg/epp/flowcontrol/registry/shard.go
index eb11dc7..fd98462 100644
--- a/pkg/epp/flowcontrol/registry/shard.go
+++ b/pkg/epp/flowcontrol/registry/shard.go
@@ -26,35 +26,65 @@ import (
 
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/contracts"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework"
-	inter "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/plugins/policies/interflow/dispatch"
-	intra "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/plugins/policies/intraflow/dispatch"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/types"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/logging"
 )
 
-// registryShard implements the `contracts.RegistryShard` interface. It represents a single, concurrent-safe slice of
-// the `FlowRegistry`'s state, providing an operational view for a single `controller.FlowController` worker.
+// shardCallbacks groups the callback functions that a `registryShard` uses to communicate with its parent registry.
+type shardCallbacks struct {
+	propagateStatsDelta propagateStatsDeltaFunc
+	signalQueueState    func(shardID string, key types.FlowKey, signal queueStateSignal)
+	signalShardState    signalShardStateFunc
+}
+
+// priorityBand holds all the `managedQueues` and configuration for a single priority level within a shard.
+type priorityBand struct {
+	// config holds the partitioned config for this specific band within this shard.
+	config ShardPriorityBandConfig
+
+	// queues holds all `managedQueue` instances within this band, keyed by their logical `ID` string.
+	// The priority is implicit from the parent `priorityBand`.
+	queues map[string]*managedQueue
+
+	// Band-level statistics. Updated atomically via lock-free propagation.
+	byteSize atomic.Int64
+	len      atomic.Int64
+
+	// Cached policy instance for this band, created at initialization.
+	interFlowDispatchPolicy framework.InterFlowDispatchPolicy
+}
+
+// registryShard implements the `contracts.RegistryShard` interface.
+//
+// # Role: The Data Plane Slice
+//
+// It represents a single, concurrent-safe slice of the registry's total state. It provides a read-optimized view for a
+// `controller.FlowController` worker.
 //
-// # Responsibilities
+// # Concurrency: `RWMutex` and Atomics
 //
-//   - Holding the partitioned configuration and state (queues, policies) for its assigned shard.
-//   - Providing read-only access to its state for the `controller.FlowController`'s dispatch loop.
-//   - Aggregating statistics from its `managedQueue` instances.
+// The `registryShard` balances read performance with write safety:
 //
-// # Concurrency
+//   - `sync.RWMutex` (mu): Protects the shard's internal maps (`priorityBands`) during administrative operations.
 //
-// The `registryShard` uses a combination of an `RWMutex` and atomic operations to manage concurrency.
-//   - The `mu` RWMutex protects the shard's internal maps (`priorityBands`) during administrative
-//     operations like flow registration or updates. This ensures that the set of queues appears
-//     atomic to a `controller.FlowController` worker. All read-oriented methods on the shard take a read lock.
-//   - All statistics (`totalByteSize`, `totalLen`, etc.) are implemented as `atomic.Uint64` to allow for lock-free,
-//     high-performance updates from many concurrent queue operations.
+//   - Atomics (Stats): Aggregated statistics (`totalByteSize`, `totalLen`) use atomics for lock-free updates during
+//     delta propagation.
+//
+//   - Atomic Lifecycle (Status): The lifecycle state is managed via an atomic `status` enum.
 type registryShard struct {
-	id           string
-	logger       logr.Logger
-	config       *Config // Holds the *partitioned* config for this shard.
-	isActive     bool
-	reconcileFun parentStatsReconciler
+	id     string
+	logger logr.Logger
+
+	// config holds the partitioned configuration for this shard, derived from the `FlowRegistry`'s global `Config`.
+	// It contains only the settings and capacity limits relevant to this specific shard.
+	config *ShardConfig
+
+	// status tracks the lifecycle state of the shard (Active, Draining, Drained).
+	// It is stored as an `int32` for atomic operations.
+	status atomic.Int32 // `componentStatus`
+
+	// parentCallbacks provides the communication channels back to the parent registry.
+	parentCallbacks shardCallbacks
 
 	// mu protects the shard's internal maps (`priorityBands`).
 	mu sync.RWMutex
@@ -67,122 +97,66 @@ type registryShard struct {
 	// ensuring a deterministic, ordered traversal from highest to lowest priority.
 	orderedPriorityLevels []uint
 
-	// Shard-level statistics, which are updated atomically to ensure they are safe for concurrent access without locks.
-	totalByteSize atomic.Uint64
-	totalLen      atomic.Uint64
+	// Shard-level statistics. Updated atomically via lock-free propagation.
+	totalByteSize atomic.Int64
+	totalLen      atomic.Int64
 }
 
-// priorityBand holds all the `managedQueues` and configuration for a single priority level within a shard.
-type priorityBand struct {
-	// config holds the partitioned config for this specific band.
-	config PriorityBandConfig
-
-	// queues holds all `managedQueue` instances within this band, keyed by their composite `FlowKey`.
-	queues map[types.FlowKey]*managedQueue
-
-	// flowKeys is a cached slice of the keys from the `queues` map. This is an optimization to avoid repeated map key
-	// iteration in the `FlowKeys()` accessor method, making it an O(1) operation.
-	flowKeys []types.FlowKey
-
-	// Band-level statistics, which are updated atomically.
-	byteSize atomic.Uint64
-	len      atomic.Uint64
-
-	// Cached policy instances for this band, created at initialization.
-	interFlowDispatchPolicy        framework.InterFlowDispatchPolicy
-	defaultIntraFlowDispatchPolicy framework.IntraFlowDispatchPolicy
-}
+var _ contracts.RegistryShard = &registryShard{}
 
 // newShard creates a new `registryShard` instance from a partitioned configuration.
 func newShard(
 	id string,
-	partitionedConfig *Config,
+	config *ShardConfig,
 	logger logr.Logger,
-	reconcileFunc parentStatsReconciler,
+	parentCallbacks shardCallbacks,
+	interFlowFactory interFlowDispatchPolicyFactory,
 ) (*registryShard, error) {
 	shardLogger := logger.WithName("registry-shard").WithValues("shardID", id)
 	s := &registryShard{
-		id:            id,
-		logger:        shardLogger,
-		config:        partitionedConfig,
-		isActive:      true,
-		reconcileFun:  reconcileFunc,
-		priorityBands: make(map[uint]*priorityBand, len(partitionedConfig.PriorityBands)),
+		id:              id,
+		logger:          shardLogger,
+		config:          config,
+		parentCallbacks: parentCallbacks,
+		priorityBands:   make(map[uint]*priorityBand, len(config.PriorityBands)),
 	}
+	s.status.Store(int32(componentStatusActive))
 
-	for _, bandConfig := range partitionedConfig.PriorityBands {
-		interPolicy, err := inter.NewPolicyFromName(bandConfig.InterFlowDispatchPolicy)
+	for _, bandConfig := range config.PriorityBands {
+		interPolicy, err := interFlowFactory(bandConfig.InterFlowDispatchPolicy)
 		if err != nil {
 			return nil, fmt.Errorf("failed to create inter-flow policy %q for priority band %d: %w",
 				bandConfig.InterFlowDispatchPolicy, bandConfig.Priority, err)
 		}
 
-		intraPolicy, err := intra.NewPolicyFromName(bandConfig.IntraFlowDispatchPolicy)
-		if err != nil {
-			return nil, fmt.Errorf("failed to create intra-flow policy %q for priority band %d: %w",
-				bandConfig.IntraFlowDispatchPolicy, bandConfig.Priority, err)
-		}
-
 		s.priorityBands[bandConfig.Priority] = &priorityBand{
-			config:                         bandConfig,
-			queues:                         make(map[types.FlowKey]*managedQueue),
-			interFlowDispatchPolicy:        interPolicy,
-			defaultIntraFlowDispatchPolicy: intraPolicy,
+			config:                  bandConfig,
+			queues:                  make(map[string]*managedQueue),
+			interFlowDispatchPolicy: interPolicy,
 		}
 		s.orderedPriorityLevels = append(s.orderedPriorityLevels, bandConfig.Priority)
 	}
 
-	// Sort the priority levels to ensure deterministic iteration order.
 	slices.Sort(s.orderedPriorityLevels)
 	s.logger.V(logging.DEFAULT).Info("Registry shard initialized successfully",
 		"priorityBandCount", len(s.priorityBands), "orderedPriorities", s.orderedPriorityLevels)
 	return s, nil
 }
 
-// reconcileStats is the single point of entry for all statistics changes within the shard. It updates the relevant
-// band's stats, the shard's total stats, and propagates the delta to the parent registry.
-func (s *registryShard) reconcileStats(priority uint, lenDelta, byteSizeDelta int64) {
-	s.totalLen.Add(uint64(lenDelta))
-	s.totalByteSize.Add(uint64(byteSizeDelta))
-
-	if band, ok := s.priorityBands[priority]; ok {
-		band.len.Add(uint64(lenDelta))
-		band.byteSize.Add(uint64(byteSizeDelta))
-	}
-
-	s.logger.V(logging.TRACE).Info("Reconciled shard stats", "priority", priority,
-		"lenDelta", lenDelta, "byteSizeDelta", byteSizeDelta)
-
-	if s.reconcileFun != nil {
-		s.reconcileFun(lenDelta, byteSizeDelta)
-	}
-}
-
 // ID returns the unique identifier for this shard.
 func (s *registryShard) ID() string { return s.id }
 
 // IsActive returns true if the shard is active and accepting new requests.
+// This is used by the `controller.FlowController` to determine if it should use this shard for new enqueue operations.
 func (s *registryShard) IsActive() bool {
-	s.mu.RLock()
-	defer s.mu.RUnlock()
-	return s.isActive
+	return componentStatus(s.status.Load()) == componentStatusActive
 }
 
-// ManagedQueue retrieves a specific `ManagedQueue` instance from this shard.
+// ManagedQueue retrieves a specific `contracts.ManagedQueue` instance from this shard.
 func (s *registryShard) ManagedQueue(key types.FlowKey) (contracts.ManagedQueue, error) {
 	s.mu.RLock()
 	defer s.mu.RUnlock()
-
-	band, ok := s.priorityBands[key.Priority]
-	if !ok {
-		return nil, fmt.Errorf("failed to get managed queue for flow %q: %w", key, contracts.ErrPriorityBandNotFound)
-	}
-	mq, ok := band.queues[key]
-	if !ok {
-		return nil, fmt.Errorf("failed to get managed queue for flow %q: %w",
-			key, contracts.ErrFlowInstanceNotFound)
-	}
-	return mq, nil
+	return s.managedQueueLocked(key)
 }
 
 // IntraFlowDispatchPolicy retrieves a flow's configured `framework.IntraFlowDispatchPolicy`.
@@ -194,20 +168,17 @@ func (s *registryShard) IntraFlowDispatchPolicy(key types.FlowKey) (framework.In
 	if !ok {
 		return nil, fmt.Errorf("failed to get intra-flow policy for flow %q: %w", key, contracts.ErrPriorityBandNotFound)
 	}
-	mq, ok := band.queues[key]
+	mq, ok := band.queues[key.ID]
 	if !ok {
-		return nil, fmt.Errorf("failed to get intra-flow policy for flow %q: %w",
-			key, contracts.ErrFlowInstanceNotFound)
+		return nil, fmt.Errorf("failed to get intra-flow policy for flow %q: %w", key, contracts.ErrFlowInstanceNotFound)
 	}
-	// The policy is stored on the managed queue.
+	// The policy is stored on the `managedQueue`.
 	return mq.dispatchPolicy, nil
 }
 
 // InterFlowDispatchPolicy retrieves a priority band's configured `framework.InterFlowDispatchPolicy`.
+// This read is lock-free as the policy instance is immutable after the shard is initialized.
 func (s *registryShard) InterFlowDispatchPolicy(priority uint) (framework.InterFlowDispatchPolicy, error) {
-	s.mu.RLock()
-	defer s.mu.RUnlock()
-
 	band, ok := s.priorityBands[priority]
 	if !ok {
 		return nil, fmt.Errorf("failed to get inter-flow policy for priority %d: %w",
@@ -216,7 +187,7 @@ func (s *registryShard) InterFlowDispatchPolicy(priority uint) (framework.InterF
 	return band.interFlowDispatchPolicy, nil
 }
 
-// PriorityBandAccessor retrieves a read-only accessor for a given priority level.
+// PriorityBandAccessor retrieves a read-only view for a given priority level.
 func (s *registryShard) PriorityBandAccessor(priority uint) (framework.PriorityBandAccessor, error) {
 	s.mu.RLock()
 	defer s.mu.RUnlock()
@@ -229,22 +200,29 @@ func (s *registryShard) PriorityBandAccessor(priority uint) (framework.PriorityB
 	return &priorityBandAccessor{shard: s, band: band}, nil
 }
 
-// AllOrderedPriorityLevels returns all configured priority levels for this shard, sorted from highest to lowest
-// priority (ascending numerical order).
+// AllOrderedPriorityLevels returns a cached, sorted slice of all configured priority levels for this shard.
+// The slice is sorted from highest to lowest priority (ascending numerical order).
 func (s *registryShard) AllOrderedPriorityLevels() []uint {
-	// This is cached and read-only, so no lock is needed.
 	return s.orderedPriorityLevels
 }
 
-// Stats returns a snapshot of the statistics for this specific shard.
+// Stats returns a snapshot of the aggregated statistics for this specific shard.
+//
+// Note on Concurrency and Consistency: Statistics are aggregated using high-performance, lock-free atomic updates
+// propagated from the underlying `managedQueue` instances. The returned stats represent a near-consistent snapshot of
+// the shard's state. It is not perfectly atomic because the various counters are loaded independently without a global
+// lock.
 func (s *registryShard) Stats() contracts.ShardStats {
+	// Acquire `RLock` only to ensure the config/map structure isn't changing during iteration.
 	s.mu.RLock()
 	defer s.mu.RUnlock()
 
+	// Casts from `int64` to `uint64` are safe because the non-negative invariant is strictly enforced at the
+	// `managedQueue` level.
 	stats := contracts.ShardStats{
 		TotalCapacityBytes:   s.config.MaxBytes,
-		TotalByteSize:        s.totalByteSize.Load(),
-		TotalLen:             s.totalLen.Load(),
+		TotalByteSize:        uint64(s.totalByteSize.Load()),
+		TotalLen:             uint64(s.totalLen.Load()),
 		PerPriorityBandStats: make(map[uint]contracts.PriorityBandStats, len(s.priorityBands)),
 	}
 
@@ -252,17 +230,156 @@ func (s *registryShard) Stats() contracts.ShardStats {
 		stats.PerPriorityBandStats[priority] = contracts.PriorityBandStats{
 			Priority:      priority,
 			PriorityName:  band.config.PriorityName,
-			CapacityBytes: band.config.MaxBytes, // This is the partitioned capacity
-			ByteSize:      band.byteSize.Load(),
-			Len:           band.len.Load(),
+			CapacityBytes: band.config.MaxBytes, // This is the partitioned capacity.
+			ByteSize:      uint64(band.byteSize.Load()),
+			Len:           uint64(band.len.Load()),
 		}
 	}
 	return stats
 }
 
-var _ contracts.RegistryShard = &registryShard{}
+//  --- Internal Administrative/Lifecycle Methods (called by `FlowRegistry`) ---
+
+// synchronizeFlow is the internal administrative method for creating a flow instance on this shard.
+// Since a flow instance (identified by its immutable `FlowKey`) cannot be updated yet, this function is a simple
+// "create if not exists" operation. It is idempotent.
+func (s *registryShard) synchronizeFlow(
+	spec types.FlowSpecification,
+	policy framework.IntraFlowDispatchPolicy,
+	q framework.SafeQueue,
+) {
+	s.mu.Lock()
+	defer s.mu.Unlock()
+
+	key := spec.Key
+
+	// Find the correct priority band. A missing band is an invariant violation, as the `FlowRegistry` should have already
+	// validated this.
+	band, ok := s.priorityBands[key.Priority]
+	if !ok {
+		panic(fmt.Sprintf("invariant violation: attempt to synchronize flow on non-existent priority band %d", key.Priority))
+	}
+
+	if _, ok := band.queues[key.ID]; ok {
+		return
+	}
 
-// --- priorityBandAccessor ---
+	s.logger.V(logging.TRACE).Info("Creating new queue for flow instance.",
+		"flowKey", key, "queueType", q.Name())
+
+	callbacks := managedQueueCallbacks{
+		propagateStatsDelta: s.propagateStatsDelta,
+		signalQueueState: func(key types.FlowKey, signal queueStateSignal) {
+			s.parentCallbacks.signalQueueState(s.id, key, signal)
+		},
+	}
+	mq := newManagedQueue(q, policy, spec.Key, s.logger, callbacks)
+	band.queues[key.ID] = mq
+}
+
+// garbageCollectLocked removes a queue instance from the shard.
+// This must be called under the shard's write lock.
+func (s *registryShard) garbageCollectLocked(key types.FlowKey) {
+	s.logger.Info("Garbage collecting queue instance.", "flowKey", key, "flowID", key.ID, "priority", key.Priority)
+	if band, ok := s.priorityBands[key.Priority]; ok {
+		delete(band.queues, key.ID)
+	}
+}
+
+// markAsDraining transitions the shard to a Draining state. This method is lock-free.
+func (s *registryShard) markAsDraining() {
+	// Attempt to transition from Active to Draining atomically.
+	if s.status.CompareAndSwap(int32(componentStatusActive), int32(componentStatusDraining)) {
+		s.logger.V(logging.DEBUG).Info("Shard status changed",
+			"from", componentStatusActive,
+			"to", componentStatusDraining,
+		)
+	}
+
+	// Check if the shard is *already* empty when marked as draining. If so, immediately attempt the transition to
+	// Drained to ensure timely GC. This handles the race where the shard becomes empty just before or during being
+	// marked Draining.
+	if s.totalLen.Load() == 0 {
+		// Attempt to transition from Draining to Drained atomically.
+		if s.status.CompareAndSwap(int32(componentStatusDraining), int32(componentStatusDrained)) {
+			s.parentCallbacks.signalShardState(s.id, shardStateSignalBecameDrained)
+		}
+	}
+}
+
+// managedQueueLocked retrieves a specific `contracts.ManagedQueue` instance from this shard.
+// This must be called under the shard's read lock.
+func (s *registryShard) managedQueueLocked(key types.FlowKey) (*managedQueue, error) {
+	band, ok := s.priorityBands[key.Priority]
+	if !ok {
+		return nil, fmt.Errorf("failed to get managed queue for flow %q: %w", key, contracts.ErrPriorityBandNotFound)
+	}
+	mq, ok := band.queues[key.ID]
+	if !ok {
+		return nil, fmt.Errorf("failed to get managed queue for flow %q: %w", key, contracts.ErrFlowInstanceNotFound)
+	}
+	return mq, nil
+}
+
+// updateConfig atomically replaces the shard's configuration. This is used during scaling events to re-partition
+// capacity allocations.
+func (s *registryShard) updateConfig(newConfig *ShardConfig) {
+	s.mu.Lock()
+	defer s.mu.Unlock()
+
+	s.config = newConfig
+	// Update the partitioned config for each priority band as well.
+	for priority, band := range s.priorityBands {
+		newBandConfig, err := newConfig.getBandConfig(priority)
+		if err != nil {
+			// An invariant was violated: a priority exists in the shard but not in the new config.
+			// This should be impossible if the registry's logic is correct.
+			panic(fmt.Errorf("invariant violation: priority band (%d) missing in new shard configuration during update: %w",
+				priority, err))
+		}
+		band.config = *newBandConfig
+	}
+	s.logger.Info("Shard configuration updated")
+}
+
+// --- Internal Callback Methods ---
+
+// propagateStatsDelta is the single point of entry for all statistics changes within the shard.
+// It updates the relevant band's stats, the shard's total stats, and handles the shard's lifecycle signaling before
+// propagating the delta to the parent registry.
+// It uses atomic operations to maintain high performance under concurrent updates from multiple shards.
+// As a result, its counters are eventually consistent and may be transiently inaccurate during high-contention races.
+func (s *registryShard) propagateStatsDelta(priority uint, lenDelta, byteSizeDelta int64) {
+	band, ok := s.priorityBands[priority]
+	if !ok {
+		// This should be impossible if the `managedQueue` calling this is correctly registered.
+		panic(fmt.Sprintf("invariant violation on shard %s: received stats propagation for unknown priority band (%d)",
+			s.id, priority))
+	}
+
+	band.len.Add(lenDelta)
+	band.byteSize.Add(byteSizeDelta)
+	newTotalLen := s.totalLen.Add(lenDelta)
+	s.totalByteSize.Add(byteSizeDelta)
+
+	// Following the strict bottom-up signaling pattern, we evaluate and signal our own state change *before* propagating
+	// the statistics to the parent registry.
+	s.evaluateDrainingState(newTotalLen)
+	s.parentCallbacks.propagateStatsDelta(priority, lenDelta, byteSizeDelta)
+}
+
+// evaluateDrainingState checks if the shard has transitioned to the Drained state and signals the parent.
+func (s *registryShard) evaluateDrainingState(currentLen int64) {
+	if currentLen == 0 {
+		// Attempt transition from Draining to Drained atomically.
+		// This acts as the exactly-once latch. If it succeeds, this goroutine is solely responsible for signaling.
+		if s.status.CompareAndSwap(int32(componentStatusDraining), int32(componentStatusDrained)) {
+			s.parentCallbacks.signalShardState(s.id, shardStateSignalBecameDrained)
+		}
+	}
+}
+
+// --- `priorityBandAccessor` ---
 
 // priorityBandAccessor implements `framework.PriorityBandAccessor`. It provides a read-only, concurrent-safe view of a
 // single priority band within a shard.
@@ -271,30 +388,39 @@ type priorityBandAccessor struct {
 	band  *priorityBand
 }
 
+var _ framework.PriorityBandAccessor = &priorityBandAccessor{}
+
 // Priority returns the numerical priority level of this band.
-func (a *priorityBandAccessor) Priority() uint {
-	return a.band.config.Priority
-}
+func (a *priorityBandAccessor) Priority() uint { return a.band.config.Priority }
 
 // PriorityName returns the human-readable name of this priority band.
-func (a *priorityBandAccessor) PriorityName() string {
-	return a.band.config.PriorityName
-}
+func (a *priorityBandAccessor) PriorityName() string { return a.band.config.PriorityName }
 
 // FlowKeys returns a slice of all flow keys within this priority band.
-// This is an O(1) operation because the slice is pre-computed and cached.
+//
+// To minimize lock contention, this implementation first snapshots the flow IDs under a read lock and then constructs
+// the final slice of `types.FlowKey` structs outside of the lock.
 func (a *priorityBandAccessor) FlowKeys() []types.FlowKey {
 	a.shard.mu.RLock()
-	defer a.shard.mu.RUnlock()
-	return a.band.flowKeys
+	ids := make([]string, 0, len(a.band.queues))
+	for id := range a.band.queues {
+		ids = append(ids, id)
+	}
+	a.shard.mu.RUnlock()
+
+	flowKeys := make([]types.FlowKey, len(ids))
+	for i, id := range ids {
+		flowKeys[i] = types.FlowKey{ID: id, Priority: a.Priority()}
+	}
+	return flowKeys
 }
 
-// Queue returns a `framework.FlowQueueAccessor` for the specified `ID` within this priority band.
+// Queue returns a `framework.FlowQueueAccessor` for the specified logical `ID` within this priority band.
 func (a *priorityBandAccessor) Queue(id string) framework.FlowQueueAccessor {
 	a.shard.mu.RLock()
 	defer a.shard.mu.RUnlock()
 
-	mq, ok := a.band.queues[types.FlowKey{ID: id, Priority: a.Priority()}]
+	mq, ok := a.band.queues[id]
 	if !ok {
 		return nil
 	}
@@ -302,18 +428,21 @@ func (a *priorityBandAccessor) Queue(id string) framework.FlowQueueAccessor {
 }
 
 // IterateQueues executes the given `callback` for each `framework.FlowQueueAccessor` in this priority band.
-// The callback is executed under the shard's read lock, so it should be efficient and non-blocking.
-// If the callback returns false, iteration stops.
+//
+// To minimize lock contention, this implementation snapshots the queue accessors under a read lock and then executes
+// the callback on the snapshot, outside of the lock. This ensures that a potentially slow policy (the callback) does
+// not block other operations on the shard.
 func (a *priorityBandAccessor) IterateQueues(callback func(queue framework.FlowQueueAccessor) bool) {
 	a.shard.mu.RLock()
-	defer a.shard.mu.RUnlock()
+	accessors := make([]framework.FlowQueueAccessor, 0, len(a.band.queues))
+	for _, mq := range a.band.queues {
+		accessors = append(accessors, mq.FlowQueueAccessor())
+	}
+	a.shard.mu.RUnlock()
 
-	for _, key := range a.band.flowKeys {
-		mq := a.band.queues[key]
-		if !callback(mq.FlowQueueAccessor()) {
+	for _, accessor := range accessors {
+		if !callback(accessor) {
 			return
 		}
 	}
 }
-
-var _ framework.PriorityBandAccessor = &priorityBandAccessor{}
diff --git a/pkg/epp/flowcontrol/types/errors.go b/pkg/epp/flowcontrol/types/errors.go
index 4da47c1..f7dffbd 100644
--- a/pkg/epp/flowcontrol/types/errors.go
+++ b/pkg/epp/flowcontrol/types/errors.go
@@ -46,9 +46,6 @@ var (
 	// ErrNilRequest indicates that a nil `types.FlowControlRequest` was provided.
 	ErrNilRequest = errors.New("FlowControlRequest cannot be nil")
 
-	// ErrFlowIDEmpty indicates that a flow ID was empty when one was required.
-	ErrFlowIDEmpty = errors.New("flow ID cannot be empty")
-
 	// ErrQueueAtCapacity indicates that a request could not be enqueued because queue capacity limits were met.
 	ErrQueueAtCapacity = errors.New("queue at capacity and displacement failed to make space")
 )
diff --git a/pkg/epp/flowcontrol/types/flow.go b/pkg/epp/flowcontrol/types/flow.go
index 0d8a1b8..71017c1 100644
--- a/pkg/epp/flowcontrol/types/flow.go
+++ b/pkg/epp/flowcontrol/types/flow.go
@@ -17,7 +17,7 @@ limitations under the License.
 package types
 
 import (
-	"fmt"
+	"strconv"
 	"strings"
 )
 
@@ -44,23 +44,23 @@ type FlowKey struct {
 	Priority uint
 }
 
+func (k FlowKey) String() string {
+	return k.ID + ":" + strconv.FormatUint(uint64(k.Priority), 10)
+}
+
 // Compare provides a stable comparison function for two FlowKey instances, suitable for use with sorting algorithms.
 // It returns -1 if the key is less than the other, 0 if they are equal, and 1 if the key is greater than the other.
-// The comparison is performed first by Priority (descending) and then by ID (ascending).
+// The comparison is performed first by `Priority` (ascending, higher priority first) and then by `ID` (ascending).
 func (k FlowKey) Compare(other FlowKey) int {
-	if k.Priority > other.Priority {
+	if k.Priority < other.Priority { // Lower number means higher priority
 		return -1
 	}
-	if k.Priority < other.Priority {
+	if k.Priority > other.Priority {
 		return 1
 	}
 	return strings.Compare(k.ID, other.ID)
 }
 
-func (k FlowKey) String() string {
-	return fmt.Sprintf("%s::%d", k.ID, k.Priority)
-}
-
 // FlowSpecification defines the complete configuration for a single logical flow instance, which is uniquely identified
 // by its immutable `Key`.
 //
diff --git a/pkg/epp/requestcontrol/director.go b/pkg/epp/requestcontrol/director.go
index 1435c01..5330dd2 100644
--- a/pkg/epp/requestcontrol/director.go
+++ b/pkg/epp/requestcontrol/director.go
@@ -29,10 +29,10 @@ import (
 
 	"sigs.k8s.io/controller-runtime/pkg/log"
 
+	v1 "sigs.k8s.io/gateway-api-inference-extension/api/v1"
 	"sigs.k8s.io/gateway-api-inference-extension/apix/v1alpha2"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend"
 	backendmetrics "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend/metrics"
-	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/datastore"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/handlers"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/metadata"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/metrics"
@@ -42,6 +42,13 @@ import (
 	requtil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/request"
 )
 
+// Datastore defines the interface required by the Director.
+type Datastore interface {
+	PoolGet() (*v1.InferencePool, error)
+	ObjectiveGet(modelName string) *v1alpha2.InferenceObjective
+	PodList(predicate func(backendmetrics.PodMetrics) bool) []backendmetrics.PodMetrics
+}
+
 // Scheduler defines the interface required by the Director for scheduling.
 type Scheduler interface {
 	Schedule(ctx context.Context, request *schedulingtypes.LLMRequest, candidatePods []schedulingtypes.Pod) (result *schedulingtypes.SchedulingResult, err error)
@@ -49,23 +56,24 @@ type Scheduler interface {
 
 // SaturationDetector provides a signal indicating whether the backends are considered saturated.
 type SaturationDetector interface {
-	IsSaturated(ctx context.Context) bool
+	IsSaturated(ctx context.Context, candidatePods []backendmetrics.PodMetrics) bool
 }
 
 // NewDirectorWithConfig creates a new Director instance with all dependencies.
-func NewDirectorWithConfig(datastore datastore.Datastore, scheduler Scheduler, saturationDetector SaturationDetector, config *Config) *Director {
+func NewDirectorWithConfig(datastore Datastore, scheduler Scheduler, saturationDetector SaturationDetector, config *Config) *Director {
 	return &Director{
 		datastore:           datastore,
 		scheduler:           scheduler,
 		saturationDetector:  saturationDetector,
 		preRequestPlugins:   config.preRequestPlugins,
 		postResponsePlugins: config.postResponsePlugins,
+		defaultPriority:     0, // define default priority explicitly
 	}
 }
 
 // Director orchestrates the request handling flow, including scheduling.
 type Director struct {
-	datastore           datastore.Datastore
+	datastore           Datastore
 	scheduler           Scheduler
 	saturationDetector  SaturationDetector
 	preRequestPlugins   []PreRequest
@@ -76,17 +84,12 @@ type Director struct {
 	defaultPriority int
 }
 
-// HandleRequest orchestrates the request lifecycle:
-//  1. Parses request details.
-//  2. Calls admitRequest for admission control.
-//  3. Calls Scheduler.Schedule if request is approved.
-//  4. Calls prepareRequest to populate RequestContext with result and call PreRequest plugins.
-//
+// HandleRequest orchestrates the request lifecycle.
 // It always returns the requestContext even in the error case, as the request context is used in error handling.
 func (d *Director) HandleRequest(ctx context.Context, reqCtx *handlers.RequestContext) (*handlers.RequestContext, error) {
 	logger := log.FromContext(ctx)
 
-	// --- 1. Parse Request, Resolve Target Models, and Determine Parameters ---
+	// Parse Request, Resolve Target Models, and Determine Parameters
 	requestBodyMap := reqCtx.Request.Body
 	var ok bool
 	reqCtx.IncomingModelName, ok = requestBodyMap["model"].(string)
@@ -130,22 +133,23 @@ func (d *Director) HandleRequest(ctx context.Context, reqCtx *handlers.RequestCo
 	ctx = log.IntoContext(ctx, logger)
 	logger.V(logutil.DEBUG).Info("LLM request assembled")
 
-	// --- 2. Admission Control check --
-	if err := d.admitRequest(ctx, *infObjective.Spec.Priority, reqCtx.FairnessID); err != nil {
-		return reqCtx, err
-	}
-
-	// --- 3. Call Scheduler (with the relevant candidate pods) ---
+	// Get candidate pods for scheduling
 	candidatePods := d.getCandidatePodsForScheduling(ctx, reqCtx.Request.Metadata)
 	if len(candidatePods) == 0 {
 		return reqCtx, errutil.Error{Code: errutil.ServiceUnavailable, Msg: "failed to find candidate pods for serving the request"}
 	}
-	result, err := d.scheduler.Schedule(ctx, reqCtx.SchedulingRequest, candidatePods)
+
+	// Admission Control check
+	if err := d.admitRequest(ctx, candidatePods, *infObjective.Spec.Priority, reqCtx.FairnessID); err != nil {
+		return reqCtx, err
+	}
+
+	result, err := d.scheduler.Schedule(ctx, reqCtx.SchedulingRequest, d.toSchedulerPodMetrics(candidatePods))
 	if err != nil {
 		return reqCtx, errutil.Error{Code: errutil.InferencePoolResourceExhausted, Msg: fmt.Errorf("failed to find target pod: %w", err).Error()}
 	}
 
-	// --- 4. Prepare Request (Populates RequestContext and call PreRequest plugins) ---
+	// Prepare Request (Populates RequestContext and call PreRequest plugins)
 	// Insert target endpoint to instruct Envoy to route requests to the specified target pod and attach the port number.
 	// Invoke PreRequest registered plugins.
 	reqCtx, err = d.prepareRequest(ctx, reqCtx, result)
@@ -156,52 +160,27 @@ func (d *Director) HandleRequest(ctx context.Context, reqCtx *handlers.RequestCo
 	return reqCtx, nil
 }
 
-// admitRequest handles admission control to decide whether or not to accept the request
-// based on the request priority and system saturation state.
-func (d *Director) admitRequest(ctx context.Context, requestPriority int, fairnessID string) error {
-	logger := log.FromContext(ctx)
-
-	logger.V(logutil.TRACE).Info("Entering Flow Control", "priority", requestPriority, "fairnessID", fairnessID)
-
-	// This will be removed in favor of a more robust implementation (Flow Control) in the very near future.
-	// TODO: Make this a configurable value.
-	// Tracking issue https://github.com/kubernetes-sigs/gateway-api-inference-extension/issues/1347
-	if requestPriority >= 0 {
-		logger.V(logutil.TRACE).Info("Non-sheddable request bypassing saturation check.")
-		return nil
-	}
-
-	if d.saturationDetector.IsSaturated(ctx) { // Assuming non-nil Saturation Detector
-		return errutil.Error{
-			Code: errutil.InferencePoolResourceExhausted,
-			Msg:  "system saturated, sheddable request dropped",
-		}
-	}
-
-	return nil
-}
-
 // getCandidatePodsForScheduling gets the list of relevant endpoints for the scheduling cycle from the datastore.
 // according to EPP protocol, if "x-gateway-destination-endpoint-subset" is set on the request metadata and specifies
 // a subset of endpoints, only these endpoints will be considered as candidates for the scheduler.
 // Snapshot pod metrics from the datastore to:
 // 1. Reduce concurrent access to the datastore.
 // 2. Ensure consistent data during the scheduling operation of a request between all scheduling cycles.
-func (d *Director) getCandidatePodsForScheduling(ctx context.Context, requestMetadata map[string]any) []schedulingtypes.Pod {
+func (d *Director) getCandidatePodsForScheduling(ctx context.Context, requestMetadata map[string]any) []backendmetrics.PodMetrics {
 	loggerTrace := log.FromContext(ctx).V(logutil.TRACE)
 
 	subsetMap, found := requestMetadata[metadata.SubsetFilterNamespace].(map[string]any)
 	if !found {
-		return d.toSchedulerPodMetrics(d.datastore.PodList(backendmetrics.AllPodsPredicate))
+		return d.datastore.PodList(backendmetrics.AllPodsPredicate)
 	}
 
 	// Check if endpoint key is present in the subset map and ensure there is at least one value
 	endpointSubsetList, found := subsetMap[metadata.SubsetFilterKey].([]any)
 	if !found {
-		return d.toSchedulerPodMetrics(d.datastore.PodList(backendmetrics.AllPodsPredicate))
+		return d.datastore.PodList(backendmetrics.AllPodsPredicate)
 	} else if len(endpointSubsetList) == 0 {
 		loggerTrace.Info("found empty subset filter in request metadata, filtering all pods")
-		return []schedulingtypes.Pod{}
+		return []backendmetrics.PodMetrics{}
 	}
 
 	// Create a map of endpoint addresses for easy lookup
@@ -214,7 +193,7 @@ func (d *Director) getCandidatePodsForScheduling(ctx context.Context, requestMet
 	}
 
 	podTotalCount := 0
-	podFitleredList := d.datastore.PodList(func(pm backendmetrics.PodMetrics) bool {
+	podFilteredList := d.datastore.PodList(func(pm backendmetrics.PodMetrics) bool {
 		podTotalCount++
 		if _, found := endpoints[pm.GetPod().Address]; found {
 			return true
@@ -222,9 +201,34 @@ func (d *Director) getCandidatePodsForScheduling(ctx context.Context, requestMet
 		return false
 	})
 
-	loggerTrace.Info("filtered candidate pods by subset filtering", "podTotalCount", podTotalCount, "filteredCount", len(podFitleredList))
+	loggerTrace.Info("filtered candidate pods by subset filtering", "podTotalCount", podTotalCount, "filteredCount", len(podFilteredList))
+
+	return podFilteredList
+}
+
+// admitRequest handles admission control to decide whether or not to accept the request
+// based on the request priority and saturation state.
+func (d *Director) admitRequest(ctx context.Context, candidatePods []backendmetrics.PodMetrics, requestPriority int, fairnessID string) error {
+	loggerTrace := log.FromContext(ctx).V(logutil.TRACE)
+
+	loggerTrace.Info("Entering Flow Control", "priority", requestPriority, "fairnessID", fairnessID)
+
+	// This will be removed in favor of a more robust implementation (Flow Control) in the very near future.
+	// TODO: Make this a configurable value.
+	// Tracking issue https://github.com/kubernetes-sigs/gateway-api-inference-extension/issues/1347
+	if requestPriority >= 0 {
+		loggerTrace.Info("Non-sheddable request bypassing saturation check.")
+		return nil
+	}
+
+	if d.saturationDetector.IsSaturated(ctx, candidatePods) {
+		return errutil.Error{
+			Code: errutil.InferencePoolResourceExhausted,
+			Msg:  "system saturated, sheddable request dropped",
+		}
+	}
 
-	return d.toSchedulerPodMetrics(podFitleredList)
+	return nil
 }
 
 // prepareRequest populates the RequestContext and calls the registered PreRequest plugins
diff --git a/pkg/epp/saturationdetector/saturationdetector.go b/pkg/epp/saturationdetector/saturationdetector.go
index bc47ecd..46b94b2 100644
--- a/pkg/epp/saturationdetector/saturationdetector.go
+++ b/pkg/epp/saturationdetector/saturationdetector.go
@@ -17,11 +17,10 @@ limitations under the License.
 // Package saturationdetector implements a mechanism to determine if the
 // backend model servers are considered saturated based on observed metrics.
 //
-// The current implementation provides a global saturation signal (IsSaturated)
+// The current implementation provides a saturation signal (IsSaturated)
 // primarily based on backend queue depths and KV cache utilization, reflecting
 // the saturation signals previously used by the Scheduler before the
-// introduction of the FlowController. It fetches live metrics from the
-// provided Datastore.
+// introduction of the FlowController.
 //
 // TODO: Explore more advanced saturation signals in the future, such as:
 //   - Latency-objective-based saturation.
@@ -61,39 +60,21 @@ type Config struct {
 	MetricsStalenessThreshold time.Duration
 }
 
-// Datastore provides an interface to access backend pod metrics.
-type Datastore interface {
-	PodList(predicate func(backendmetrics.PodMetrics) bool) []backendmetrics.PodMetrics
-}
-
-// Detector determines system saturation based on metrics from the Datastore.
-//
-// The Detector currently holds a direct dependency on a Datastore interface.
-// This design choice was made to encapsulate the logic of fetching and
-// interpreting metrics for saturation, thereby simplifying the dependencies
-// for primary consumers like the FlowController--to be added soon--(which
-// would otherwise need to manage Datastore interactions itself).
-// This architectural decision may be revisited in the future if a more
-// decoupled approach (e.g., passing metrics directly to IsSaturated) proves
-// more beneficial.
+// Detector determines system saturation based on metrics of the given candidate pods.
 type Detector struct {
-	datastore Datastore
-	config    *Config
+	config *Config
 }
 
 // NewDetector creates a new SaturationDetector.
-// The datastore is expected to provide access to live/recently-updated pod
-// metrics.
 // The config provides the thresholds for determining saturation.
-func NewDetector(config *Config, datastore Datastore, logger logr.Logger) *Detector {
+func NewDetector(config *Config, logger logr.Logger) *Detector {
 	logger.WithName(loggerName).V(logutil.DEFAULT).Info("Creating new SaturationDetector",
 		"queueDepthThreshold", config.QueueDepthThreshold,
 		"kvCacheUtilThreshold", config.KVCacheUtilThreshold,
 		"metricsStalenessThreshold", config.MetricsStalenessThreshold.String())
 
 	return &Detector{
-		datastore: datastore,
-		config:    config,
+		config: config,
 	}
 }
 
@@ -104,20 +85,10 @@ func NewDetector(config *Config, datastore Datastore, logger logr.Logger) *Detec
 //  2. WaitingQueueSize <= QueueDepthThreshold.
 //  3. KVCacheUsagePercent <= KVCacheUtilThreshold.
 //
-// If no pods are found in the datastore, the system is considered saturated
-// (no capacity).
-func (d *Detector) IsSaturated(ctx context.Context) bool {
-	logger := log.FromContext(ctx).WithName(loggerName)
-	// TODO: filter out stale metrics here if needed.
-	allPodsMetrics := d.datastore.PodList(backendmetrics.AllPodsPredicate)
-	if len(allPodsMetrics) == 0 {
-		logger.V(logutil.VERBOSE).Info("No pods found in datastore; system is considered SATURATED (no capacity).")
-		// If there are no pods, there is no capacity to serve requests.
-		// Treat this as a saturated state to enable FlowController queuing.
-		return true
-	}
-
-	for _, podMetric := range allPodsMetrics {
+// This function is called with the relevant pods for the current request.
+func (d *Detector) IsSaturated(ctx context.Context, candidatePods []backendmetrics.PodMetrics) bool {
+	logger := log.FromContext(ctx)
+	for _, podMetric := range candidatePods {
 		metrics := podMetric.GetMetrics()
 		podNn := "unknown-pod"
 		if podMetric.GetPod() != nil {
diff --git a/pkg/epp/scheduling/framework/plugins/multi/prefix/plugin.go b/pkg/epp/scheduling/framework/plugins/multi/prefix/plugin.go
index 6cb7a3a..8c7b52c 100644
--- a/pkg/epp/scheduling/framework/plugins/multi/prefix/plugin.go
+++ b/pkg/epp/scheduling/framework/plugins/multi/prefix/plugin.go
@@ -263,8 +263,16 @@ func hashPrompt(ctx context.Context, request *types.LLMRequest, cacheBlockSize i
 	// If the last block is smaller than cacheBlockSize, it will be ignored.
 	res := make([]BlockHash, 0, 1+len(prompt)/cacheBlockSize)
 	// Add the model to the first block hash so that different models have different hashes even with the same body.
-	res = append(res, BlockHash(xxhash.Sum64String(request.TargetModel)))
-	for i := 0; i+cacheBlockSize <= len(prompt); i += cacheBlockSize {
+
+	firstBlockSize := cacheBlockSize
+	if len(prompt) < cacheBlockSize {
+		firstBlockSize = len(prompt)
+	}
+	firstBlock := prompt[0:firstBlockSize]
+	firstBlockWithModel := append([]byte(request.TargetModel), firstBlock...)
+	res = append(res, BlockHash(xxhash.Sum64(firstBlockWithModel)))
+
+	for i := cacheBlockSize; i+cacheBlockSize <= len(prompt); i += cacheBlockSize {
 		block := prompt[i : i+cacheBlockSize]
 		prevBlockHash := res[len(res)-1]
 		block = append(block, toBytes(prevBlockHash)...)
diff --git a/site-src/guides/index.md b/site-src/guides/index.md
index e02ffb5..58bb580 100644
--- a/site-src/guides/index.md
+++ b/site-src/guides/index.md
@@ -4,11 +4,16 @@
 
     This project is still in an alpha state and breaking changes may occur in the future.
 
+???+ warning
+
+
+    This page is out of date with the v1.0.0 release candidate. Updates under active development
+
 This quickstart guide is intended for engineers familiar with k8s and model servers (vLLM in this instance). The goal of this guide is to get an Inference Gateway up and running!
 
 ## **Prerequisites**
 
-- A cluster with:
+A cluster with:
   - Support for services of type `LoadBalancer`. For kind clusters, follow [this guide](https://kind.sigs.k8s.io/docs/user/loadbalancer)
   to get services of type LoadBalancer working.
   - Support for [sidecar containers](https://kubernetes.io/docs/concepts/workloads/pods/sidecar-containers/) (enabled by default since Kubernetes v1.29)
@@ -75,20 +80,6 @@ This quickstart guide is intended for engineers familiar with k8s and model serv
    kubectl apply -f https://github.com/kubernetes-sigs/gateway-api-inference-extension/releases/latest/download/manifests.yaml
    ```
 
-### Deploy InferenceModel
-
-   Deploy the sample InferenceModel which is configured to forward traffic to the `food-review-1` [LoRA adapter](https://docs.vllm.ai/en/latest/features/lora.html) of the sample model server.
-
-   ```bash
-   kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api-inference-extension/refs/tags/v0.5.1/config/manifests/inferencemodel.yaml
-   ```
-
-### Deploy the InferencePool and Endpoint Picker Extension
-
-   ```bash
-   kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api-inference-extension/refs/tags/v0.5.1/config/manifests/inferencepool-resources.yaml
-   ```
-
 ### Deploy an Inference Gateway
 
    Choose one of the following options to deploy an Inference Gateway.
@@ -98,20 +89,19 @@ This quickstart guide is intended for engineers familiar with k8s and model serv
       1. Enable the Gateway API and configure proxy-only subnets when necessary. See [Deploy Gateways](https://cloud.google.com/kubernetes-engine/docs/how-to/deploying-gateways)
       for detailed instructions.
 
-      1. Deploy Gateway and HealthCheckPolicy resources
+      2. Deploy Inference Gateway:
 
          ```bash
          kubectl apply -f https://github.com/kubernetes-sigs/gateway-api-inference-extension/raw/main/config/manifests/gateway/gke/gateway.yaml
-         kubectl apply -f https://github.com/kubernetes-sigs/gateway-api-inference-extension/raw/main/config/manifests/gateway/gke/healthcheck.yaml
          ```
 
          Confirm that the Gateway was assigned an IP address and reports a `Programmed=True` status:
+
          ```bash
          $ kubectl get gateway inference-gateway
          NAME                CLASS               ADDRESS         PROGRAMMED   AGE
          inference-gateway   inference-gateway   <MY_ADDRESS>    True         22s
          ```
-
       3. Deploy the HTTPRoute
 
          ```bash
@@ -123,13 +113,7 @@ This quickstart guide is intended for engineers familiar with k8s and model serv
          ```bash
          kubectl get httproute llm-route -o yaml
          ```
-
-      5. Given that the default connection timeout may be insufficient for most inference workloads, it is recommended to configure a timeout appropriate for your intended use case.
-
-         ```bash
-         kubectl apply -f https://github.com/kubernetes-sigs/gateway-api-inference-extension/raw/main/config/manifests/gateway/gke/gcp-backend-policy.yaml
-         ```
-
+   
 === "Istio"
 
       Please note that this feature is currently in an experimental phase and is not intended for production use.
@@ -283,6 +267,31 @@ This quickstart guide is intended for engineers familiar with k8s and model serv
          kubectl get httproute llm-route -o yaml
          ```
 
+
+### Deploy the InferencePool and Endpoint Picker Extension
+
+   Install an InferencePool named `vllm-llama3-8b-instruct` that selects from endpoints with label app: vllm-llama3-8b-instruct and listening on port 8000, you can run the following command:
+
+   ```bash
+   export GATEWAY_PROVIDER=none #  See [README](https://github.com/kubernetes-sigs/gateway-api-inference-extension/blob/main/config/charts/inferencepool/README.md#configuration) for valid configurations
+   helm install vllm-llama3-8b-instruct \
+   --set inferencePool.modelServers.matchLabels.app=vllm-llama3-8b-instruct \
+   --set provider.name=$GATEWAY_PROVIDER \
+   --version v0.3.0 \
+   oci://registry.k8s.io/gateway-api-inference-extension/charts/inferencepool
+   ```
+
+   The Helm install automatically installs the endpoint-picker, inferencepool along with provider specific resources.
+
+### Deploy InferenceObjective (Optional)
+
+   Deploy the sample InferenceObjective which allows you to specify priority of requests.
+
+   ```bash
+   kubectl apply -f https://github.com/kubernetes-sigs/gateway-api-inference-extension/raw/main/config/manifests/inferenceobjective.yaml
+   ```
+
+
 ### Try it out
 
    Wait until the gateway is ready.
diff --git a/site-src/guides/troubleshooting.md b/site-src/guides/troubleshooting.md
new file mode 100644
index 0000000..65a781d
--- /dev/null
+++ b/site-src/guides/troubleshooting.md
@@ -0,0 +1,91 @@
+# Troubleshooting Guide
+
+This guide provides troubleshooting steps and solutions for common issues encountered with the Gateway API inference extension.
+
+## 400 Bad Request
+
+### `model not found in request body` or `prompt not found in request`
+If the OpenAI API endpoint you're using isn't working as expected, the issue might be related to the request body format. The endpoint picker (EPP) assumes that if a request is a POST, its body must contain the `model` field and the `prompt` (or `messages`) field. This is because the gateway currently assumes the requests are for Large Language Models (LLMs).
+
+**Solution**: Make sure your request body contains the missing field.
+
+## 404 Not Found
+This is a default gateway error, meaning the request never reached a backend service. This usually means that there is no HTTPRoute configured to match the request path (e.g. /v1/completions). The gateway doesn't know where to send the traffic.
+
+**Solution**: Ensure you have an HTTPRoute resource deployed that specifies the correct host, path, and backendRef to your InferencePool.
+
+## 429 Too Many Requests
+### `system saturated, sheddable request dropped`
+This error indicates that the entire inference pool has exceeded its saturation thresholds. This means the system is under heavy load and is shedding non-critical requests. To address this, check the following:
+
+* gateway-api-inference-extension version:
+    * **v0.5.1 and earlier**: Verify you're using an `InferenceModel` and that its `criticality` is set to `Critical`. This ensures requests are queued on the model servers instead of being dropped.
+    * **v1.0.0 and later**: Ensure the `InferenceObjective` you're using has a `priority` greater than or equal to 0. A negative priority can cause requests to be dropped.
+
+* Pool Thresholds: Check the defined pool [thresholds](https://github.com/kubernetes-sigs/gateway-api-inference-extension/blob/f36111cab0ed5a309d1eafade896d4f37ab623a6/pkg/epp/saturationdetector/config.go#L41) to understand the saturation limits. Currently, we use three main metrics to assess the system's load:
+    * `DefaultQueueDepthThreshold`: This is the maximum number of requests waiting in the queue for a backend. The default value is 5. If the queue for a model server exceeds this number, the saturation detector may consider the system under pressure. To override this, set the `SD_QUEUE_DEPTH_THRESHOLD` environment variable.
+    * `DefaultKVCacheUtilThreshold`: This is the maximum utilization of the Key-Value (KV) cache on the model server, expressed as a decimal from 0.0 to 1.0. The default is 0.8, or 80%. The KV cache stores attention keys and values to speed up inference for subsequent tokens. When its utilization exceeds this threshold, it's an indication that the model server is nearing its memory capacity and may be becoming saturated. To override this, set the `SD_KV_CACHE_UTIL_THRESHOLD` environment variable.
+    * `DefaultMetricsStalenessThreshold`: This defines the maximum age of metrics data before it's considered outdated. The default is 200 milliseconds. The saturation detector needs up-to-date metrics to make accurate decisions about system load. If the metrics are older than this threshold, the detector won't use them. This value is tied to how often metrics are refreshed, and setting it slightly higher ensures that there's always fresh data available. To override this, set the `SD_METRICS_STALENESS_THRESHOLD` environment variable.
+
+## 500 Internal Server Error
+### `fault filter abort`
+This internal error suggests a misconfiguration in the gateway's backend routing. Your HTTPRoute is configured to point to an InferencePool that does not exist or cannot be found by the gateway. The gateway recognizes the route but fails when trying to send traffic to the non-existent backend.
+
+**Solution**: Verify that the backendRef in your HTTPRoute correctly names an InferencePool resource that is deployed and accessible in the same namespace. If you wish to route to an InferencePool in a different namespace, you can create a `ReferenceGrant` like below:
+
+```
+apiVersion: gateway.networking.k8s.io/v1beta1
+kind: ReferenceGrant
+metadata:
+  name: ref-grant
+  namespace: ns2
+spec:
+  from:
+    - group: gateway.networking.k8s.io
+      kind: HTTPRoute
+      namespace: ns1
+  to:
+    - group: inference.networking.k8s.io
+      kind: InferencePool
+      name: my-inference-pool
+```
+
+## 502 Bad Gateway or 503 Service Unavailable
+### `upstream connect error or disconnect/reset ...`
+The gateway can return an error when it cannot connect to its backends. This error indicates that the gateway successfully identified the correct model server pod but failed to establish a connection to it. This is likely caused by the port number specified in the InferencePool's configuration doesn't match the port your model server is listening on. The gateway tries to connect to the wrong port and is refused.
+
+**Solution**: Verify the port specified in your InferencePool matches the port number exposed by your model server container, and update your InferencePool accordingly.
+
+## 503 Service Unavailable
+### `no healthy upstream`
+This error indicates that the HTTPRoute and InferencePool are correctly configured, but there are no healthy pods in the pool to route traffic to. This can happen if the pods are crashing, still starting up, or failing their health checks.
+
+**Solution**: Check the status of your model server pods. Investigate the pod logs for any startup errors or health check failures. Ensure your model server is running and listening on the correct port and that any configured healthchecks / readiness probes are succeeding.
+
+## The endpoint picker (EPP) Crashlooping
+When EPP is crashlooping, check the logs of your EPP pod. Some common errors include:
+
+### `failed to list <InferencePool or InferenceObjective or Pod>: … is forbidden`
+The EPP needs to watch the InferencePool, InferenceObjectives and Pods that belong to them. This constant watching and reconciliation allows the EPP to maintain an up-to-date view of the environment, enabling it to make dynamic decisions. This particular error indicates that the service account used by the EPP doesn't have the necessary permissions to list the resources it’s watching.
+
+**Solution**: Create or update the RBAC configuration to grant the [required permissions](https://github.com/kubernetes-sigs/gateway-api-inference-extension/blob/137a0b4660b96487caac626ed135b3600be876ed/config/manifests/inferencepool-resources.yaml#L129) to the EPP service account.
+
+### `Pool is not initialized, skipping refreshing metrics`
+This error indicates that the Inference Pool pods are not initialized. 
+
+**Solution**: Check the EPP start up argument `--pool-name` has the correct InferencePool name specified and the InferencePool exists.
+
+## Unexpected Routing Behaviors
+The EPP's core function is to intelligently route requests to the most optimal model server pod in a pool. It uses a score-based algorithm that considers several metrics (such as queue depth, KV cache utilization, etc.) to choose the best pod for each request. 
+
+For unexpected routing behaviors: 
+
+* Verify the expected metrics are being emitted from the model server. Some model servers aren't fully compatible with the default expected metrics, vLLM is generally the most up-to-date in this regard. See [Support Model Servers](https://gateway-api-inference-extension.sigs.k8s.io/implementations/model-servers/).
+* Check your [plugins](https://gateway-api-inference-extension.sigs.k8s.io/guides/epp-configuration/config-text/) configuration, especially the weights of the scorer plugins. If weight is omitted, a default weight of 1 will be used.
+
+## Poor Performance under High Concurrency
+For more information, check out [EPP scale testing](https://docs.google.com/document/d/1TDD_wvuTO5hhm1Byl8K7TZkNnn8sVQ1ZrkZM_u0gJvw/edit?tab=t.0#heading=h.mtff4cnithxf).
+
+When performance degrades under high load (for example high-latency tail or significantly lower-than-expected successful QPS) with underutilized resources, the issue may be related to excessive logging in the endpoint picker (EPP). Higher verbosity levels (e.g., `--v=2` or greater) generate a large volume of logs. This floods the log buffer and standard output, leading to heavy writelock contention. In extreme cases, this can cause the kubelet to kill the pod due to health check timeouts, leading to a restart cycle. 
+
+**Solution**: Ensure log level for the EPP is set to `--v=1`.
diff --git a/site-src/index.md b/site-src/index.md
index 7a2a116..7539d01 100644
--- a/site-src/index.md
+++ b/site-src/index.md
@@ -1,5 +1,11 @@
 # Introduction
 
+???+ warning
+
+
+    Some portions of this site may be out of date with the v1.0.0 release candidate. 
+    Updates under active development!
+
 Gateway API Inference Extension is an official Kubernetes project that optimizes self-hosting Generative Models on Kubernetes.
 
 The overall resource model focuses on 2 new inference-focused
diff --git a/site-src/reference/spec.md b/site-src/reference/spec.md
index 9b31f44..12ce3d7 100644
--- a/site-src/reference/spec.md
+++ b/site-src/reference/spec.md
@@ -15,43 +15,44 @@ inference.networking.k8s.io API group.
 
 
 
-#### Extension
+#### EndpointPickerFailureMode
 
+_Underlying type:_ _string_
 
+EndpointPickerFailureMode defines the options for how the parent handles the case when the
+Endpoint Picker extension is non-responsive.
 
-Extension specifies how to configure an extension that runs the endpoint picker.
+_Validation:_
+- Enum: [FailOpen FailClose]
 
+_Appears in:_
+- [EndpointPickerRef](#endpointpickerref)
 
+| Field | Description |
+| --- | --- |
+| `FailOpen` | EndpointPickerFailOpen specifies that the parent should forward the request to an endpoint<br />of its picking when the Endpoint Picker extension fails.<br /> |
+| `FailClose` | EndpointPickerFailClose specifies that the parent should drop the request when the Endpoint<br />Picker extension fails.<br /> |
 
-_Appears in:_
-- [InferencePoolSpec](#inferencepoolspec)
 
-| Field | Description | Default | Validation |
-| --- | --- | --- | --- |
-| `group` _[Group](#group)_ | Group is the group of the referent.<br />The default value is "", representing the Core API group. |  | MaxLength: 253 <br />MinLength: 0 <br />Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` <br /> |
-| `kind` _[Kind](#kind)_ | Kind is the Kubernetes resource kind of the referent.<br />Defaults to "Service" when not specified.<br />ExternalName services can refer to CNAME DNS records that may live<br />outside of the cluster and as such are difficult to reason about in<br />terms of conformance. They also may not be safe to forward to (see<br />CVE-2021-25740 for more information). Implementations MUST NOT<br />support ExternalName Services. | Service | MaxLength: 63 <br />MinLength: 1 <br />Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$` <br /> |
-| `name` _[ObjectName](#objectname)_ | Name is the name of the referent. |  | MaxLength: 253 <br />MinLength: 1 <br /> |
-| `portNumber` _[PortNumber](#portnumber)_ | The port number on the service running the extension. When unspecified,<br />implementations SHOULD infer a default value of 9002 when the Kind is<br />Service. |  | Maximum: 65535 <br />Minimum: 1 <br /> |
-| `failureMode` _[ExtensionFailureMode](#extensionfailuremode)_ | Configures how the gateway handles the case when the extension is not responsive.<br />Defaults to failClose. | FailClose | Enum: [FailOpen FailClose] <br /> |
+#### EndpointPickerRef
 
 
-#### ExtensionFailureMode
 
-_Underlying type:_ _string_
+EndpointPickerRef specifies a reference to an Endpoint Picker extension and its
+associated configuration.
 
-ExtensionFailureMode defines the options for how the gateway handles the case when the extension is not
-responsive.
 
-_Validation:_
-- Enum: [FailOpen FailClose]
 
 _Appears in:_
-- [Extension](#extension)
+- [InferencePoolSpec](#inferencepoolspec)
 
-| Field | Description |
-| --- | --- |
-| `FailOpen` | FailOpen specifies that the proxy should forward the request to an endpoint of its picking when the Endpoint Picker fails.<br /> |
-| `FailClose` | FailClose specifies that the proxy should drop the request when the Endpoint Picker fails.<br /> |
+| Field | Description | Default | Validation |
+| --- | --- | --- | --- |
+| `group` _[Group](#group)_ | Group is the group of the referent API object. When unspecified, the default value<br />is "", representing the Core API group. |  | MaxLength: 253 <br />MinLength: 0 <br />Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` <br /> |
+| `kind` _[Kind](#kind)_ | Kind is the Kubernetes resource kind of the referent.<br />Required if the referent is ambiguous, e.g. service with multiple ports.<br />Defaults to "Service" when not specified.<br />ExternalName services can refer to CNAME DNS records that may live<br />outside of the cluster and as such are difficult to reason about in<br />terms of conformance. They also may not be safe to forward to (see<br />CVE-2021-25740 for more information). Implementations MUST NOT<br />support ExternalName Services. | Service | MaxLength: 63 <br />MinLength: 1 <br />Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$` <br /> |
+| `name` _[ObjectName](#objectname)_ | Name is the name of the referent API object. |  | MaxLength: 253 <br />MinLength: 1 <br /> |
+| `portNumber` _[PortNumber](#portnumber)_ | PortNumber is the port number of the Endpoint Picker extension service. When unspecified,<br />implementations SHOULD infer a default value of 9002 when the kind field is "Service" or<br />unspecified (defaults to "Service"). |  | Maximum: 65535 <br />Minimum: 1 <br /> |
+| `failureMode` _[EndpointPickerFailureMode](#endpointpickerfailuremode)_ | FailureMode configures how the parent handles the case when the Endpoint Picker extension<br />is non-responsive. When unspecified, defaults to "FailClose". | FailClose | Enum: [FailOpen FailClose] <br /> |
 
 
 #### Group
@@ -80,8 +81,8 @@ _Validation:_
 - Pattern: `^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
 
 _Appears in:_
-- [Extension](#extension)
-- [ParentGatewayReference](#parentgatewayreference)
+- [EndpointPickerRef](#endpointpickerref)
+- [ParentReference](#parentreference)
 
 
 
@@ -101,8 +102,8 @@ InferencePool is the Schema for the InferencePools API.
 | `apiVersion` _string_ | `inference.networking.k8s.io/v1` | | |
 | `kind` _string_ | `InferencePool` | | |
 | `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. |  |  |
-| `spec` _[InferencePoolSpec](#inferencepoolspec)_ |  |  |  |
-| `status` _[InferencePoolStatus](#inferencepoolstatus)_ | Status defines the observed state of InferencePool. | \{ parent:[map[conditions:[map[lastTransitionTime:1970-01-01T00:00:00Z message:Waiting for controller reason:Pending status:Unknown type:Accepted]] parentRef:map[kind:Status name:default]]] \} | MinProperties: 1 <br /> |
+| `spec` _[InferencePoolSpec](#inferencepoolspec)_ | Spec defines the desired state of the InferencePool. |  |  |
+| `status` _[InferencePoolStatus](#inferencepoolstatus)_ | Status defines the observed state of the InferencePool. |  |  |
 
 
 
@@ -113,7 +114,7 @@ InferencePool is the Schema for the InferencePools API.
 
 
 
-InferencePoolSpec defines the desired state of InferencePool
+InferencePoolSpec defines the desired state of the InferencePool.
 
 
 
@@ -124,24 +125,23 @@ _Appears in:_
 | --- | --- | --- | --- |
 | `selector` _[LabelSelector](#labelselector)_ | Selector determines which Pods are members of this inference pool.<br />It matches Pods by their labels only within the same namespace; cross-namespace<br />selection is not supported.<br />The structure of this LabelSelector is intentionally simple to be compatible<br />with Kubernetes Service selectors, as some implementations may translate<br />this configuration into a Service resource. |  |  |
 | `targetPorts` _[Port](#port) array_ | TargetPorts defines a list of ports that are exposed by this InferencePool.<br />Currently, the list may only include a single port definition. |  | MaxItems: 1 <br />MinItems: 1 <br /> |
-| `extensionRef` _[Extension](#extension)_ | Extension configures an endpoint picker as an extension service. |  |  |
+| `endpointPickerRef` _[EndpointPickerRef](#endpointpickerref)_ | EndpointPickerRef is a reference to the Endpoint Picker extension and its<br />associated configuration. |  |  |
 
 
 #### InferencePoolStatus
 
 
 
-InferencePoolStatus defines the observed state of InferencePool.
+InferencePoolStatus defines the observed state of the InferencePool.
+
 
-_Validation:_
-- MinProperties: 1
 
 _Appears in:_
 - [InferencePool](#inferencepool)
 
 | Field | Description | Default | Validation |
 | --- | --- | --- | --- |
-| `parent` _[PoolStatus](#poolstatus) array_ | Parents is a list of parent resources (usually Gateways) that are<br />associated with the InferencePool, and the status of the InferencePool with respect to<br />each parent.<br />A maximum of 32 Gateways will be represented in this list. When the list contains<br />`kind: Status, name: default`, it indicates that the InferencePool is not<br />associated with any Gateway and a controller must perform the following:<br /> - Remove the parent when setting the "Accepted" condition.<br /> - Add the parent when the controller will no longer manage the InferencePool<br />   and no other parents exist. |  | MaxItems: 32 <br /> |
+| `parents` _[ParentStatus](#parentstatus) array_ | Parents is a list of parent resources, typically Gateways, that are associated with<br />the InferencePool, and the status of the InferencePool with respect to each parent.<br />A controller that manages the InferencePool, must add an entry for each parent it manages<br />and remove the parent entry when the controller no longer considers the InferencePool to<br />be associated with that parent.<br />A maximum of 32 parents will be represented in this list. When the list is empty,<br />it indicates that the InferencePool is not associated with any parents. |  | MaxItems: 32 <br /> |
 
 
 #### Kind
@@ -165,8 +165,8 @@ _Validation:_
 - Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$`
 
 _Appears in:_
-- [Extension](#extension)
-- [ParentGatewayReference](#parentgatewayreference)
+- [EndpointPickerRef](#endpointpickerref)
+- [ParentReference](#parentreference)
 
 
 
@@ -217,7 +217,7 @@ _Appears in:_
 
 | Field | Description | Default | Validation |
 | --- | --- | --- | --- |
-| `matchLabels` _object (keys:[LabelKey](#labelkey), values:[LabelValue](#labelvalue))_ | matchLabels contains a set of required \{key,value\} pairs.<br />An object must match every label in this map to be selected.<br />The matching logic is an AND operation on all entries. |  | MaxItems: 64 <br /> |
+| `matchLabels` _object (keys:[LabelKey](#labelkey), values:[LabelValue](#labelvalue))_ | MatchLabels contains a set of required \{key,value\} pairs.<br />An object must match every label in this map to be selected.<br />The matching logic is an AND operation on all entries. |  | MaxItems: 64 <br />MinItems: 1 <br /> |
 
 
 #### LabelValue
@@ -272,7 +272,7 @@ _Validation:_
 - Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
 
 _Appears in:_
-- [ParentGatewayReference](#parentgatewayreference)
+- [ParentReference](#parentreference)
 
 
 
@@ -289,36 +289,36 @@ _Validation:_
 - MinLength: 1
 
 _Appears in:_
-- [Extension](#extension)
-- [ParentGatewayReference](#parentgatewayreference)
+- [EndpointPickerRef](#endpointpickerref)
+- [ParentReference](#parentreference)
 
 
 
-#### ParentGatewayReference
+#### ParentReference
 
 
 
-ParentGatewayReference identifies an API object including its namespace,
-defaulting to Gateway.
+ParentReference identifies an API object. It is used to associate the InferencePool with a
+parent resource, such as a Gateway.
 
 
 
 _Appears in:_
-- [PoolStatus](#poolstatus)
+- [ParentStatus](#parentstatus)
 
 | Field | Description | Default | Validation |
 | --- | --- | --- | --- |
-| `group` _[Group](#group)_ | Group is the group of the referent. | gateway.networking.k8s.io | MaxLength: 253 <br />MinLength: 0 <br />Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` <br /> |
-| `kind` _[Kind](#kind)_ | Kind is kind of the referent. For example "Gateway". | Gateway | MaxLength: 63 <br />MinLength: 1 <br />Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$` <br /> |
-| `name` _[ObjectName](#objectname)_ | Name is the name of the referent. |  | MaxLength: 253 <br />MinLength: 1 <br /> |
-| `namespace` _[Namespace](#namespace)_ | Namespace is the namespace of the referent.  If not present,<br />the namespace of the referent is assumed to be the same as<br />the namespace of the referring object. |  | MaxLength: 63 <br />MinLength: 1 <br />Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$` <br /> |
+| `group` _[Group](#group)_ | Group is the group of the referent API object. When unspecified, the referent is assumed<br />to be in the "gateway.networking.k8s.io" API group. | gateway.networking.k8s.io | MaxLength: 253 <br />MinLength: 0 <br />Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` <br /> |
+| `kind` _[Kind](#kind)_ | Kind is the kind of the referent API object. When unspecified, the referent is assumed<br />to be a "Gateway" kind. | Gateway | MaxLength: 63 <br />MinLength: 1 <br />Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$` <br /> |
+| `name` _[ObjectName](#objectname)_ | Name is the name of the referent API object. |  | MaxLength: 253 <br />MinLength: 1 <br /> |
+| `namespace` _[Namespace](#namespace)_ | Namespace is the namespace of the referenced object. When unspecified, the local<br />namespace is inferred.<br />Note that when a namespace different than the local namespace is specified,<br />a ReferenceGrant object is required in the referent namespace to allow that<br />namespace's owner to accept the reference. See the ReferenceGrant<br />documentation for details: https://gateway-api.sigs.k8s.io/api-types/referencegrant/ |  | MaxLength: 63 <br />MinLength: 1 <br />Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$` <br /> |
 
 
-#### PoolStatus
+#### ParentStatus
 
 
 
-PoolStatus defines the observed state of InferencePool from a Gateway.
+ParentStatus defines the observed state of InferencePool from a Parent, i.e. Gateway.
 
 
 
@@ -327,8 +327,8 @@ _Appears in:_
 
 | Field | Description | Default | Validation |
 | --- | --- | --- | --- |
-| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#condition-v1-meta) array_ | Conditions track the state of the InferencePool.<br />Known condition types are:<br />* "Accepted"<br />* "ResolvedRefs" | [map[lastTransitionTime:1970-01-01T00:00:00Z message:Waiting for controller reason:Pending status:Unknown type:Accepted]] | MaxItems: 8 <br /> |
-| `parentRef` _[ParentGatewayReference](#parentgatewayreference)_ | GatewayRef indicates the gateway that observed state of InferencePool. |  |  |
+| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#condition-v1-meta) array_ | Conditions is a list of status conditions that provide information about the observed<br />state of the InferencePool. This field is required to be set by the controller that<br />manages the InferencePool.<br />Supported condition types are:<br />* "Accepted"<br />* "ResolvedRefs" |  | MaxItems: 8 <br /> |
+| `parentRef` _[ParentReference](#parentreference)_ | ParentRef is used to identify the parent resource that this status<br />is associated with. It is used to match the InferencePool with the parent<br />resource, such as a Gateway. |  |  |
 
 
 #### Port
@@ -358,7 +358,7 @@ _Validation:_
 - Minimum: 1
 
 _Appears in:_
-- [Extension](#extension)
+- [EndpointPickerRef](#endpointpickerref)
 - [Port](#port)
 
 
diff --git a/site-src/reference/x-spec.md b/site-src/reference/x-spec.md
index bb91323..9151dcd 100644
--- a/site-src/reference/x-spec.md
+++ b/site-src/reference/x-spec.md
@@ -136,7 +136,7 @@ _Appears in:_
 
 | Field | Description | Default | Validation |
 | --- | --- | --- | --- |
-| `priority` _integer_ | Priority defines how important it is to serve the request compared to other requests in the same pool.<br />Priority is an integer value that defines the priority of the request.<br />The higher the value, the more critical the request is; negative values _are_ allowed.<br />No default value is set for this field, allowing for future additions of new fields that may 'one of' with this field.<br />However, implementations that consume this field (such as the Endpoint Picker) will treat an unset value as '0'.<br />Priority is used in flow control, primarily in the event of resource scarcity(reqeusts need to be queued).<br />All requests will be queued, and flow control will _always_ allow requests of higher priority to be served first.<br />Fairness is only enforced and tracked between requests of the same priority.<br />Example: requests with Priority 10 will always be served before<br />requests with Priority of 0 (the value used if Priority is unset or no InfereneceObjective is specified).<br />Similarly requests with a Priority of -10 will always be served after requests with Priority of 0. |  |  |
+| `priority` _integer_ | Priority defines how important it is to serve the request compared to other requests in the same pool.<br />Priority is an integer value that defines the priority of the request.<br />The higher the value, the more critical the request is; negative values _are_ allowed.<br />No default value is set for this field, allowing for future additions of new fields that may 'one of' with this field.<br />However, implementations that consume this field (such as the Endpoint Picker) will treat an unset value as '0'.<br />Priority is used in flow control, primarily in the event of resource scarcity(requests need to be queued).<br />All requests will be queued, and flow control will _always_ allow requests of higher priority to be served first.<br />Fairness is only enforced and tracked between requests of the same priority.<br />Example: requests with Priority 10 will always be served before<br />requests with Priority of 0 (the value used if Priority is unset or no InfereneceObjective is specified).<br />Similarly requests with a Priority of -10 will always be served after requests with Priority of 0. |  |  |
 | `poolRef` _[PoolObjectReference](#poolobjectreference)_ | PoolRef is a reference to the inference pool, the pool must exist in the same namespace. |  | Required: \{\} <br /> |
 
 



Test patch:
diff --git a/apix/v1alpha2/inferencepool_conversion_test.go b/apix/v1alpha2/inferencepool_conversion_test.go
index 2c59fc6..a4147f2 100644
--- a/apix/v1alpha2/inferencepool_conversion_test.go
+++ b/apix/v1alpha2/inferencepool_conversion_test.go
@@ -33,7 +33,7 @@ var (
 
 	v1Group       = v1.Group("my-group")
 	v1Kind        = v1.Kind("MyKind")
-	v1FailureMode = v1.ExtensionFailureMode("Deny")
+	v1FailureMode = v1.EndpointPickerFailureMode("Deny")
 	v1PortNumber  = v1.PortNumber(9000)
 )
 
@@ -49,7 +49,7 @@ func TestInferencePoolConvertTo(t *testing.T) {
 			src: &InferencePool{
 				TypeMeta: metav1.TypeMeta{
 					Kind:       "InferencePool",
-					APIVersion: "inference.networking.x-k8s.io/v1alpha2",
+					APIVersion: GroupVersion.String(),
 				},
 				ObjectMeta: metav1.ObjectMeta{
 					Name:      "test-pool",
@@ -73,6 +73,12 @@ func TestInferencePoolConvertTo(t *testing.T) {
 						{
 							GatewayRef: ParentGatewayReference{Name: "my-gateway"},
 							Conditions: []metav1.Condition{
+								{ // v1alpha2 default condition is skipped from conversion.
+									Type:               string(v1.InferencePoolConditionAccepted),
+									Status:             metav1.ConditionUnknown,
+									Reason:             string(InferencePoolReasonPending),
+									LastTransitionTime: timestamp,
+								},
 								{
 									Type:               string(InferencePoolConditionAccepted),
 									Status:             metav1.ConditionTrue,
@@ -87,7 +93,7 @@ func TestInferencePoolConvertTo(t *testing.T) {
 			want: &v1.InferencePool{
 				TypeMeta: metav1.TypeMeta{
 					Kind:       "InferencePool",
-					APIVersion: "inference.networking.x-k8s.io/v1alpha2",
+					APIVersion: v1.GroupVersion.String(),
 				},
 				ObjectMeta: metav1.ObjectMeta{
 					Name:      "test-pool",
@@ -109,9 +115,9 @@ func TestInferencePoolConvertTo(t *testing.T) {
 					},
 				},
 				Status: v1.InferencePoolStatus{
-					Parents: []v1.PoolStatus{
+					Parents: []v1.ParentStatus{
 						{
-							GatewayRef: v1.ParentGatewayReference{Name: "my-gateway"},
+							ParentRef: v1.ParentReference{Name: "my-gateway"},
 							Conditions: []metav1.Condition{
 								{
 									Type:               string(v1.InferencePoolConditionAccepted),
@@ -127,11 +133,11 @@ func TestInferencePoolConvertTo(t *testing.T) {
 			wantErr: false,
 		},
 		{
-			name: "conversion from v1alpha2 to v1 with empty extensionRef",
+			name: "conversion from v1alpha2 to v1 with empty extensionRef and default v1alpha2 status condition",
 			src: &InferencePool{
 				TypeMeta: metav1.TypeMeta{
 					Kind:       "InferencePool",
-					APIVersion: "inference.networking.x-k8s.io/v1alpha2",
+					APIVersion: GroupVersion.String(),
 				},
 				ObjectMeta: metav1.ObjectMeta{
 					Name:      "test-pool",
@@ -149,9 +155,9 @@ func TestInferencePoolConvertTo(t *testing.T) {
 							GatewayRef: ParentGatewayReference{Name: "my-gateway"},
 							Conditions: []metav1.Condition{
 								{
-									Type:               string(InferencePoolConditionAccepted),
-									Status:             metav1.ConditionTrue,
-									Reason:             string(InferencePoolReasonAccepted),
+									Type:               string(v1.InferencePoolConditionAccepted),
+									Status:             metav1.ConditionUnknown,
+									Reason:             string(InferencePoolReasonPending),
 									LastTransitionTime: timestamp,
 								},
 							},
@@ -162,7 +168,7 @@ func TestInferencePoolConvertTo(t *testing.T) {
 			want: &v1.InferencePool{
 				TypeMeta: metav1.TypeMeta{
 					Kind:       "InferencePool",
-					APIVersion: "inference.networking.x-k8s.io/v1alpha2",
+					APIVersion: v1.GroupVersion.String(),
 				},
 				ObjectMeta: metav1.ObjectMeta{
 					Name:      "test-pool",
@@ -177,14 +183,202 @@ func TestInferencePoolConvertTo(t *testing.T) {
 					TargetPorts: []v1.Port{{Number: v1.PortNumber(int32(8080))}},
 				},
 				Status: v1.InferencePoolStatus{
-					Parents: []v1.PoolStatus{
+					Parents: []v1.ParentStatus{
+						{
+							ParentRef: v1.ParentReference{Name: "my-gateway"},
+							// Conditions omitted (nil) after dropping the synthetic default.
+						},
+					},
+				},
+			},
+			wantErr: false,
+		},
+		{
+			name: "v1alpha2 -> v1 maps NotSupportedByGateway to NotSupportedByParent",
+			src: &InferencePool{
+				TypeMeta: metav1.TypeMeta{
+					Kind:       "InferencePool",
+					APIVersion: GroupVersion.String(),
+				},
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "pool",
+					Namespace: "ns",
+				},
+				Spec: InferencePoolSpec{
+					Selector:         map[LabelKey]LabelValue{"app": "m"},
+					TargetPortNumber: 8080,
+				},
+				Status: InferencePoolStatus{
+					Parents: []PoolStatus{
 						{
-							GatewayRef: v1.ParentGatewayReference{Name: "my-gateway"},
+							GatewayRef: ParentGatewayReference{Name: "gw"},
+							Conditions: []metav1.Condition{
+								{
+									Type:               string(InferencePoolConditionAccepted),
+									Status:             metav1.ConditionFalse,
+									Reason:             string(InferencePoolReasonNotSupportedByGateway),
+									LastTransitionTime: timestamp,
+								},
+							},
+						},
+					},
+				},
+			},
+			want: &v1.InferencePool{
+				TypeMeta: metav1.TypeMeta{
+					Kind:       "InferencePool",
+					APIVersion: v1.GroupVersion.String(),
+				},
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "pool",
+					Namespace: "ns",
+				},
+				Spec: v1.InferencePoolSpec{
+					Selector: v1.LabelSelector{MatchLabels: map[v1.LabelKey]v1.LabelValue{"app": "m"}},
+					TargetPorts: []v1.Port{
+						{Number: v1.PortNumber(8080)},
+					},
+				},
+				Status: v1.InferencePoolStatus{
+					Parents: []v1.ParentStatus{
+						{
+							ParentRef: v1.ParentReference{Name: "gw"},
 							Conditions: []metav1.Condition{
 								{
 									Type:               string(v1.InferencePoolConditionAccepted),
+									Status:             metav1.ConditionFalse,
+									Reason:             string(v1.InferencePoolReasonNotSupportedByParent),
+									LastTransitionTime: timestamp,
+								},
+							},
+						},
+					},
+				},
+			},
+			wantErr: false,
+		},
+		{
+			name: "v1alpha2 -> v1 drops synthetic default parent",
+			src: &InferencePool{
+				TypeMeta: metav1.TypeMeta{
+					Kind:       "InferencePool",
+					APIVersion: GroupVersion.String(),
+				},
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "pool",
+					Namespace: "ns",
+				},
+				Spec: InferencePoolSpec{
+					Selector:         map[LabelKey]LabelValue{"app": "m"},
+					TargetPortNumber: 8080,
+				},
+				Status: InferencePoolStatus{
+					Parents: []PoolStatus{
+						{
+							GatewayRef: func() ParentGatewayReference {
+								k := Kind("Status")
+								return ParentGatewayReference{
+									Kind: &k, Name: "default",
+								}
+							}(),
+							Conditions: []metav1.Condition{
+								{
+									Type:               string(InferencePoolConditionAccepted),
+									Status:             metav1.ConditionUnknown,
+									Reason:             string(InferencePoolReasonPending),
+									LastTransitionTime: timestamp,
+								},
+							},
+						},
+					},
+				},
+			},
+			want: &v1.InferencePool{
+				TypeMeta: metav1.TypeMeta{
+					Kind:       "InferencePool",
+					APIVersion: v1.GroupVersion.String(),
+				},
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "pool",
+					Namespace: "ns",
+				},
+				Spec: v1.InferencePoolSpec{
+					Selector:    v1.LabelSelector{MatchLabels: map[v1.LabelKey]v1.LabelValue{"app": "m"}},
+					TargetPorts: []v1.Port{{Number: v1.PortNumber(8080)}},
+				},
+				Status: v1.InferencePoolStatus{
+					// All parents dropped -> empty status.
+				},
+			},
+			wantErr: false,
+		},
+		{
+			name: "v1alpha2 -> v1 drops synthetic default parent but keeps real parent",
+			src: &InferencePool{
+				TypeMeta: metav1.TypeMeta{
+					Kind:       "InferencePool",
+					APIVersion: GroupVersion.String(),
+				},
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "pool",
+					Namespace: "ns",
+				},
+				Spec: InferencePoolSpec{
+					Selector:         map[LabelKey]LabelValue{"app": "m"},
+					TargetPortNumber: 8080,
+				},
+				Status: InferencePoolStatus{
+					Parents: []PoolStatus{
+						{
+							GatewayRef: func() ParentGatewayReference {
+								k := Kind("Status")
+								return ParentGatewayReference{Kind: &k, Name: "default"}
+							}(),
+							Conditions: []metav1.Condition{
+								{
+									Type:               string(InferencePoolConditionAccepted),
+									Status:             metav1.ConditionUnknown,
+									Reason:             string(InferencePoolReasonPending),
+									LastTransitionTime: timestamp,
+								},
+							},
+						},
+						{
+							GatewayRef: ParentGatewayReference{Name: "real-gw"},
+							Conditions: []metav1.Condition{
+								{
+									Type:               string(InferencePoolConditionResolvedRefs),
 									Status:             metav1.ConditionTrue,
-									Reason:             string(v1.InferencePoolReasonAccepted),
+									Reason:             string(InferencePoolReasonResolvedRefs),
+									LastTransitionTime: timestamp,
+								},
+							},
+						},
+					},
+				},
+			},
+			want: &v1.InferencePool{
+				TypeMeta: metav1.TypeMeta{
+					Kind:       "InferencePool",
+					APIVersion: v1.GroupVersion.String(),
+				},
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "pool",
+					Namespace: "ns",
+				},
+				Spec: v1.InferencePoolSpec{
+					Selector:    v1.LabelSelector{MatchLabels: map[v1.LabelKey]v1.LabelValue{"app": "m"}},
+					TargetPorts: []v1.Port{{Number: v1.PortNumber(8080)}},
+				},
+				Status: v1.InferencePoolStatus{
+					Parents: []v1.ParentStatus{
+						{
+							ParentRef: v1.ParentReference{Name: "real-gw"},
+							Conditions: []metav1.Condition{
+								{
+									Type:               string(v1.InferencePoolConditionResolvedRefs),
+									Status:             metav1.ConditionTrue,
+									Reason:             string(v1.InferencePoolReasonResolvedRefs),
 									LastTransitionTime: timestamp,
 								},
 							},
@@ -222,7 +416,7 @@ func TestInferencePoolConvertFrom(t *testing.T) {
 			src: &v1.InferencePool{
 				TypeMeta: metav1.TypeMeta{
 					Kind:       "InferencePool",
-					APIVersion: "inference.networking.k8s.io/v1",
+					APIVersion: v1.GroupVersion.String(),
 				},
 				ObjectMeta: metav1.ObjectMeta{
 					Name:      "test-pool",
@@ -244,9 +438,9 @@ func TestInferencePoolConvertFrom(t *testing.T) {
 					},
 				},
 				Status: v1.InferencePoolStatus{
-					Parents: []v1.PoolStatus{
+					Parents: []v1.ParentStatus{
 						{
-							GatewayRef: v1.ParentGatewayReference{Name: "my-gateway"},
+							ParentRef: v1.ParentReference{Name: "my-gateway"},
 							Conditions: []metav1.Condition{
 								{
 									Type:               string(v1.InferencePoolConditionAccepted),
@@ -262,7 +456,7 @@ func TestInferencePoolConvertFrom(t *testing.T) {
 			want: &InferencePool{
 				TypeMeta: metav1.TypeMeta{
 					Kind:       "InferencePool",
-					APIVersion: "inference.networking.k8s.io/v1",
+					APIVersion: GroupVersion.String(),
 				},
 				ObjectMeta: metav1.ObjectMeta{
 					Name:      "test-pool",
@@ -300,11 +494,11 @@ func TestInferencePoolConvertFrom(t *testing.T) {
 			wantErr: false,
 		},
 		{
-			name: "conversion from v1 to v1alpha2 with empty extensionRef",
+			name: "conversion from v1 to v1alpha2 with empty extensionRef and nil status condition",
 			src: &v1.InferencePool{
 				TypeMeta: metav1.TypeMeta{
 					Kind:       "InferencePool",
-					APIVersion: "inference.networking.k8s.io/v1",
+					APIVersion: v1.GroupVersion.String(),
 				},
 				ObjectMeta: metav1.ObjectMeta{
 					Name:      "test-pool",
@@ -319,17 +513,62 @@ func TestInferencePoolConvertFrom(t *testing.T) {
 					TargetPorts: []v1.Port{{Number: v1.PortNumber(int32(8080))}},
 				},
 				Status: v1.InferencePoolStatus{
-					Parents: []v1.PoolStatus{
+					Parents: []v1.ParentStatus{
 						{
-							GatewayRef: v1.ParentGatewayReference{Name: "my-gateway"},
-							Conditions: []metav1.Condition{
-								{
-									Type:               string(v1.InferencePoolConditionAccepted),
-									Status:             metav1.ConditionTrue,
-									Reason:             string(v1.InferencePoolReasonAccepted),
-									LastTransitionTime: timestamp,
-								},
-							},
+							ParentRef: v1.ParentReference{Name: "my-gateway"},
+						},
+					},
+				},
+			},
+			want: &InferencePool{
+				TypeMeta: metav1.TypeMeta{
+					Kind:       "InferencePool",
+					APIVersion: GroupVersion.String(),
+				},
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "test-pool",
+					Namespace: "test-ns",
+				},
+				Spec: InferencePoolSpec{
+					Selector: map[LabelKey]LabelValue{
+						"app": "my-model-server",
+					},
+					TargetPortNumber: 8080,
+				},
+				Status: InferencePoolStatus{
+					Parents: []PoolStatus{
+						{
+							GatewayRef: ParentGatewayReference{Name: "my-gateway"},
+						},
+					},
+				},
+			},
+			wantErr: false,
+		},
+		{
+			name: "conversion from v1 to v1alpha2 with empty extensionRef and empty status condition",
+			src: &v1.InferencePool{
+				TypeMeta: metav1.TypeMeta{
+					Kind:       "InferencePool",
+					APIVersion: v1.GroupVersion.String(),
+				},
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "test-pool",
+					Namespace: "test-ns",
+				},
+				Spec: v1.InferencePoolSpec{
+					Selector: v1.LabelSelector{
+						MatchLabels: map[v1.LabelKey]v1.LabelValue{
+							"app": "my-model-server",
+						},
+					},
+					TargetPorts: []v1.Port{{Number: v1.PortNumber(int32(8080))}},
+				},
+				Status: v1.InferencePoolStatus{
+					Parents: []v1.ParentStatus{
+						{
+							ParentRef:  v1.ParentReference{Name: "my-gateway"},
+							Conditions: []metav1.Condition{},
 						},
 					},
 				},
@@ -337,7 +576,7 @@ func TestInferencePoolConvertFrom(t *testing.T) {
 			want: &InferencePool{
 				TypeMeta: metav1.TypeMeta{
 					Kind:       "InferencePool",
-					APIVersion: "inference.networking.k8s.io/v1",
+					APIVersion: GroupVersion.String(),
 				},
 				ObjectMeta: metav1.ObjectMeta{
 					Name:      "test-pool",
@@ -353,11 +592,67 @@ func TestInferencePoolConvertFrom(t *testing.T) {
 					Parents: []PoolStatus{
 						{
 							GatewayRef: ParentGatewayReference{Name: "my-gateway"},
+							Conditions: nil, // Conditions omitted because the converter leaves it nil when v1 had [].
+
+						},
+					},
+				},
+			},
+			wantErr: false,
+		},
+		{
+			name: "v1 -> v1alpha2 maps NotSupportedByParent to NotSupportedByGateway",
+			src: &v1.InferencePool{
+				TypeMeta: metav1.TypeMeta{
+					Kind:       "InferencePool",
+					APIVersion: v1.GroupVersion.String(),
+				},
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "pool",
+					Namespace: "ns",
+				},
+				Spec: v1.InferencePoolSpec{
+					Selector:    v1.LabelSelector{MatchLabels: map[v1.LabelKey]v1.LabelValue{"app": "m"}},
+					TargetPorts: []v1.Port{{Number: v1.PortNumber(8080)}},
+				},
+				Status: v1.InferencePoolStatus{
+					Parents: []v1.ParentStatus{
+						{
+							ParentRef: v1.ParentReference{Name: "gw"},
+							Conditions: []metav1.Condition{
+								{
+									Type:               string(v1.InferencePoolConditionAccepted),
+									Status:             metav1.ConditionFalse,
+									Reason:             string(v1.InferencePoolReasonNotSupportedByParent),
+									LastTransitionTime: timestamp,
+								},
+							},
+						},
+					},
+				},
+			},
+			want: &InferencePool{
+				TypeMeta: metav1.TypeMeta{
+					Kind:       "InferencePool",
+					APIVersion: GroupVersion.String(),
+				},
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "pool",
+					Namespace: "ns",
+				},
+				Spec: InferencePoolSpec{
+					Selector:         map[LabelKey]LabelValue{"app": "m"},
+					TargetPortNumber: 8080,
+				},
+				Status: InferencePoolStatus{
+					Parents: []PoolStatus{
+						{
+							GatewayRef: ParentGatewayReference{Name: "gw"},
 							Conditions: []metav1.Condition{
 								{
 									Type:               string(InferencePoolConditionAccepted),
-									Status:             metav1.ConditionTrue,
-									Reason:             string(InferencePoolReasonAccepted),
+									Status:             metav1.ConditionFalse,
+									Reason:             string(InferencePoolReasonNotSupportedByGateway),
 									LastTransitionTime: timestamp,
 								},
 							},
diff --git a/pkg/epp/flowcontrol/registry/config_test.go b/pkg/epp/flowcontrol/registry/config_test.go
index 0cf9f93..376282f 100644
--- a/pkg/epp/flowcontrol/registry/config_test.go
+++ b/pkg/epp/flowcontrol/registry/config_test.go
@@ -18,7 +18,9 @@ package registry
 
 import (
 	"errors"
+	"fmt"
 	"testing"
+	"time"
 
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
@@ -27,120 +29,147 @@ import (
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/mocks"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/plugins/policies/interflow/dispatch/besthead"
-	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/plugins/policies/interflow/dispatch/roundrobin"
 	intra "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/plugins/policies/intraflow/dispatch"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/plugins/policies/intraflow/dispatch/fcfs"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/plugins/queue"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/plugins/queue/listqueue"
 )
 
-func TestConfig_ValidateAndApplyDefaults(t *testing.T) {
+func TestConfig_NewConfig(t *testing.T) {
 	t.Parallel()
 
-	// Setup for failure injection tests
-	failingPolicyName := intra.RegisteredPolicyName("failing-policy-for-config-test")
-	intra.MustRegisterPolicy(failingPolicyName, func() (framework.IntraFlowDispatchPolicy, error) {
-		return nil, errors.New("policy instantiation failed")
-	})
-	failingQueueName := queue.RegisteredQueueName("failing-queue-for-config-test")
-	queue.MustRegisterQueue(failingQueueName, func(_ framework.ItemComparator) (framework.SafeQueue, error) {
-		return nil, errors.New("queue instantiation failed")
-	})
-
-	// Setup a mock policy with a specific capability requirement to test the compatibility check.
-	const mockCapability = framework.QueueCapability("TEST_CAPABILITY_FOR_CONFIG")
-	policyWithReqName := intra.RegisteredPolicyName("policy-with-req-for-config-test")
-	intra.MustRegisterPolicy(policyWithReqName, func() (framework.IntraFlowDispatchPolicy, error) {
-		return &mocks.MockIntraFlowDispatchPolicy{
-			NameV: string(policyWithReqName),
-			RequiredQueueCapabilitiesV: []framework.QueueCapability{
-				mockCapability,
-			},
-		}, nil
-	})
-
 	testCases := []struct {
 		name          string
-		input         *Config
+		input         Config
+		opts          []configOption
 		expectErr     bool
 		expectedErrIs error
-		expectedCfg   *Config
+		assertion     func(*testing.T, Config, *Config)
 	}{
+		// --- Success Paths ---
 		{
-			name: "Valid config with missing defaults",
-			input: &Config{
+			name: "ShouldApplyDefaults_WhenFieldsAreUnspecified",
+			input: Config{
 				PriorityBands: []PriorityBandConfig{
 					{Priority: 1, PriorityName: "High"},
-					{Priority: 2, PriorityName: "Low", InterFlowDispatchPolicy: roundrobin.RoundRobinPolicyName},
+					{Priority: 2, PriorityName: "Low", MaxBytes: 500},
 				},
 			},
-			expectErr: false,
-			expectedCfg: &Config{
-				PriorityBands: []PriorityBandConfig{
-					{
-						Priority:                1,
-						PriorityName:            "High",
-						IntraFlowDispatchPolicy: fcfs.FCFSPolicyName,
-						InterFlowDispatchPolicy: besthead.BestHeadPolicyName,
-						Queue:                   listqueue.ListQueueName,
-					},
-					{
-						Priority:                2,
-						PriorityName:            "Low",
-						IntraFlowDispatchPolicy: fcfs.FCFSPolicyName,
-						InterFlowDispatchPolicy: roundrobin.RoundRobinPolicyName,
-						Queue:                   listqueue.ListQueueName,
-					},
-				},
+			assertion: func(t *testing.T, _ Config, newCfg *Config) {
+				assert.Equal(t, defaultInitialShardCount, newCfg.InitialShardCount, "InitialShardCount should be defaulted")
+				assert.Equal(t, defaultFlowGCTimeout, newCfg.FlowGCTimeout, "FlowGCTimeout should be defaulted")
+				assert.Equal(t, defaultEventChannelBufferSize, newCfg.EventChannelBufferSize,
+					"EventChannelBufferSize should be defaulted")
+				require.Len(t, newCfg.PriorityBands, 2, "Should have two priority bands")
+				band1 := newCfg.PriorityBands[0]
+				assert.Equal(t, defaultIntraFlowDispatchPolicy, band1.IntraFlowDispatchPolicy,
+					"Band 1 IntraFlowDispatchPolicy should be defaulted")
+				assert.Equal(t, defaultInterFlowDispatchPolicy, band1.InterFlowDispatchPolicy,
+					"Band 1 InterFlowDispatchPolicy should be defaulted")
+				assert.Equal(t, defaultQueue, band1.Queue, "Band 1 Queue should be defaulted")
+				assert.Equal(t, defaultPriorityBandMaxBytes, band1.MaxBytes, "Band 1 MaxBytes should be defaulted")
+				band2 := newCfg.PriorityBands[1]
+				assert.Equal(t, uint64(500), band2.MaxBytes, "Band 2 MaxBytes should retain its specified value")
 			},
 		},
 		{
-			name: "Config with all fields specified and compatible",
-			input: &Config{
-				MaxBytes: 1000,
-				PriorityBands: []PriorityBandConfig{
-					{
-						Priority:                1,
-						PriorityName:            "High",
-						IntraFlowDispatchPolicy: fcfs.FCFSPolicyName, // Compatible with ListQueue
-						InterFlowDispatchPolicy: besthead.BestHeadPolicyName,
-						Queue:                   listqueue.ListQueueName,
-						MaxBytes:                500,
-					},
-				},
+			name: "ShouldRemainUnchanged_WhenConfigIsFullySpecifiedAndValid",
+			input: Config{
+				MaxBytes:               1000,
+				InitialShardCount:      10,
+				FlowGCTimeout:          10 * time.Minute,
+				EventChannelBufferSize: 5000,
+				PriorityBands: []PriorityBandConfig{{
+					Priority:                1,
+					PriorityName:            "Critical",
+					IntraFlowDispatchPolicy: fcfs.FCFSPolicyName,
+					InterFlowDispatchPolicy: besthead.BestHeadPolicyName,
+					Queue:                   listqueue.ListQueueName,
+					MaxBytes:                500,
+				}},
+			},
+			assertion: func(t *testing.T, originalCfg Config, newCfg *Config) {
+				assert.Equal(t, originalCfg.MaxBytes, newCfg.MaxBytes, "MaxBytes should remain unchanged")
+				assert.Equal(t, originalCfg.InitialShardCount, newCfg.InitialShardCount,
+					"InitialShardCount should remain unchanged")
+				assert.Equal(t, originalCfg.FlowGCTimeout, newCfg.FlowGCTimeout, "FlowGCTimeout should remain unchanged")
+				assert.Equal(t, originalCfg.EventChannelBufferSize, newCfg.EventChannelBufferSize,
+					"EventChannelBufferSize should remain unchanged")
+				assert.Equal(t, originalCfg.PriorityBands, newCfg.PriorityBands, "PriorityBands should remain unchanged")
+			},
+		},
+		{
+			name: "ShouldSucceed_WhenPolicyHasNoRequirements",
+			input: Config{
+				PriorityBands: []PriorityBandConfig{{
+					Priority:                1,
+					PriorityName:            "High",
+					IntraFlowDispatchPolicy: intra.RegisteredPolicyName("policy-without-req"),
+				}},
+			},
+			opts: []configOption{
+				withIntraFlowDispatchPolicyFactory(
+					func(_ intra.RegisteredPolicyName) (framework.IntraFlowDispatchPolicy, error) {
+						return &mocks.MockIntraFlowDispatchPolicy{
+							NameV:                      "policy-without-req",
+							RequiredQueueCapabilitiesV: []framework.QueueCapability{},
+						}, nil
+					}),
 			},
 			expectErr: false,
-			expectedCfg: &Config{ // Should be unchanged
-				MaxBytes: 1000,
-				PriorityBands: []PriorityBandConfig{
-					{
-						Priority:                1,
-						PriorityName:            "High",
-						IntraFlowDispatchPolicy: fcfs.FCFSPolicyName,
-						InterFlowDispatchPolicy: besthead.BestHeadPolicyName,
-						Queue:                   listqueue.ListQueueName,
-						MaxBytes:                500,
-					},
-				},
+		},
+		{
+			name: "ShouldSucceed_WhenPolicyAndQueueAreCompatible",
+			input: Config{
+				PriorityBands: []PriorityBandConfig{{
+					Priority:                1,
+					PriorityName:            "High",
+					IntraFlowDispatchPolicy: intra.RegisteredPolicyName("policy-with-reqs"),
+					Queue:                   queue.RegisteredQueueName("queue-with-reqs-capability"),
+				}},
+			},
+			opts: []configOption{
+				withIntraFlowDispatchPolicyFactory(
+					func(_ intra.RegisteredPolicyName) (framework.IntraFlowDispatchPolicy, error) {
+						return &mocks.MockIntraFlowDispatchPolicy{
+							RequiredQueueCapabilitiesV: []framework.QueueCapability{"capability-A", "capability-B"},
+						}, nil
+					}),
+				withQueueFactory(
+					func(_ queue.RegisteredQueueName, _ framework.ItemComparator) (framework.SafeQueue, error) {
+						return &mocks.MockSafeQueue{
+							CapabilitiesV: []framework.QueueCapability{"capability-A", "capability-B", "capability-C"},
+						}, nil
+					}),
+			},
+			expectErr: false,
+		},
+		// --- Core Behavioral Contracts ---
+		{
+			name: "ShouldReturnDeepCopy_AndNotMutateInput",
+			input: Config{
+				PriorityBands: []PriorityBandConfig{{Priority: 1, PriorityName: "High"}},
+			},
+			assertion: func(t *testing.T, originalCfg Config, newCfg *Config) {
+				newCfg.PriorityBands[0].PriorityName = "changed"
+				assert.NotEqual(t, originalCfg.PriorityBands[0].PriorityName, newCfg.PriorityBands[0].PriorityName,
+					"Original config should not be mutated by changes to the new config")
 			},
 		},
+		// --- Input Validation Errors ---
 		{
-			name:      "Error: No priority bands",
-			input:     &Config{PriorityBands: []PriorityBandConfig{}},
+			name:      "ShouldError_WhenNoPriorityBandsAreDefined",
+			input:     Config{PriorityBands: []PriorityBandConfig{}},
 			expectErr: true,
 		},
 		{
-			name: "Error: Missing PriorityName",
-			input: &Config{
-				PriorityBands: []PriorityBandConfig{
-					{Priority: 1},
-				},
-			},
+			name:      "ShouldError_WhenPriorityNameIsMissing",
+			input:     Config{PriorityBands: []PriorityBandConfig{{Priority: 1}}},
 			expectErr: true,
 		},
 		{
-			name: "Error: Duplicate priority level",
-			input: &Config{
+			name: "ShouldError_WhenPriorityLevelsAreDuplicated",
+			input: Config{
 				PriorityBands: []PriorityBandConfig{
 					{Priority: 1, PriorityName: "High"},
 					{Priority: 1, PriorityName: "Also High"},
@@ -149,62 +178,118 @@ func TestConfig_ValidateAndApplyDefaults(t *testing.T) {
 			expectErr: true,
 		},
 		{
-			name: "Error: Incompatible policy and queue",
-			input: &Config{
+			name: "ShouldError_WhenPriorityNamesAreDuplicated",
+			input: Config{
 				PriorityBands: []PriorityBandConfig{
-					{
-						Priority:                1,
-						PriorityName:            "High",
-						IntraFlowDispatchPolicy: policyWithReqName,       // Requires mock capability
-						Queue:                   listqueue.ListQueueName, // Does not provide it
-					},
+					{Priority: 1, PriorityName: "High"},
+					{Priority: 2, PriorityName: "High"},
 				},
 			},
+			expectErr: true,
+		},
+		// --- Plugin and Compatibility Errors ---
+		{
+			name: "ShouldError_WhenPolicyAndQueueAreIncompatible",
+			input: Config{
+				PriorityBands: []PriorityBandConfig{{
+					Priority:                1,
+					PriorityName:            "High",
+					IntraFlowDispatchPolicy: intra.RegisteredPolicyName("policy-with-req"),
+					Queue:                   listqueue.ListQueueName,
+				}},
+			},
+			opts: []configOption{withIntraFlowDispatchPolicyFactory(
+				func(_ intra.RegisteredPolicyName) (framework.IntraFlowDispatchPolicy, error) {
+					return &mocks.MockIntraFlowDispatchPolicy{
+						RequiredQueueCapabilitiesV: []framework.QueueCapability{framework.QueueCapability("required-capability")},
+					}, nil
+				})},
 			expectErr:     true,
 			expectedErrIs: contracts.ErrPolicyQueueIncompatible,
 		},
 		{
-			name: "Error: Failing policy instantiation",
-			input: &Config{
-				PriorityBands: []PriorityBandConfig{
-					{
-						Priority:                1,
-						PriorityName:            "High",
-						IntraFlowDispatchPolicy: failingPolicyName,
-						Queue:                   listqueue.ListQueueName,
-					},
-				},
+			name: "ShouldError_WhenQueueFactoryFails",
+			input: Config{
+				PriorityBands: []PriorityBandConfig{{
+					Priority:     1,
+					PriorityName: "High",
+					Queue:        queue.RegisteredQueueName("failing-queue"),
+				}},
 			},
 			expectErr: true,
+			opts: []configOption{withQueueFactory(
+				func(_ queue.RegisteredQueueName, _ framework.ItemComparator) (framework.SafeQueue, error) {
+					return nil, errors.New("queue creation failed")
+				})},
 		},
 		{
-			name: "Error: Failing queue instantiation",
-			input: &Config{
-				PriorityBands: []PriorityBandConfig{
-					{
-						Priority:                1,
-						PriorityName:            "High",
-						IntraFlowDispatchPolicy: fcfs.FCFSPolicyName,
-						Queue:                   failingQueueName,
-					},
-				},
+			name: "ShouldError_WhenPolicyFactoryFails",
+			input: Config{
+				PriorityBands: []PriorityBandConfig{{
+					Priority:                1,
+					PriorityName:            "High",
+					IntraFlowDispatchPolicy: intra.RegisteredPolicyName("failing-policy"),
+				}},
 			},
+			opts: []configOption{withIntraFlowDispatchPolicyFactory(
+				func(_ intra.RegisteredPolicyName) (framework.IntraFlowDispatchPolicy, error) {
+					return nil, errors.New("policy creation failed")
+				})},
 			expectErr: true,
 		},
+		// --- Defaulting of Invalid Values ---
+		{
+			name: "ShouldApplyDefault_WhenInitialShardCountIsInvalid",
+			input: Config{
+				InitialShardCount: -1,
+				PriorityBands:     []PriorityBandConfig{{Priority: 1, PriorityName: "High"}},
+			},
+			assertion: func(t *testing.T, _ Config, newCfg *Config) {
+				assert.Equal(t, defaultInitialShardCount, newCfg.InitialShardCount,
+					"Invalid InitialShardCount should be corrected to the default")
+			},
+		},
+		{
+			name: "ShouldApplyDefault_WhenFlowGCTimeoutIsInvalid",
+			input: Config{
+				FlowGCTimeout: 0,
+				PriorityBands: []PriorityBandConfig{{Priority: 1, PriorityName: "High"}},
+			},
+			assertion: func(t *testing.T, _ Config, newCfg *Config) {
+				assert.Equal(t, defaultFlowGCTimeout, newCfg.FlowGCTimeout,
+					"Invalid FlowGCTimeout should be corrected to the default")
+			},
+		},
+		{
+			name: "ShouldApplyDefault_WhenEventChannelBufferSizeIsInvalid",
+			input: Config{
+				EventChannelBufferSize: -1,
+				PriorityBands:          []PriorityBandConfig{{Priority: 1, PriorityName: "High"}},
+			},
+			assertion: func(t *testing.T, _ Config, newCfg *Config) {
+				assert.Equal(t, defaultEventChannelBufferSize, newCfg.EventChannelBufferSize,
+					"Invalid EventChannelBufferSize should be corrected to the default")
+			},
+		},
 	}
 
 	for _, tc := range testCases {
 		t.Run(tc.name, func(t *testing.T) {
 			t.Parallel()
-			err := tc.input.validateAndApplyDefaults()
+			originalInputCopy := tc.input.deepCopy()
+			newCfg, err := NewConfig(tc.input, tc.opts...)
 			if tc.expectErr {
-				require.Error(t, err, "Expected an error for this test case")
+				require.Error(t, err, "NewConfig should have returned an error")
 				if tc.expectedErrIs != nil {
-					assert.ErrorIs(t, err, tc.expectedErrIs, "Error should be of the expected type")
+					assert.ErrorIs(t, err, tc.expectedErrIs, "Error should wrap the expected error type")
 				}
+				assert.Nil(t, newCfg, "On error, the returned config should be nil")
 			} else {
-				require.NoError(t, err, "Did not expect an error for this test case")
-				assert.Equal(t, tc.expectedCfg, tc.input, "Config after applying defaults does not match expected config")
+				require.NoError(t, err, "NewConfig should not have returned an error")
+				require.NotNil(t, newCfg, "On success, the returned config should not be nil")
+				if tc.assertion != nil {
+					tc.assertion(t, *originalInputCopy, newCfg)
+				}
 			}
 		})
 	}
@@ -212,81 +297,201 @@ func TestConfig_ValidateAndApplyDefaults(t *testing.T) {
 
 func TestConfig_Partition(t *testing.T) {
 	t.Parallel()
-
-	baseConfig := &Config{
-		MaxBytes: 103,
+	baseCfg, err := NewConfig(Config{
+		MaxBytes: 103, // Will not distribute evenly
 		PriorityBands: []PriorityBandConfig{
-			{Priority: 1, PriorityName: "High", MaxBytes: 55},
-			{Priority: 2, PriorityName: "Low", MaxBytes: 0}, // Should remain 0
+			{Priority: 1, PriorityName: "High", MaxBytes: 55}, // Will not distribute evenly
+			{Priority: 2, PriorityName: "Low", MaxBytes: 0},   // Will be defaulted to 1,000,000,000
+			{Priority: 3, PriorityName: "Mid", MaxBytes: 20},  // Will distribute evenly
 		},
-	}
+	})
+	require.NoError(t, err, "Test setup: creating the base config should not fail")
 
-	t.Run("EvenDistributionWithRemainder", func(t *testing.T) {
+	t.Run("ShouldDistributeWithRemainderCorrectly", func(t *testing.T) {
 		t.Parallel()
 		totalShards := 10
-		// Global: 103 / 10 = 10 remainder 3. First 3 shards get 11, rest get 10.
-		// Band 1: 55 / 10 = 5 remainder 5. First 5 shards get 6, rest get 5.
+		// Global: 103 / 10 = 10 rem 3. First 3 shards get 11, rest get 10.
+		// Band 1: 55 / 10 = 5 rem 5. First 5 shards get 6, rest get 5.
+		// Band 2 (defaulted): 1,000,000,000 / 10 = 100,000,000 for all shards.
+		// Band 3: 20 / 10 = 2 rem 0. All shards get 2.
 		expectedGlobalBytes := []uint64{11, 11, 11, 10, 10, 10, 10, 10, 10, 10}
 		expectedBand1Bytes := []uint64{6, 6, 6, 6, 6, 5, 5, 5, 5, 5}
 
-		var totalGlobal, totalBand1 uint64
+		var totalGlobal, totalBand1, totalBand2, totalBand3 uint64
 		for i := range totalShards {
-			partitioned, err := baseConfig.partition(i, totalShards)
-			require.NoError(t, err, "Partitioning should not fail for shard %d", i)
-			assert.Equal(t, expectedGlobalBytes[i], partitioned.MaxBytes, "Global MaxBytes for shard %d is incorrect", i)
-			require.Len(t, partitioned.PriorityBands, 2, "Partitioned config should have the same number of bands")
-			assert.Equal(t, expectedBand1Bytes[i], partitioned.PriorityBands[0].MaxBytes,
+			shardCfg := baseCfg.partition(i, totalShards)
+			require.NotNil(t, shardCfg, "Partitioned config for shard %d should not be nil", i)
+			assert.Equal(t, expectedGlobalBytes[i], shardCfg.MaxBytes, "Global MaxBytes for shard %d is incorrect", i)
+			require.Len(t, shardCfg.PriorityBands, 3, "Partitioned config should have 3 bands")
+			assert.Equal(t, expectedBand1Bytes[i], shardCfg.PriorityBands[0].MaxBytes,
 				"Band 1 MaxBytes for shard %d is incorrect", i)
-			assert.Zero(t, partitioned.PriorityBands[1].MaxBytes, "Band 2 MaxBytes should remain zero for shard %d", i)
-			totalGlobal += partitioned.MaxBytes
-			totalBand1 += partitioned.PriorityBands[0].MaxBytes
+
+			expectedBand2Bytes := defaultPriorityBandMaxBytes / uint64(totalShards)
+			assert.Equal(t, expectedBand2Bytes, shardCfg.PriorityBands[1].MaxBytes,
+				"Band 2 MaxBytes for shard %d is incorrect", i)
+			assert.Equal(t, uint64(2), shardCfg.PriorityBands[2].MaxBytes,
+				"Band 3 MaxBytes for shard %d is incorrect", i)
+
+			totalGlobal += shardCfg.MaxBytes
+			totalBand1 += shardCfg.PriorityBands[0].MaxBytes
+			totalBand2 += shardCfg.PriorityBands[1].MaxBytes
+			totalBand3 += shardCfg.PriorityBands[2].MaxBytes
 		}
-		assert.Equal(t, baseConfig.MaxBytes, totalGlobal, "Sum of partitioned global MaxBytes should equal original")
-		assert.Equal(t, baseConfig.PriorityBands[0].MaxBytes, totalBand1,
+		assert.Equal(t, baseCfg.MaxBytes, totalGlobal, "Sum of partitioned global MaxBytes should equal original")
+		assert.Equal(t, baseCfg.PriorityBands[0].MaxBytes, totalBand1,
 			"Sum of partitioned band 1 MaxBytes should equal original")
+		assert.Equal(t, defaultPriorityBandMaxBytes, totalBand2,
+			"Sum of partitioned band 2 MaxBytes should equal the default value")
+		assert.Equal(t, baseCfg.PriorityBands[2].MaxBytes, totalBand3,
+			"Sum of partitioned band 3 MaxBytes should equal original")
 	})
 
-	t.Run("SingleShard", func(t *testing.T) {
+	t.Run("ShouldHandleSingleShard", func(t *testing.T) {
 		t.Parallel()
-		partitioned, err := baseConfig.partition(0, 1)
-		require.NoError(t, err, "Partitioning for a single shard should not fail")
-		assert.Equal(t, baseConfig.MaxBytes, partitioned.MaxBytes, "Global MaxBytes should be unchanged for a single shard")
-		require.Len(t, partitioned.PriorityBands, 2, "Partitioned config should have the same number of bands")
-		assert.Equal(t, baseConfig.PriorityBands[0].MaxBytes, partitioned.PriorityBands[0].MaxBytes,
-			"Band 1 MaxBytes should be unchanged for a single shard")
-	})
-
-	t.Run("EmptyPriorityBands", func(t *testing.T) {
-		t.Parallel()
-		config := &Config{
-			MaxBytes:      100,
-			PriorityBands: []PriorityBandConfig{},
-		}
-		partitioned, err := config.partition(1, 3)
-		require.NoError(t, err, "Partitioning should not fail for empty priority bands")
-		assert.Equal(t, uint64(33), partitioned.MaxBytes, "Global MaxBytes should be partitioned correctly")
-		assert.Empty(t, partitioned.PriorityBands, "PriorityBands slice should be empty")
-		assert.NotNil(t, partitioned.PriorityBands, "PriorityBands slice should not be nil")
+		shardCfg := baseCfg.partition(0, 1)
+		require.NotNil(t, shardCfg, "Partitioned config for single shard should not be nil")
+		assert.Equal(t, baseCfg.MaxBytes, shardCfg.MaxBytes, "Global MaxBytes should be unchanged for a single shard")
+		require.Len(t, shardCfg.PriorityBands, 3, "Partitioned config should have 3 bands")
+		assert.Equal(t, baseCfg.PriorityBands[0].MaxBytes, shardCfg.PriorityBands[0].MaxBytes,
+			"Band 1 MaxBytes should be unchanged")
 	})
 
-	t.Run("ErrorHandling", func(t *testing.T) {
+	t.Run("ShouldPanic_WhenTotalShardsIsInvalid", func(t *testing.T) {
 		t.Parallel()
 		testCases := []struct {
 			name        string
-			shardIndex  int
 			totalShards int
 		}{
-			{"NegativeShardIndex", -1, 5},
-			{"ShardIndexOutOfBounds", 5, 5},
-			{"ZeroTotalShards", 0, 0},
-			{"NegativeTotalShards", 0, -1},
+			{"ZeroShards", 0},
+			{"NegativeShards", -1},
 		}
+
 		for _, tc := range testCases {
 			t.Run(tc.name, func(t *testing.T) {
 				t.Parallel()
-				_, err := baseConfig.partition(tc.shardIndex, tc.totalShards)
-				assert.Error(t, err, "Expected an error for invalid partitioning arguments")
+				assert.PanicsWithValue(t,
+					fmt.Sprintf("invariant violation: cannot partition into %d partitions", tc.totalShards),
+					func() { baseCfg.partition(0, tc.totalShards) },
+					"Should panic with a specific message when totalShards is not positive",
+				)
 			})
 		}
 	})
 }
+
+func TestConfig_GetBandConfig(t *testing.T) {
+	t.Parallel()
+	cfg, err := NewConfig(Config{
+		PriorityBands: []PriorityBandConfig{
+			{Priority: 10, PriorityName: "High"},
+		},
+	})
+	require.NoError(t, err, "Test setup: creating the config should not fail")
+
+	t.Run("ShouldReturnCorrectConfig_ForExistingPriority", func(t *testing.T) {
+		t.Parallel()
+		bandCfg, err := cfg.getBandConfig(10)
+		require.NoError(t, err, "Should not error for an existing priority")
+		require.NotNil(t, bandCfg, "Returned band config should not be nil")
+		assert.Equal(t, "High", bandCfg.PriorityName, "Should return the correct band config")
+	})
+
+	t.Run("ShouldReturnError_ForNonExistentPriority", func(t *testing.T) {
+		t.Parallel()
+		_, err := cfg.getBandConfig(99)
+		assert.ErrorIs(t, err, contracts.ErrPriorityBandNotFound, "Error should wrap ErrPriorityBandNotFound")
+	})
+}
+
+func TestConfig_DeepCopy(t *testing.T) {
+	t.Parallel()
+
+	baseCfg := Config{
+		MaxBytes:               1000,
+		InitialShardCount:      5,
+		FlowGCTimeout:          10 * time.Minute,
+		EventChannelBufferSize: 2048,
+		PriorityBands: []PriorityBandConfig{
+			{Priority: 1, PriorityName: "A"},
+			{Priority: 2, PriorityName: "B"},
+		},
+	}
+	// Create a fully initialized "original" config to be the source of the copy.
+	original, err := NewConfig(baseCfg)
+	require.NoError(t, err, "Setup for deep copy should not fail")
+
+	t.Run("ShouldReturnNil_ForNilReceiver", func(t *testing.T) {
+		t.Parallel()
+		var nilConfig *Config
+		assert.Nil(t, nilConfig.deepCopy(), "Deep copy of a nil config should be nil")
+	})
+
+	t.Run("ShouldCreateIdenticalButSeparateObject", func(t *testing.T) {
+		t.Parallel()
+		clone := original.deepCopy()
+
+		// Assert that the clone is not the same object in memory.
+		require.NotSame(t, original, clone, "Clone should be a new object in memory")
+		require.NotSame(t, &original.PriorityBands, &clone.PriorityBands, "PriorityBands slice should be a new object")
+		require.NotSame(t, &original.priorityBandMap, &clone.priorityBandMap, "priorityBandMap should be a new object")
+		assert.Equal(t, original.MaxBytes, clone.MaxBytes, "MaxBytes should be copied")
+		assert.Equal(t, original.InitialShardCount, clone.InitialShardCount, "InitialShardCount should be copied")
+		assert.Equal(t, original.FlowGCTimeout, clone.FlowGCTimeout, "FlowGCTimeout should be copied")
+		assert.Equal(t, original.EventChannelBufferSize, clone.EventChannelBufferSize,
+			"EventChannelBufferSize should be copied")
+		assert.Equal(t, original.PriorityBands, clone.PriorityBands, "PriorityBands should be deeply copied")
+	})
+
+	t.Run("ShouldBeIndependent_AfterCopying", func(t *testing.T) {
+		t.Parallel()
+		clone := original.deepCopy()
+
+		// Modify the clone
+		clone.MaxBytes = 2000
+		clone.PriorityBands[0].PriorityName = "modified"
+		// This modification through the map should also modify the slice element, as the map holds pointers.
+		clone.priorityBandMap[clone.PriorityBands[0].Priority].PriorityName = "modified-in-map"
+		clone.queueFactory = func(_ queue.RegisteredQueueName, _ framework.ItemComparator) (framework.SafeQueue, error) {
+			return nil, nil
+		}
+
+		// Assert that the original remains unchanged by comparing field by field for clarity.
+		assert.Equal(t, uint64(1000), original.MaxBytes, "Original MaxBytes should not be changed")
+		assert.Equal(t, 5, original.InitialShardCount, "Original InitialShardCount should not be changed")
+		assert.Equal(t, "A", original.PriorityBands[0].PriorityName, "Original PriorityBands slice should not be changed")
+		assert.Equal(t, "A", original.priorityBandMap[1].PriorityName, "Original priorityBandMap should not be changed")
+		assert.NotNil(t, original.queueFactory, "Original queueFactory should not be nil")
+
+		// Verify the change was contained to the clone. The final value should be the one set via the map.
+		assert.Equal(t, "modified-in-map", clone.PriorityBands[0].PriorityName,
+			"Clone's slice should reflect the change from the map")
+		assert.Equal(t, "modified-in-map", clone.priorityBandMap[1].PriorityName, "Clone's map should reflect the change")
+	})
+}
+
+func TestShardConfig_GetBandConfig(t *testing.T) {
+	t.Parallel()
+	baseCfg, err := NewConfig(Config{
+		PriorityBands: []PriorityBandConfig{
+			{Priority: 10, PriorityName: "High"},
+			{Priority: 20, PriorityName: "Low"},
+		},
+	})
+	require.NoError(t, err, "Test setup: creating the base config should not fail")
+	shardCfg := baseCfg.partition(0, 2)
+	require.NotNil(t, shardCfg, "Test setup: partitioned config should not be nil")
+
+	t.Run("ShouldReturnCorrectConfig_ForExistingPriority", func(t *testing.T) {
+		t.Parallel()
+		bandCfg, err := shardCfg.getBandConfig(20)
+		require.NoError(t, err, "Should not error for an existing priority")
+		require.NotNil(t, bandCfg, "Returned band config should not be nil")
+		assert.Equal(t, "Low", bandCfg.PriorityName, "Should return the correct partitioned band config")
+	})
+
+	t.Run("ShouldReturnError_ForNonExistentPriority", func(t *testing.T) {
+		t.Parallel()
+		_, err := shardCfg.getBandConfig(99)
+		assert.ErrorIs(t, err, contracts.ErrPriorityBandNotFound, "Error should wrap ErrPriorityBandNotFound")
+	})
+}
diff --git a/pkg/epp/flowcontrol/registry/flowstate_test.go b/pkg/epp/flowcontrol/registry/flowstate_test.go
new file mode 100644
index 0000000..ceedbd5
--- /dev/null
+++ b/pkg/epp/flowcontrol/registry/flowstate_test.go
@@ -0,0 +1,216 @@
+/*
+Copyright 2025 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package registry
+
+import (
+	"fmt"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+
+	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/types"
+)
+
+// fsTestHarness holds all the common components for a `flowState` test.
+type fsTestHarness struct {
+	t         *testing.T
+	fs        *flowState
+	allShards []*registryShard
+}
+
+// newFsTestHarness creates a new test harness, initializing a `flowState` with a default spec and shard layout.
+func newFsTestHarness(t *testing.T) *fsTestHarness {
+	t.Helper()
+
+	spec := types.FlowSpecification{
+		Key: types.FlowKey{ID: "f1", Priority: 10},
+	}
+	// Note: The shards are simple structs for this test, as we only need their IDs.
+	allShards := []*registryShard{{id: "s1"}, {id: "s2"}, {id: "s3-draining"}}
+
+	fs := newFlowState(spec, allShards)
+
+	return &fsTestHarness{
+		t:         t,
+		fs:        fs,
+		allShards: allShards,
+	}
+}
+
+func TestFlowState_New(t *testing.T) {
+	t.Parallel()
+	h := newFsTestHarness(t)
+
+	assert.Equal(t, uint64(0), h.fs.lastActiveGeneration, "Initial lastActiveGeneration should be 0")
+	require.Len(t, h.fs.emptyOnShards, 3, "Should track emptiness status for all initial shards")
+
+	// A new flow instance should be considered empty on all shards by default.
+	assert.True(t, h.fs.emptyOnShards["s1"], "Queue on s1 should start as empty")
+	assert.True(t, h.fs.emptyOnShards["s2"], "Queue on s2 should start as empty")
+	assert.True(t, h.fs.emptyOnShards["s3-draining"], "Queue on s3-draining should start as empty")
+}
+
+func TestFlowState_Update(t *testing.T) {
+	t.Parallel()
+
+	t.Run("ShouldUpdateSpec_WhenKeyIsUnchanged", func(t *testing.T) {
+		t.Parallel()
+		h := newFsTestHarness(t)
+
+		// Create a new spec with the same key but different (hypothetical) content.
+		updatedSpec := types.FlowSpecification{
+			Key: h.fs.spec.Key,
+			// Imagine other fields like per-flow `framework.IntraFlowDispatchPolicy` overrides being added here in the
+			// future.
+		}
+
+		h.fs.update(updatedSpec)
+		assert.Equal(t, updatedSpec, h.fs.spec, "Spec should be updated with new content")
+	})
+
+	t.Run("ShouldPanic_WhenKeyIsChanged", func(t *testing.T) {
+		t.Parallel()
+		h := newFsTestHarness(t)
+
+		invalidSpec := types.FlowSpecification{
+			Key: types.FlowKey{ID: "f1", Priority: 99}, // Different priority
+		}
+
+		assert.PanicsWithValue(t,
+			fmt.Sprintf("invariant violation: attempted to update flowState for key %s with a new key %s",
+				h.fs.spec.Key, invalidSpec.Key),
+			func() { h.fs.update(invalidSpec) },
+			"Should panic when attempting to change the immutable FlowKey",
+		)
+	})
+}
+
+func TestFlowState_HandleQueueSignal(t *testing.T) {
+	t.Parallel()
+
+	testCases := []struct {
+		name          string
+		signal        queueStateSignal
+		initialState  bool
+		expectedState bool
+		message       string
+	}{
+		{
+			name:          "BecameNonEmpty_WhenPreviouslyEmpty",
+			signal:        queueStateSignalBecameNonEmpty,
+			initialState:  true,
+			expectedState: false,
+			message:       "Should mark queue as non-empty (false)",
+		},
+		{
+			name:          "BecameEmpty_WhenPreviouslyNonEmpty",
+			signal:        queueStateSignalBecameEmpty,
+			initialState:  false,
+			expectedState: true,
+			message:       "Should mark queue as empty (true)",
+		},
+	}
+
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			t.Parallel()
+			h := newFsTestHarness(t)
+			shardID := "s1"
+
+			h.fs.emptyOnShards[shardID] = tc.initialState
+			h.fs.handleQueueSignal(shardID, tc.signal)
+			assert.Equal(t, tc.expectedState, h.fs.emptyOnShards[shardID], tc.message)
+		})
+	}
+}
+
+func TestFlowState_IsIdle(t *testing.T) {
+	t.Parallel()
+
+	testCases := []struct {
+		name       string
+		setup      func(h *fsTestHarness)
+		shards     []*registryShard // The set of shards to check for idleness.
+		expectIdle bool
+		message    string
+	}{
+		{
+			name:       "WhenAllShardsAreEmpty",
+			setup:      nil, // Default state is all empty.
+			expectIdle: true,
+			message:    "Should be idle when all tracked queues are empty",
+		},
+		{
+			name: "WhenOneShardIsNonEmpty",
+			setup: func(h *fsTestHarness) {
+				h.fs.handleQueueSignal("s2", queueStateSignalBecameNonEmpty)
+			},
+			expectIdle: false,
+			message:    "Should not be idle if any queue is non-empty",
+		},
+		{
+			name: "WhenADrainingShardIsNonEmpty",
+			setup: func(h *fsTestHarness) {
+				h.fs.handleQueueSignal("s3-draining", queueStateSignalBecameNonEmpty)
+			},
+			expectIdle: false,
+			message:    "Should not be idle if a draining shard's queue is non-empty",
+		},
+		{
+			name: "WhenNonEmptyShardIsNotInCheckedSet",
+			setup: func(h *fsTestHarness) {
+				// The flow is active on a shard that is Draining.
+				h.fs.handleQueueSignal("s3-draining", queueStateSignalBecameNonEmpty)
+			},
+			// But we are only checking the set of Active shards.
+			shards:     []*registryShard{{id: "s1"}, {id: "s2"}},
+			expectIdle: true,
+			message:    "Should be considered idle if the only non-empty queue is on a shard that is not being checked",
+		},
+	}
+
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			t.Parallel()
+			h := newFsTestHarness(t)
+			if tc.setup != nil {
+				tc.setup(h)
+			}
+
+			shardsToCheck := tc.shards
+			if shardsToCheck == nil {
+				shardsToCheck = h.allShards
+			}
+
+			assert.Equal(t, tc.expectIdle, h.fs.isIdle(shardsToCheck), tc.message)
+		})
+	}
+}
+
+func TestFlowState_PurgeShard(t *testing.T) {
+	t.Parallel()
+	h := newFsTestHarness(t)
+	shardToPurge := "s2"
+
+	require.Contains(t, h.fs.emptyOnShards, shardToPurge, "Test setup: shard must exist before purging")
+	h.fs.purgeShard(shardToPurge)
+
+	assert.NotContains(t, h.fs.emptyOnShards, shardToPurge, "Shard should be purged from the tracking map")
+	assert.Contains(t, h.fs.emptyOnShards, "s1", "Other shards should remain in the tracking map")
+	assert.Len(t, h.fs.emptyOnShards, 2, "Map length should be reduced by one")
+}
diff --git a/pkg/epp/flowcontrol/registry/managedqueue_test.go b/pkg/epp/flowcontrol/registry/managedqueue_test.go
index ff73457..0b3d3da 100644
--- a/pkg/epp/flowcontrol/registry/managedqueue_test.go
+++ b/pkg/epp/flowcontrol/registry/managedqueue_test.go
@@ -18,6 +18,7 @@ package registry
 
 import (
 	"errors"
+	"fmt"
 	"sync"
 	"sync/atomic"
 	"testing"
@@ -34,433 +35,551 @@ import (
 	typesmocks "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/types/mocks"
 )
 
-var testFlowKey = types.FlowKey{ID: "test-flow", Priority: 1}
+// --- Test Harness and Mocks ---
 
-// testStatsReconciler is a mock implementation of the `parentStatsReconciler` function.
-// It captures the deltas it's called with, allowing tests to assert on them.
-type testStatsReconciler struct {
-	mu              sync.Mutex
-	lenDelta        int64
-	byteSizeDelta   int64
-	invocationCount int
-}
-
-func (r *testStatsReconciler) reconcile(lenDelta, byteSizeDelta int64) {
-	r.mu.Lock()
-	defer r.mu.Unlock()
-	r.lenDelta += lenDelta
-	r.byteSizeDelta += byteSizeDelta
-	r.invocationCount++
+// mqTestHarness holds all components for testing a `managedQueue`.
+type mqTestHarness struct {
+	t              *testing.T
+	mq             *managedQueue
+	propagator     *mockStatsPropagator
+	signalRecorder *mockQueueStateSignalRecorder
+	mockPolicy     *frameworkmocks.MockIntraFlowDispatchPolicy
 }
 
-func (r *testStatsReconciler) getStats() (lenDelta, byteSizeDelta int64, count int) {
-	r.mu.Lock()
-	defer r.mu.Unlock()
-	return r.lenDelta, r.byteSizeDelta, r.invocationCount
+// newMockedMqHarness creates a harness that uses a mocked underlying queue.
+// This is ideal for isolating and unit testing the decorator logic of `managedQueue`.
+func newMockedMqHarness(t *testing.T, queue *frameworkmocks.MockSafeQueue, key types.FlowKey) *mqTestHarness {
+	t.Helper()
+	return newMqHarness(t, queue, key)
 }
 
-// testFixture holds the components needed for a `managedQueue` test.
-type testFixture struct {
-	mq             *managedQueue
-	mockQueue      *frameworkmocks.MockSafeQueue
-	mockPolicy     *frameworkmocks.MockIntraFlowDispatchPolicy
-	reconciler     *testStatsReconciler
-	flowKey        types.FlowKey
-	mockComparator *frameworkmocks.MockItemComparator
+// newRealMqHarness creates a harness that uses a real "ListQueue" implementation.
+// This is essential for integration and concurrency tests.
+func newRealMqHarness(t *testing.T, key types.FlowKey) *mqTestHarness {
+	t.Helper()
+	q, err := queue.NewQueueFromName(listqueue.ListQueueName, nil)
+	require.NoError(t, err, "Test setup: creating a real ListQueue should not fail")
+	return newMqHarness(t, q, key)
 }
 
-// setupTestManagedQueue creates a new test fixture for testing the `managedQueue`.
-func setupTestManagedQueue(t *testing.T) *testFixture {
+func newMqHarness(t *testing.T, queue framework.SafeQueue, key types.FlowKey) *mqTestHarness {
 	t.Helper()
 
-	mockQueue := &frameworkmocks.MockSafeQueue{}
-	reconciler := &testStatsReconciler{}
-	flowKey := types.FlowKey{ID: "test-flow", Priority: 1}
-	mockComparator := &frameworkmocks.MockItemComparator{}
+	propagator := &mockStatsPropagator{}
+	signalRec := newMockQueueStateSignalRecorder()
 	mockPolicy := &frameworkmocks.MockIntraFlowDispatchPolicy{
-		ComparatorV: mockComparator,
+		ComparatorV: &frameworkmocks.MockItemComparator{},
 	}
 
-	mq := newManagedQueue(
-		mockQueue,
-		mockPolicy,
-		flowKey,
-		logr.Discard(),
-		reconciler.reconcile,
-	)
-	require.NotNil(t, mq, "newManagedQueue should not return nil")
+	callbacks := managedQueueCallbacks{
+		propagateStatsDelta: propagator.propagate,
+		signalQueueState:    signalRec.signal,
+	}
+	mq := newManagedQueue(queue, mockPolicy, key, logr.Discard(), callbacks)
+	require.NotNil(t, mq, "Test setup: newManagedQueue should not return nil")
 
-	return &testFixture{
+	return &mqTestHarness{
+		t:              t,
 		mq:             mq,
-		mockQueue:      mockQueue,
+		propagator:     propagator,
+		signalRecorder: signalRec,
 		mockPolicy:     mockPolicy,
-		reconciler:     reconciler,
-		flowKey:        flowKey,
-		mockComparator: mockComparator,
 	}
 }
 
-func TestManagedQueue_New(t *testing.T) {
-	t.Parallel()
-	f := setupTestManagedQueue(t)
+func (h *mqTestHarness) setupWithItems(items ...types.QueueItemAccessor) {
+	h.t.Helper()
+	for _, item := range items {
+		err := h.mq.Add(item)
+		require.NoError(h.t, err, "Harness setup: failed to add item")
+	}
+	// Reset counters after the setup phase is complete.
+	h.propagator.reset()
+}
+
+// mockStatsPropagator captures stat changes from the system under test.
+type mockStatsPropagator struct {
+	lenDelta      atomic.Int64
+	byteSizeDelta atomic.Int64
+}
 
-	assert.Zero(t, f.mq.Len(), "A new managedQueue should have a length of 0")
-	assert.Zero(t, f.mq.ByteSize(), "A new managedQueue should have a byte size of 0")
+func (p *mockStatsPropagator) propagate(_ uint, lenDelta, byteSizeDelta int64) {
+	p.lenDelta.Add(lenDelta)
+	p.byteSizeDelta.Add(byteSizeDelta)
+}
+
+func (p *mockStatsPropagator) reset() {
+	p.lenDelta.Store(0)
+	p.byteSizeDelta.Store(0)
+}
+
+// mockQueueStateSignalRecorder captures queue state signals from the system under test.
+type mockQueueStateSignalRecorder struct {
+	mu      sync.Mutex
+	signals []queueStateSignal
+}
+
+func newMockQueueStateSignalRecorder() *mockQueueStateSignalRecorder {
+	return &mockQueueStateSignalRecorder{signals: make([]queueStateSignal, 0)}
+}
+
+func (r *mockQueueStateSignalRecorder) signal(_ types.FlowKey, signal queueStateSignal) {
+	r.mu.Lock()
+	defer r.mu.Unlock()
+	r.signals = append(r.signals, signal)
+}
+
+func (r *mockQueueStateSignalRecorder) getSignals() []queueStateSignal {
+	r.mu.Lock()
+	defer r.mu.Unlock()
+	signalsCopy := make([]queueStateSignal, len(r.signals))
+	copy(signalsCopy, r.signals)
+	return signalsCopy
+}
+
+// --- Unit Tests ---
+
+func TestManagedQueue_InitialState(t *testing.T) {
+	t.Parallel()
+	h := newMockedMqHarness(t, &frameworkmocks.MockSafeQueue{}, types.FlowKey{ID: "flow", Priority: 1})
+	assert.Zero(t, h.mq.Len(), "A new queue should have a length of 0")
+	assert.Zero(t, h.mq.ByteSize(), "A new queue should have a byte size of 0")
 }
 
 func TestManagedQueue_Add(t *testing.T) {
 	t.Parallel()
+	flowKey := types.FlowKey{ID: "flow", Priority: 1}
 
 	testCases := []struct {
 		name                  string
-		itemByteSize          uint64
-		mockAddError          error
-		expectError           bool
-		expectedLen           int
-		expectedByteSize      uint64
+		setupMock             func(q *frameworkmocks.MockSafeQueue)
+		expectErr             bool
 		expectedLenDelta      int64
 		expectedByteSizeDelta int64
-		expectedReconcile     bool
 	}{
 		{
-			name:                  "Success",
-			itemByteSize:          100,
-			expectError:           false,
-			expectedLen:           1,
-			expectedByteSize:      100,
+			name: "ShouldSucceed_AndIncrementStats",
+			setupMock: func(q *frameworkmocks.MockSafeQueue) {
+				q.AddFunc = func(types.QueueItemAccessor) error { return nil }
+			},
+			expectErr:             false,
 			expectedLenDelta:      1,
 			expectedByteSizeDelta: 100,
-			expectedReconcile:     true,
 		},
 		{
-			name:                  "Error from underlying queue",
-			itemByteSize:          100,
-			mockAddError:          errors.New("queue full"),
-			expectError:           true,
-			expectedLen:           0,
-			expectedByteSize:      0,
+			name: "ShouldFail_AndNotChangeStats_WhenUnderlyingQueueFails",
+			setupMock: func(q *frameworkmocks.MockSafeQueue) {
+				q.AddFunc = func(types.QueueItemAccessor) error { return errors.New("add failed") }
+			},
+			expectErr:             true,
 			expectedLenDelta:      0,
 			expectedByteSizeDelta: 0,
-			expectedReconcile:     false,
 		},
 	}
 
 	for _, tc := range testCases {
 		t.Run(tc.name, func(t *testing.T) {
 			t.Parallel()
-			f := setupTestManagedQueue(t)
-
-			// Configure mock
-			f.mockQueue.AddFunc = func(item types.QueueItemAccessor) error {
-				return tc.mockAddError
-			}
+			item := typesmocks.NewMockQueueItemAccessor(100, "req", flowKey)
+			q := &frameworkmocks.MockSafeQueue{}
+			tc.setupMock(q)
+			h := newMockedMqHarness(t, q, flowKey)
 
-			item := typesmocks.NewMockQueueItemAccessor(tc.itemByteSize, "req-1", testFlowKey)
-			err := f.mq.Add(item)
+			err := h.mq.Add(item)
 
-			if tc.expectError {
+			if tc.expectErr {
 				require.Error(t, err, "Add should have returned an error")
 			} else {
 				require.NoError(t, err, "Add should not have returned an error")
 			}
-
-			// Assert final state
-			assert.Equal(t, tc.expectedLen, f.mq.Len(), "Final length should be as expected")
-			assert.Equal(t, tc.expectedByteSize, f.mq.ByteSize(), "Final byte size should be as expected")
-
-			// Assert reconciler state
-			lenDelta, byteSizeDelta, count := f.reconciler.getStats()
-			assert.Equal(t, tc.expectedLenDelta, lenDelta, "Reconciler length delta should be as expected")
-			assert.Equal(t, tc.expectedByteSizeDelta, byteSizeDelta, "Reconciler byte size delta should be as expected")
-			if tc.expectedReconcile {
-				assert.Equal(t, 1, count, "Reconciler should have been called once")
-			} else {
-				assert.Zero(t, count, "Reconciler should not have been called")
-			}
+			assert.Equal(t, tc.expectedLenDelta, h.propagator.lenDelta.Load(),
+				"Propagated length delta should be correct")
+			assert.Equal(t, tc.expectedByteSizeDelta, h.propagator.byteSizeDelta.Load(),
+				"Propagated byte size delta should be correct")
 		})
 	}
 }
 
 func TestManagedQueue_Remove(t *testing.T) {
 	t.Parallel()
-	f := setupTestManagedQueue(t)
-
-	// Setup initial state
-	initialItem := typesmocks.NewMockQueueItemAccessor(100, "req-1", testFlowKey)
-	f.mockQueue.AddFunc = func(item types.QueueItemAccessor) error { return nil }
-	err := f.mq.Add(initialItem)
-	require.NoError(t, err, "Setup: Adding an item should not fail")
-	require.Equal(t, 1, f.mq.Len(), "Setup: Length should be 1 after adding an item")
-
-	// --- Test Success ---
-	t.Run("Success", func(t *testing.T) {
-		// Configure mock for Remove
-		f.mockQueue.RemoveFunc = func(handle types.QueueItemHandle) (types.QueueItemAccessor, error) {
-			return initialItem, nil
-		}
+	flowKey := types.FlowKey{ID: "flow", Priority: 1}
 
-		// Perform Remove
-		removedItem, err := f.mq.Remove(initialItem.Handle())
-		require.NoError(t, err, "Remove should not return an error")
-		assert.Equal(t, initialItem, removedItem, "Remove should return the correct item")
-
-		// Assert final state
-		assert.Zero(t, f.mq.Len(), "Length should be 0 after removing the only item")
-		assert.Zero(t, f.mq.ByteSize(), "ByteSize should be 0 after removing the only item")
-
-		// Assert reconciler state
-		lenDelta, byteSizeDelta, count := f.reconciler.getStats()
-		assert.Equal(t, int64(0), lenDelta, "Net length delta should be 0 after add and remove")
-		assert.Equal(t, int64(0), byteSizeDelta, "Net byte size delta should be 0 after add and remove")
-		assert.Equal(t, 2, count, "Reconciler should have been called for both Add and Remove")
-	})
-
-	// --- Test Error ---
-	t.Run("Error", func(t *testing.T) {
-		f := setupTestManagedQueue(t)
-		require.NoError(t, f.mq.Add(initialItem), "Setup: Adding an item should not fail")
-
-		// Configure mock to return an error
-		expectedErr := errors.New("item not found")
-		f.mockQueue.RemoveFunc = func(handle types.QueueItemHandle) (types.QueueItemAccessor, error) {
-			return nil, expectedErr
-		}
+	testCases := []struct {
+		name                  string
+		setupMock             func(q *frameworkmocks.MockSafeQueue, item types.QueueItemAccessor)
+		expectErr             bool
+		expectedLenDelta      int64
+		expectedByteSizeDelta int64
+	}{
+		{
+			name: "ShouldSucceed_AndDecrementStats",
+			setupMock: func(q *frameworkmocks.MockSafeQueue, item types.QueueItemAccessor) {
+				q.RemoveFunc = func(_ types.QueueItemHandle) (types.QueueItemAccessor, error) {
+					return item, nil
+				}
+			},
+			expectErr:             false,
+			expectedLenDelta:      -1,
+			expectedByteSizeDelta: -100,
+		},
+		{
+			name: "ShouldFail_AndNotChangeStats_WhenUnderlyingQueueFails",
+			setupMock: func(q *frameworkmocks.MockSafeQueue, item types.QueueItemAccessor) {
+				q.RemoveFunc = func(_ types.QueueItemHandle) (types.QueueItemAccessor, error) {
+					return nil, errors.New("remove failed")
+				}
+			},
+			expectErr:             true,
+			expectedLenDelta:      0,
+			expectedByteSizeDelta: 0,
+		},
+	}
 
-		_, err := f.mq.Remove(initialItem.Handle())
-		require.ErrorIs(t, err, expectedErr, "Remove should propagate the error")
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			t.Parallel()
+			q := &frameworkmocks.MockSafeQueue{}
+			h := newMockedMqHarness(t, q, flowKey)
+			item := typesmocks.NewMockQueueItemAccessor(100, "req", flowKey)
+			h.setupWithItems(item)
+			tc.setupMock(q, item)
 
-		// Assert state did not change
-		assert.Equal(t, 1, f.mq.Len(), "Length should not change on a failed remove")
-		assert.Equal(t, uint64(100), f.mq.ByteSize(), "ByteSize should not change on a failed remove")
+			_, err := h.mq.Remove(item.Handle())
 
-		// Assert reconciler was not called for the remove
-		_, _, count := f.reconciler.getStats()
-		assert.Equal(t, 1, count, "Reconciler should only have been called for the initial Add")
-	})
+			if tc.expectErr {
+				require.Error(t, err, "Remove should have returned an error")
+			} else {
+				require.NoError(t, err, "Remove should not have returned an error")
+			}
+			assert.Equal(t, tc.expectedLenDelta, h.propagator.lenDelta.Load(), "Propagated length delta should be correct")
+			assert.Equal(t, tc.expectedByteSizeDelta, h.propagator.byteSizeDelta.Load(),
+				"Propagated byte size delta should be correct")
+		})
+	}
 }
 
-func TestManagedQueue_CleanupAndDrain(t *testing.T) {
+func TestManagedQueue_Cleanup(t *testing.T) {
 	t.Parallel()
-	item1 := typesmocks.NewMockQueueItemAccessor(10, "req-1", testFlowKey)
-	item2 := typesmocks.NewMockQueueItemAccessor(20, "req-2", testFlowKey)
-	item3 := typesmocks.NewMockQueueItemAccessor(30, "req-3", testFlowKey)
-
-	// --- Test Cleanup ---
-	t.Run("Cleanup", func(t *testing.T) {
-		t.Parallel()
-		f := setupTestManagedQueue(t)
-		// Add initial items
-		require.NoError(t, f.mq.Add(item1), "Setup: Add item1 should not fail")
-		require.NoError(t, f.mq.Add(item2), "Setup: Add item2 should not fail")
-		require.NoError(t, f.mq.Add(item3), "Setup: Add item3 should not fail")
-		require.Equal(t, 3, f.mq.Len(), "Setup: Initial length should be 3")
-		require.Equal(t, uint64(60), f.mq.ByteSize(), "Setup: Initial byte size should be 60")
-
-		// Configure mock to clean up item2
-		f.mockQueue.CleanupFunc = func(p framework.PredicateFunc) ([]types.QueueItemAccessor, error) {
-			return []types.QueueItemAccessor{item2}, nil
-		}
+	flowKey := types.FlowKey{ID: "flow", Priority: 1}
 
-		cleaned, err := f.mq.Cleanup(func(i types.QueueItemAccessor) bool { return true })
-		require.NoError(t, err, "Cleanup should not return an error")
-		require.Len(t, cleaned, 1, "Cleanup should return one item")
-
-		// Assert final state
-		assert.Equal(t, 2, f.mq.Len(), "Length should be 2 after cleanup")
-		assert.Equal(t, uint64(40), f.mq.ByteSize(), "ByteSize should be 40 after cleanup")
-
-		// Assert reconciler state (3 adds, 1 cleanup)
-		lenDelta, byteSizeDelta, count := f.reconciler.getStats()
-		assert.Equal(t, int64(2), lenDelta, "Net length delta should be 2")
-		assert.Equal(t, int64(40), byteSizeDelta, "Net byte size delta should be 40")
-		assert.Equal(t, 4, count, "Reconciler should have been called 4 times")
-	})
-
-	// --- Test Drain ---
-	t.Run("Drain", func(t *testing.T) {
-		t.Parallel()
-		f := setupTestManagedQueue(t)
-		// Add initial items
-		require.NoError(t, f.mq.Add(item1), "Setup: Add item1 should not fail")
-		require.NoError(t, f.mq.Add(item2), "Setup: Add item2 should not fail")
-		require.Equal(t, 2, f.mq.Len(), "Setup: Initial length should be 2")
-		require.Equal(t, uint64(30), f.mq.ByteSize(), "Setup: Initial byte size should be 30")
-
-		// Configure mock to drain both items
-		f.mockQueue.DrainFunc = func() ([]types.QueueItemAccessor, error) {
-			return []types.QueueItemAccessor{item1, item2}, nil
-		}
+	testCases := []struct {
+		name                  string
+		setupMock             func(q *frameworkmocks.MockSafeQueue, items []types.QueueItemAccessor)
+		expectErr             bool
+		expectedLenDelta      int64
+		expectedByteSizeDelta int64
+	}{
+		{
+			name: "ShouldSucceed_AndDecrementStats",
+			setupMock: func(q *frameworkmocks.MockSafeQueue, items []types.QueueItemAccessor) {
+				q.CleanupFunc = func(_ framework.PredicateFunc) ([]types.QueueItemAccessor, error) {
+					return items, nil
+				}
+			},
+			expectErr:             false,
+			expectedLenDelta:      -2,
+			expectedByteSizeDelta: -125,
+		},
+		{
+			name: "ShouldSucceed_AndNotChangeStats_WhenNoItemsRemoved",
+			setupMock: func(q *frameworkmocks.MockSafeQueue, items []types.QueueItemAccessor) {
+				q.CleanupFunc = func(_ framework.PredicateFunc) ([]types.QueueItemAccessor, error) {
+					return nil, nil // Simulate no items matching predicate.
+				}
+			},
+			expectErr:             false,
+			expectedLenDelta:      0,
+			expectedByteSizeDelta: 0,
+		},
+		{
+			name: "ShouldFail_AndNotChangeStats_WhenUnderlyingQueueFails",
+			setupMock: func(q *frameworkmocks.MockSafeQueue, items []types.QueueItemAccessor) {
+				q.CleanupFunc = func(_ framework.PredicateFunc) ([]types.QueueItemAccessor, error) {
+					return nil, errors.New("cleanup failed")
+				}
+			},
+			expectErr:             true,
+			expectedLenDelta:      0,
+			expectedByteSizeDelta: 0,
+		},
+	}
 
-		drained, err := f.mq.Drain()
-		require.NoError(t, err, "Drain should not return an error")
-		require.Len(t, drained, 2, "Drain should return two items")
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			t.Parallel()
+			q := &frameworkmocks.MockSafeQueue{}
+			h := newMockedMqHarness(t, q, flowKey)
+			items := []types.QueueItemAccessor{
+				typesmocks.NewMockQueueItemAccessor(50, "req", flowKey),
+				typesmocks.NewMockQueueItemAccessor(75, "req", flowKey),
+			}
+			h.setupWithItems(items...)
+			tc.setupMock(q, items)
 
-		// Assert final state
-		assert.Zero(t, f.mq.Len(), "Length should be 0 after drain")
-		assert.Zero(t, f.mq.ByteSize(), "ByteSize should be 0 after drain")
+			_, err := h.mq.Cleanup(func(_ types.QueueItemAccessor) bool { return true })
 
-		// Assert reconciler state (2 adds, 1 drain)
-		lenDelta, byteSizeDelta, count := f.reconciler.getStats()
-		assert.Equal(t, int64(0), lenDelta, "Net length delta should be 0")
-		assert.Equal(t, int64(0), byteSizeDelta, "Net byte size delta should be 0")
-		assert.Equal(t, 3, count, "Reconciler should have been called 3 times")
-	})
+			if tc.expectErr {
+				require.Error(t, err, "Cleanup should have returned an error")
+			} else {
+				require.NoError(t, err, "Cleanup should not have returned an error")
+			}
+			assert.Equal(t, tc.expectedLenDelta, h.propagator.lenDelta.Load(), "Propagated length delta should be correct")
+			assert.Equal(t, tc.expectedByteSizeDelta, h.propagator.byteSizeDelta.Load(),
+				"Propagated byte size delta should be correct")
+		})
+	}
+}
 
-	// --- Test Error Paths ---
-	t.Run("ErrorPaths", func(t *testing.T) {
-		f := setupTestManagedQueue(t)
-		require.NoError(t, f.mq.Add(item1), "Setup: Adding an item should not fail")
-		initialLen, initialByteSize := f.mq.Len(), f.mq.ByteSize()
+func TestManagedQueue_Drain(t *testing.T) {
+	t.Parallel()
+	flowKey := types.FlowKey{ID: "flow", Priority: 1}
 
-		expectedErr := errors.New("internal error")
+	testCases := []struct {
+		name                  string
+		setupMock             func(q *frameworkmocks.MockSafeQueue, items []types.QueueItemAccessor)
+		expectErr             bool
+		expectedLenDelta      int64
+		expectedByteSizeDelta int64
+	}{
+		{
+			name: "ShouldSucceed_AndDecrementStats",
+			setupMock: func(q *frameworkmocks.MockSafeQueue, items []types.QueueItemAccessor) {
+				q.DrainFunc = func() ([]types.QueueItemAccessor, error) {
+					return items, nil
+				}
+			},
+			expectErr:             false,
+			expectedLenDelta:      -2,
+			expectedByteSizeDelta: -125,
+		},
+		{
+			name: "ShouldFail_AndNotChangeStats_WhenUnderlyingQueueFails",
+			setupMock: func(q *frameworkmocks.MockSafeQueue, items []types.QueueItemAccessor) {
+				q.DrainFunc = func() ([]types.QueueItemAccessor, error) {
+					return nil, errors.New("drain failed")
+				}
+			},
+			expectErr:             true,
+			expectedLenDelta:      0,
+			expectedByteSizeDelta: 0,
+		},
+	}
 
-		// Cleanup error
-		f.mockQueue.CleanupFunc = func(p framework.PredicateFunc) ([]types.QueueItemAccessor, error) {
-			return nil, expectedErr
-		}
-		_, err := f.mq.Cleanup(func(i types.QueueItemAccessor) bool { return true })
-		require.ErrorIs(t, err, expectedErr, "Cleanup should propagate error")
-		assert.Equal(t, initialLen, f.mq.Len(), "Len should not change on Cleanup error")
-		assert.Equal(t, initialByteSize, f.mq.ByteSize(), "ByteSize should not change on Cleanup error")
-
-		// Drain error
-		f.mockQueue.DrainFunc = func() ([]types.QueueItemAccessor, error) {
-			return nil, expectedErr
-		}
-		_, err = f.mq.Drain()
-		require.ErrorIs(t, err, expectedErr, "Drain should propagate error")
-		assert.Equal(t, initialLen, f.mq.Len(), "Len should not change on Drain error")
-		assert.Equal(t, initialByteSize, f.mq.ByteSize(), "ByteSize should not change on Drain error")
-	})
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			t.Parallel()
+			q := &frameworkmocks.MockSafeQueue{}
+			h := newMockedMqHarness(t, q, flowKey)
+			items := []types.QueueItemAccessor{
+				typesmocks.NewMockQueueItemAccessor(50, "req", flowKey),
+				typesmocks.NewMockQueueItemAccessor(75, "req", flowKey),
+			}
+			h.setupWithItems(items...)
+			tc.setupMock(q, items)
+
+			_, err := h.mq.Drain()
+
+			if tc.expectErr {
+				require.Error(t, err, "Drain should have returned an error")
+			} else {
+				require.NoError(t, err, "Drain should not have returned an error")
+			}
+			assert.Equal(t, tc.expectedLenDelta, h.propagator.lenDelta.Load(), "Propagated length delta should be correct")
+			assert.Equal(t, tc.expectedByteSizeDelta, h.propagator.byteSizeDelta.Load(),
+				"Propagated byte size delta should be correct")
+		})
+	}
 }
 
-func TestManagedQueue_FlowQueueAccessor(t *testing.T) {
+func TestManagedQueue_PanicOnUnderflow(t *testing.T) {
 	t.Parallel()
-	f := setupTestManagedQueue(t)
-	item := typesmocks.NewMockQueueItemAccessor(100, "req-1", testFlowKey)
-
-	// Setup underlying queue state
-	f.mockQueue.PeekHeadV = item
-	f.mockQueue.PeekTailV = item
-	f.mockQueue.NameV = "MockQueue"
-	f.mockQueue.CapabilitiesV = []framework.QueueCapability{framework.CapabilityFIFO}
+	flowKey := types.FlowKey{ID: "flow", Priority: 1}
+	item := typesmocks.NewMockQueueItemAccessor(100, "req", flowKey)
+	q := &frameworkmocks.MockSafeQueue{}
+	q.AddFunc = func(types.QueueItemAccessor) error { return nil }
+	q.RemoveFunc = func(types.QueueItemHandle) (types.QueueItemAccessor, error) {
+		return item, nil
+	}
+	h := newMockedMqHarness(t, q, flowKey)
+
+	// Add and then successfully remove the item.
+	require.NoError(t, h.mq.Add(item), "Test setup: Add should succeed")
+	_, err := h.mq.Remove(item.Handle())
+	require.NoError(t, err, "Test setup: First Remove should succeed")
+	require.Zero(t, h.mq.Len(), "Test setup: Queue should be empty")
+
+	// Attempting to remove the same item again should cause a panic.
+	assert.PanicsWithValue(t,
+		fmt.Sprintf("invariant violation: managedQueue length for flow %s became negative (-1)", flowKey),
+		func() { _, _ = h.mq.Remove(item.Handle()) },
+		"A second removal of the same item should trigger a panic on length underflow",
+	)
+}
 
-	// Add an item to populate the managed queue's stats
-	require.NoError(t, f.mq.Add(item), "Setup: Adding an item should not fail")
+func TestManagedQueue_Signaling(t *testing.T) {
+	t.Parallel()
+	flowKey := types.FlowKey{ID: "flow", Priority: 1}
+	h := newRealMqHarness(t, flowKey)
+	item1 := typesmocks.NewMockQueueItemAccessor(100, "r1", flowKey)
+	item2 := typesmocks.NewMockQueueItemAccessor(50, "r2", flowKey)
+
+	// 1. Initial state: Empty
+	assert.Empty(t, h.signalRecorder.getSignals(), "No signals should be present on a new queue")
+
+	// 2. Transition: Empty -> NonEmpty
+	require.NoError(t, h.mq.Add(item1), "Adding an item should not fail")
+	assert.Equal(t, []queueStateSignal{queueStateSignalBecameNonEmpty}, h.signalRecorder.getSignals(),
+		"Should signal BecameNonEmpty on first add")
+
+	// 3. Steady state: NonEmpty -> NonEmpty
+	require.NoError(t, h.mq.Add(item2), "Adding a second item should not fail")
+	assert.Equal(t, []queueStateSignal{queueStateSignalBecameNonEmpty}, h.signalRecorder.getSignals(),
+		"No new signal should be sent when adding to a non-empty queue")
+
+	// 4. Steady state: NonEmpty -> NonEmpty
+	_, err := h.mq.Remove(item1.Handle())
+	require.NoError(t, err, "Removing an item should not fail")
+	assert.Equal(t, []queueStateSignal{queueStateSignalBecameNonEmpty}, h.signalRecorder.getSignals(),
+		"No new signal should be sent when removing from a multi-item queue")
+
+	// 5. Transition: NonEmpty -> Empty
+	_, err = h.mq.Remove(item2.Handle())
+	require.NoError(t, err, "Removing the last item should not fail")
+	expectedSignalSequence := []queueStateSignal{queueStateSignalBecameNonEmpty, queueStateSignalBecameEmpty}
+	assert.Equal(t, expectedSignalSequence, h.signalRecorder.getSignals(),
+		"Should signal BecameEmpty on removal of the last item")
+}
 
-	// Get the accessor
-	accessor := f.mq.FlowQueueAccessor()
+func TestManagedQueue_FlowQueueAccessor_ProxiesCalls(t *testing.T) {
+	t.Parallel()
+	flowKey := types.FlowKey{ID: "flow", Priority: 1}
+	q := &frameworkmocks.MockSafeQueue{}
+	harness := newMockedMqHarness(t, q, flowKey)
+	item := typesmocks.NewMockQueueItemAccessor(100, "req-1", flowKey)
+	q.PeekHeadV = item
+	q.PeekTailV = item
+	q.NameV = "MockQueue"
+	q.CapabilitiesV = []framework.QueueCapability{framework.CapabilityFIFO}
+	require.NoError(t, harness.mq.Add(item), "Test setup: Adding an item should not fail")
+
+	accessor := harness.mq.FlowQueueAccessor()
 	require.NotNil(t, accessor, "FlowQueueAccessor should not be nil")
 
-	// Assert that the accessor methods reflect the underlying state
-	assert.Equal(t, f.mq.Name(), accessor.Name(), "Accessor Name() should match managed queue")
-	assert.Equal(t, f.mq.Capabilities(), accessor.Capabilities(), "Accessor Capabilities() should match managed queue")
-	assert.Equal(t, f.mq.Len(), accessor.Len(), "Accessor Len() should match managed queue")
-	assert.Equal(t, f.mq.ByteSize(), accessor.ByteSize(), "Accessor ByteSize() should match managed queue")
-	assert.Equal(t, f.flowKey, accessor.FlowKey(), "Accessor FlowKey() should match managed queue")
-	assert.Equal(t, f.mockComparator, accessor.Comparator(), "Accessor Comparator() should match the one from the policy")
-	assert.Equal(t, f.mockComparator, f.mq.Comparator(), "ManagedQueue Comparator() should match the one from the policy")
+	assert.Equal(t, harness.mq.Name(), accessor.Name(), "Accessor Name() should match managed queue")
+	assert.Equal(t, harness.mq.Capabilities(), accessor.Capabilities(),
+		"Accessor Capabilities() should match managed queue")
+	assert.Equal(t, harness.mq.Len(), accessor.Len(), "Accessor Len() should match managed queue")
+	assert.Equal(t, harness.mq.ByteSize(), accessor.ByteSize(), "Accessor ByteSize() should match managed queue")
+	assert.Equal(t, flowKey, accessor.FlowKey(), "Accessor FlowKey() should match managed queue")
+	assert.Equal(t, harness.mockPolicy.Comparator(), accessor.Comparator(),
+		"Accessor Comparator() should match the one from the policy")
+	assert.Equal(t, harness.mockPolicy.Comparator(), harness.mq.Comparator(),
+		"ManagedQueue Comparator() should also match the one from the policy")
 
 	peekedHead, err := accessor.PeekHead()
 	require.NoError(t, err, "Accessor PeekHead() should not return an error")
-	assert.Equal(t, item, peekedHead, "Accessor PeekHead() should return the correct item")
+	assert.Same(t, item, peekedHead, "Accessor PeekHead() should return the correct item instance")
 
 	peekedTail, err := accessor.PeekTail()
 	require.NoError(t, err, "Accessor PeekTail() should not return an error")
-	assert.Equal(t, item, peekedTail, "Accessor PeekTail() should return the correct item")
+	assert.Same(t, item, peekedTail, "Accessor PeekTail() should return the correct item instance")
 }
 
-func TestManagedQueue_Concurrency(t *testing.T) {
+// --- Concurrency Tests ---
+
+// TestManagedQueue_Concurrency_SignalingRace targets the race condition of a queue flapping between empty and non-empty
+// states.
+// It ensures the `BecameEmpty` and `BecameNonEmpty` signals are sent correctly in strict alternation, without
+// duplicates or missed signals.
+func TestManagedQueue_Concurrency_SignalingRace(t *testing.T) {
 	t.Parallel()
 
-	// Use a real `listqueue` since it's concurrent-safe.
-	lq, err := queue.NewQueueFromName(listqueue.ListQueueName, nil)
-	require.NoError(t, err, "Setup: creating a real listqueue should not fail")
+	const ops = 1000
+	flowKey := types.FlowKey{ID: "flow", Priority: 1}
+	h := newRealMqHarness(t, flowKey)
 
-	reconciler := &testStatsReconciler{}
-	flowKey := types.FlowKey{ID: "conc-test-flow", Priority: 1}
-	mq := newManagedQueue(lq, nil, flowKey, logr.Discard(), reconciler.reconcile)
+	var wg sync.WaitGroup
+	wg.Add(2)
 
-	const (
-		numGoroutines   = 20
-		opsPerGoroutine = 200
-		itemByteSize    = 10
-		initialItems    = 500
-	)
+	// Goroutine 1: Adder - continuously adds items.
+	go func() {
+		defer wg.Done()
+		for range ops {
+			_ = h.mq.Add(typesmocks.NewMockQueueItemAccessor(10, "req", flowKey))
+		}
+	}()
+
+	// Goroutine 2: Remover - continuously drains the queue.
+	go func() {
+		defer wg.Done()
+		for range ops {
+			// Drain is used to remove all items present in a single atomic operation.
+			_, _ = h.mq.Drain()
+		}
+	}()
 
-	var wg sync.WaitGroup
-	var successfulAdds, successfulRemoves atomic.Int64
+	wg.Wait()
 
-	// Use a channel as a concurrent-safe pool of handles for removal.
-	handles := make(chan types.QueueItemHandle, initialItems+(numGoroutines*opsPerGoroutine))
+	// Verification: The critical part of this test is to analyze the sequence of signals.
+	signals := h.signalRecorder.getSignals()
+	require.NotEmpty(t, signals, "At least some signals should have been generated")
 
-	// Pre-fill the queue to give removers something to do immediately.
-	for range initialItems {
-		item := typesmocks.NewMockQueueItemAccessor(uint64(itemByteSize), "initial", testFlowKey)
-		require.NoError(t, mq.Add(item), "Setup: pre-filling queue should not fail")
-		handles <- item.Handle()
+	// The sequence must be a strict alternation of `BecameNonEmpty` and `BecameEmpty` signals.
+	// There should never be two of the same signal in a row.
+	for i := 0; i < len(signals)-1; i++ {
+		assert.NotEqual(t, signals[i], signals[i+1], "Signals at index %d and %d must not be duplicates", i, i+1)
 	}
-	// Reset reconciler stats after setup so we only measure the concurrent phase.
-	*reconciler = testStatsReconciler{}
 
-	// Launch goroutines to perform a mix of concurrent operations.
-	wg.Add(numGoroutines)
-	for i := range numGoroutines {
-		go func(routineID int) {
-			defer wg.Done()
-			for j := range opsPerGoroutine {
-				// Mix up operations between adding and removing.
-				if (routineID+j)%2 == 0 {
-					// Add operation
-					item := typesmocks.NewMockQueueItemAccessor(uint64(itemByteSize), "req", testFlowKey)
-					if err := mq.Add(item); err == nil {
-						successfulAdds.Add(1)
-						handles <- item.Handle()
-					}
-				} else {
-					// Remove operation
-					select {
-					case handle := <-handles:
-						if _, err := mq.Remove(handle); err == nil {
-							successfulRemoves.Add(1)
-						}
-					default:
-						// No handles available, do nothing. This can happen if removers are faster than adders.
-					}
-				}
-			}
-		}(i)
-	}
-	wg.Wait()
+	// The first signal must be `BecameNonEmpty`.
+	assert.Equal(t, queueStateSignalBecameNonEmpty, signals[0], "The first signal must be BecameNonEmpty")
+}
 
-	// All concurrent operations are complete. Drain any remaining items to get the final count.
-	drainedItems, err := mq.Drain()
-	require.NoError(t, err, "Draining the queue at the end should not fail")
+// TestManagedQueue_Concurrency_ItemIntegrity validates that under high concurrency, the queue does not lose or
+// duplicate items and that the final propagated statistics are consistent with the operations performed.
+func TestManagedQueue_Concurrency_ItemIntegrity(t *testing.T) {
+	t.Parallel()
 
-	// Final consistency checks.
-	finalItemCount := len(drainedItems)
-	finalByteSize := mq.ByteSize()
+	const numGoRoutines = 10
+	const opsPerGoRoutine = 500
+	const itemByteSize = 10
 
-	// The number of items left in the queue should match our tracking.
-	expectedFinalItemCount := initialItems + int(successfulAdds.Load()) - int(successfulRemoves.Load())
-	assert.Equal(t, expectedFinalItemCount, finalItemCount, "Final item count should match initial + adds - removes")
+	flowKey := types.FlowKey{ID: "flow", Priority: 1}
+	h := newRealMqHarness(t, flowKey)
+	var wg sync.WaitGroup
+	wg.Add(numGoRoutines)
+
+	// Each goroutine will attempt to perform a mix of `Add` and `Remove` operations.
+	for range numGoRoutines {
+		go func() {
+			defer wg.Done()
+			for range opsPerGoRoutine {
+				// Add an item.
+				item := typesmocks.NewMockQueueItemAccessor(uint64(itemByteSize), "req", flowKey)
+				require.NoError(t, h.mq.Add(item), "Concurrent Add should not fail")
 
-	// The queue's internal stats must be zero after draining.
-	assert.Zero(t, mq.Len(), "Managed queue length must be zero after drain")
-	assert.Zero(t, finalByteSize, "Managed queue byte size must be zero after drain")
+				// Immediately try to remove it. This creates high contention on the queue's internal state.
+				_, _ = h.mq.Remove(item.Handle())
+			}
+		}()
+	}
+
+	wg.Wait()
 
-	// The net change reported to the reconciler must match the net change from the concurrent phase,
-	// plus the final drain.
-	netLenChangeDuringConcurrentPhase := successfulAdds.Load() - successfulRemoves.Load()
-	netByteSizeChangeDuringConcurrentPhase := netLenChangeDuringConcurrentPhase * itemByteSize
+	// After all operations, the queue should ideally be empty, but some removals might have failed if another goroutine
+	// got to it first. We drain any remaining items to get a final count.
+	_, err := h.mq.Drain()
+	require.NoError(t, err, "Final drain should not fail")
 
-	lenDelta, byteSizeDelta, _ := reconciler.getStats()
+	// Final State Verification
+	assert.Zero(t, h.mq.Len(), "Queue length must be zero after final drain")
+	assert.Zero(t, h.mq.ByteSize(), "Queue byte size must be zero after final drain")
 
-	expectedLenDelta := netLenChangeDuringConcurrentPhase - int64(finalItemCount)
-	expectedByteSizeDelta := netByteSizeChangeDuringConcurrentPhase - int64(uint64(finalItemCount)*itemByteSize)
+	// Statistical Integrity Verification
+	// The total number of propagated additions must equal the number of propagated removals.
+	lenDelta := h.propagator.lenDelta.Load()
+	byteSizeDelta := h.propagator.byteSizeDelta.Load()
 
-	assert.Equal(t, expectedLenDelta, lenDelta,
-		"Net length delta in reconciler should match the net change from all operations")
-	assert.Equal(t, expectedByteSizeDelta, byteSizeDelta,
-		"Net byte size delta in reconciler should match the net change from all operations")
+	assert.Equal(t, int64(0), lenDelta,
+		"Net length delta propagated must be zero, proving every add was matched by a remove delta")
+	assert.Equal(t, int64(0), byteSizeDelta, "Net byte size delta propagated must be zero")
 }
diff --git a/pkg/epp/flowcontrol/registry/registry_test.go b/pkg/epp/flowcontrol/registry/registry_test.go
new file mode 100644
index 0000000..fcefd86
--- /dev/null
+++ b/pkg/epp/flowcontrol/registry/registry_test.go
@@ -0,0 +1,809 @@
+/*
+Copyright 2025 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package registry
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"sync"
+	"testing"
+	"time"
+
+	"github.com/go-logr/logr"
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+	"k8s.io/utils/clock"
+	testclock "k8s.io/utils/clock/testing"
+
+	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/contracts"
+	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework"
+	inter "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/plugins/policies/interflow/dispatch"
+	intra "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/plugins/policies/intraflow/dispatch"
+	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/plugins/queue"
+	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/types"
+	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/types/mocks"
+)
+
+const syncTimeout = 2 * time.Second
+
+// --- Test Harness and Mocks ---
+
+// registryTestHarness provides a fully initialized test harness for the `FlowRegistry`.
+type registryTestHarness struct {
+	t           *testing.T
+	ctx         context.Context
+	cancel      context.CancelFunc
+	fr          *FlowRegistry
+	config      Config
+	fakeClock   *testclock.FakeClock
+	activeItems map[types.FlowKey]types.QueueItemAccessor
+}
+
+type harnessOptions struct {
+	config            *Config
+	useFakeClock      bool
+	initialShardCount int
+}
+
+// newRegistryTestHarness creates and starts a new `FlowRegistry` for testing.
+func newRegistryTestHarness(t *testing.T, opts harnessOptions) *registryTestHarness {
+	t.Helper()
+
+	var config Config
+	if opts.config != nil {
+		config = *opts.config
+	} else {
+		config = Config{
+			FlowGCTimeout: 1 * time.Minute,
+			PriorityBands: []PriorityBandConfig{
+				{Priority: 10, PriorityName: "High"},
+				{Priority: 20, PriorityName: "Low"},
+			},
+		}
+	}
+	if opts.initialShardCount > 0 {
+		config.InitialShardCount = opts.initialShardCount
+	}
+
+	var clk clock.WithTickerAndDelayedExecution
+	var fakeClock *testclock.FakeClock
+	if opts.useFakeClock {
+		fakeClock = testclock.NewFakeClock(time.Now())
+		clk = fakeClock
+	}
+
+	fr, err := NewFlowRegistry(config, logr.Discard(), WithClock(clk))
+	require.NoError(t, err, "Test setup: NewFlowRegistry should not fail")
+
+	ctx, cancel := context.WithCancel(context.Background())
+	var wg sync.WaitGroup
+	wg.Add(1)
+	go func() {
+		defer wg.Done()
+		fr.Run(ctx)
+	}()
+
+	t.Cleanup(func() {
+		cancel()
+		wg.Wait()
+	})
+
+	return &registryTestHarness{
+		t:           t,
+		ctx:         ctx,
+		cancel:      cancel,
+		fr:          fr,
+		config:      config,
+		fakeClock:   fakeClock,
+		activeItems: make(map[types.FlowKey]types.QueueItemAccessor),
+	}
+}
+
+// synchronize blocks until the `FlowRegistry`'s event loop has processed all preceding events.
+func (h *registryTestHarness) synchronize() {
+	h.t.Helper()
+	doneCh := make(chan struct{})
+	select {
+	case h.fr.events <- &syncEvent{doneCh: doneCh}:
+		select {
+		case <-doneCh:
+		case <-time.After(syncTimeout):
+			h.t.Fatalf("Timeout waiting for FlowRegistry synchronization ack")
+		}
+	case <-time.After(syncTimeout):
+		h.t.Fatalf("Timeout sending sync event to FlowRegistry (channel may be full)")
+	}
+}
+
+// waitForGCTick advances the fake clock to trigger a GC cycle and then blocks until that cycle is complete.
+// This works by sandwiching the clock step between two synchronization barriers.
+func (h *registryTestHarness) waitForGCTick() {
+	h.t.Helper()
+	require.NotNil(h.t, h.fakeClock, "waitForGCTick requires the fake clock to be enabled")
+	h.synchronize()
+	h.fakeClock.Step(h.config.FlowGCTimeout + time.Millisecond)
+	h.synchronize()
+}
+
+// setFlowActive makes a flow Active (by adding an item) or Idle (by removing it) and synchronizes the state change.
+func (h *registryTestHarness) setFlowActive(key types.FlowKey, active bool) {
+	h.t.Helper()
+	shard := h.getFirstActiveShard()
+	mq, err := shard.ManagedQueue(key)
+	require.NoError(h.t, err, "Failed to get managed queue to set flow activity for flow %s", key)
+
+	if active {
+		require.NotContains(h.t, h.activeItems, key, "Flow %s is already marked as Active in the test harness", key)
+		item := mocks.NewMockQueueItemAccessor(100, "req", key)
+		require.NoError(h.t, mq.Add(item), "Failed to add item to make flow %s Active", key)
+		h.activeItems[key] = item
+	} else {
+		item, ok := h.activeItems[key]
+		require.True(h.t, ok, "Flow %s was not Active in the test harness, cannot make it Idle", key)
+		_, err := mq.Remove(item.Handle())
+		require.NoError(h.t, err, "Failed to remove item to make flow %s Idle", key)
+		delete(h.activeItems, key)
+	}
+	h.synchronize()
+}
+
+func (h *registryTestHarness) getFirstActiveShard() contracts.RegistryShard {
+	h.t.Helper()
+	allShards := h.fr.Shards()
+	for _, s := range allShards {
+		if s.IsActive() {
+			return s
+		}
+	}
+	h.t.Fatalf("Failed to find any active shard in list of %d shards", len(allShards))
+	return nil
+}
+
+func (h *registryTestHarness) assertFlowExists(key types.FlowKey, msgAndArgs ...any) {
+	h.t.Helper()
+	allShards := h.fr.Shards()
+	require.NotEmpty(h.t, allShards, "Cannot assert flow existence without shards")
+
+	// It's sufficient to check one shard, as the registry guarantees consistency.
+	// A more robust check could iterate all, but this is a good balance.
+	_, err := allShards[0].ManagedQueue(key)
+	assert.NoError(h.t, err, msgAndArgs...)
+}
+
+func (h *registryTestHarness) assertFlowDoesNotExist(key types.FlowKey, msgAndArgs ...any) {
+	h.t.Helper()
+	allShards := h.fr.Shards()
+	// If there are no shards, the flow cannot exist.
+	if len(allShards) == 0 {
+		return
+	}
+	_, err := allShards[0].ManagedQueue(key)
+	assert.ErrorIs(h.t, err, contracts.ErrFlowInstanceNotFound, msgAndArgs...)
+}
+
+// --- Basic Tests ---
+
+func TestFlowRegistry_New_ErrorPaths(t *testing.T) {
+	t.Parallel()
+
+	t.Run("ShouldFail_WhenConfigIsInvalid", func(t *testing.T) {
+		t.Parallel()
+		_, err := NewFlowRegistry(Config{}, logr.Discard()) // No priority bands is invalid.
+		require.Error(t, err, "NewFlowRegistry should fail with an invalid config")
+	})
+
+	t.Run("ShouldFail_WhenInitialShardCreationFails", func(t *testing.T) {
+		t.Parallel()
+		failingInterFlowFactory := func(_ inter.RegisteredPolicyName) (framework.InterFlowDispatchPolicy, error) {
+			return nil, errors.New("injected shard creation failure")
+		}
+		configWithFailingFactory := Config{
+			PriorityBands: []PriorityBandConfig{{Priority: 10, PriorityName: "High"}},
+		}
+		cfg, err := NewConfig(configWithFailingFactory, withInterFlowDispatchPolicyFactory(failingInterFlowFactory))
+		require.NoError(t, err, "Test setup: creating the config object itself should not fail")
+
+		_, err = NewFlowRegistry(*cfg, logr.Discard())
+
+		require.Error(t, err, "NewFlowRegistry should fail when initial shard setup fails")
+		assert.Contains(t, err.Error(), "injected shard creation failure", "Error message should reflect the root cause")
+	})
+}
+
+// --- Administrative Method Tests ---
+
+func TestFlowRegistry_RegisterOrUpdateFlow(t *testing.T) {
+	t.Parallel()
+	h := newRegistryTestHarness(t, harnessOptions{})
+	key := types.FlowKey{ID: "test-flow", Priority: 10}
+	spec := types.FlowSpecification{Key: key}
+
+	err := h.fr.RegisterOrUpdateFlow(spec)
+	require.NoError(t, err, "Registering a new flow should succeed")
+	h.assertFlowExists(key, "Flow should exist in registry after initial registration")
+
+	err = h.fr.RegisterOrUpdateFlow(spec)
+	require.NoError(t, err, "Re-registering the same flow should be idempotent")
+	h.assertFlowExists(key, "Flow should still exist after idempotent re-registration")
+}
+
+func TestFlowRegistry_RegisterOrUpdateFlow_ErrorPaths(t *testing.T) {
+	t.Parallel()
+
+	// Define mock factories that can be injected to force specific failures.
+	failingPolicyFactory := func(name intra.RegisteredPolicyName) (framework.IntraFlowDispatchPolicy, error) {
+		return nil, errors.New("injected policy factory failure")
+	}
+	failingQueueFactory := func(name queue.RegisteredQueueName, c framework.ItemComparator) (framework.SafeQueue, error) {
+		return nil, errors.New("injected queue factory failure")
+	}
+
+	baseConfig := Config{
+		PriorityBands: []PriorityBandConfig{
+			{Priority: 10, PriorityName: "High"},
+		},
+	}
+
+	testCases := []struct {
+		name   string
+		spec   types.FlowSpecification
+		setup  func(h *registryTestHarness) // Surgical setup to induce failure.
+		errStr string                       // Expected substring in the error message.
+		errIs  error                        // Optional: Expected wrapped error.
+	}{
+		{
+			name:   "ShouldFail_WhenSpecIDIsEmpty",
+			spec:   types.FlowSpecification{Key: types.FlowKey{ID: "", Priority: 10}},
+			errStr: "flow ID cannot be empty",
+			errIs:  contracts.ErrFlowIDEmpty,
+		},
+		{
+			name:   "ShouldFail_WhenPriorityBandIsNotFound",
+			spec:   types.FlowSpecification{Key: types.FlowKey{ID: "flow", Priority: 99}},
+			errStr: "failed to get configuration for priority 99",
+			errIs:  contracts.ErrPriorityBandNotFound,
+		},
+		{
+			name: "ShouldFail_WhenPolicyFactoryFails",
+			spec: types.FlowSpecification{Key: types.FlowKey{ID: "flow", Priority: 10}},
+			setup: func(h *registryTestHarness) {
+				// After the registry is created with a valid config, we surgically replace the policy factory with one that is
+				// guaranteed to fail.
+				h.fr.config.intraFlowDispatchPolicyFactory = failingPolicyFactory
+			},
+			errStr: "failed to instantiate intra-flow policy",
+		},
+		{
+			name: "ShouldFail_WhenQueueFactoryFails",
+			spec: types.FlowSpecification{Key: types.FlowKey{ID: "flow", Priority: 10}},
+			setup: func(h *registryTestHarness) {
+				// Similarly, we inject a failing queue factory.
+				h.fr.config.queueFactory = failingQueueFactory
+			},
+			errStr: "failed to instantiate queue",
+		},
+	}
+
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			t.Parallel()
+			h := newRegistryTestHarness(t, harnessOptions{config: &baseConfig})
+			if tc.setup != nil {
+				tc.setup(h)
+			}
+
+			err := h.fr.RegisterOrUpdateFlow(tc.spec)
+
+			require.Error(t, err, "RegisterOrUpdateFlow should have returned an error")
+			assert.Contains(t, err.Error(), tc.errStr, "Error message should contain expected text")
+			if tc.errIs != nil {
+				assert.ErrorIs(t, err, tc.errIs, "Error should match expected wrapped error")
+			}
+		})
+	}
+}
+
+func TestFlowRegistry_UpdateShardCount(t *testing.T) {
+	t.Parallel()
+
+	// stateForDrainingTest holds the specific item that will be placed on a shard that is about to be Drained.
+	// We need to pass it from the setup phase to the assertion phase.
+	type stateForDrainingTest struct {
+		drainingShardID string
+		item            types.QueueItemAccessor
+		flowKey         types.FlowKey
+	}
+
+	testCases := []struct {
+		name              string
+		initialShardCount int
+		targetShardCount  int
+		setup             func(h *registryTestHarness) any // Returns optional state for assertions
+		expectErrIs       error
+		expectErrStr      string
+		assertions        func(t *testing.T, h *registryTestHarness, state any)
+	}{
+		{
+			name:              "ShouldSucceed_OnScaleUp",
+			initialShardCount: 2,
+			targetShardCount:  4,
+			assertions: func(t *testing.T, h *registryTestHarness, _ any) {
+				assert.Len(t, h.fr.Shards(), 4, "Registry should have 4 shards after scale-up")
+				assert.Len(t, h.fr.activeShards, 4, "Registry should have 4 active shards")
+				assert.Empty(t, h.fr.drainingShards, "Registry should have 0 draining shards")
+			},
+		},
+		{
+			name:              "ShouldBeNoOp_WhenCountIsUnchanged",
+			initialShardCount: 2,
+			targetShardCount:  2,
+			assertions: func(t *testing.T, h *registryTestHarness, _ any) {
+				assert.Len(t, h.fr.Shards(), 2, "Shard count should remain unchanged")
+			},
+		},
+		{
+			name:              "ShouldSucceed_OnScaleUp_WithExistingFlows",
+			initialShardCount: 1,
+			targetShardCount:  2,
+			setup: func(h *registryTestHarness) any {
+				key := types.FlowKey{ID: "flow", Priority: 10}
+				require.NoError(t, h.fr.RegisterOrUpdateFlow(types.FlowSpecification{Key: key}),
+					"Test setup: failed to register flow")
+				return key // Pass the key to assertions
+			},
+			assertions: func(t *testing.T, h *registryTestHarness, state any) {
+				key := state.(types.FlowKey)
+				assert.Len(t, h.fr.Shards(), 2, "Registry should now have 2 shards")
+				h.assertFlowExists(key, "Flow must exist on all shards after scaling up")
+			},
+		},
+		{
+			name:              "ShouldFail_WhenShardCountIsInvalid_Zero",
+			initialShardCount: 1,
+			targetShardCount:  0,
+			expectErrIs:       contracts.ErrInvalidShardCount,
+		},
+		{
+			name:              "ShouldFail_WhenShardCountIsInvalid_Negative",
+			initialShardCount: 1,
+			targetShardCount:  -1,
+			expectErrIs:       contracts.ErrInvalidShardCount,
+		},
+		{
+			name:              "ShouldFailAndRollback_WhenFlowSyncFailsDuringScaleUp",
+			initialShardCount: 1,
+			targetShardCount:  2,
+			setup: func(h *registryTestHarness) any {
+				// Create a valid, existing flow in the registry.
+				key := types.FlowKey{ID: "flow", Priority: 10}
+				require.NoError(t, h.fr.RegisterOrUpdateFlow(types.FlowSpecification{Key: key}),
+					"Test setup: failed to register existing flow")
+
+				// Sabotage the system: Inject a policy factory that is guaranteed to fail.
+				// This will be called when the registry tries to create components for the existing flow on the *new* shard.
+				failingPolicyFactory := func(_ intra.RegisteredPolicyName) (framework.IntraFlowDispatchPolicy, error) {
+					return nil, errors.New("injected flow sync failure")
+				}
+				h.fr.mu.Lock()
+				h.fr.config.intraFlowDispatchPolicyFactory = failingPolicyFactory
+				h.fr.mu.Unlock()
+
+				return nil
+			},
+			expectErrStr: "injected flow sync failure",
+			assertions: func(t *testing.T, h *registryTestHarness, _ any) {
+				// The scale-up must have been aborted, leaving the registry in its original state.
+				assert.Len(t, h.fr.Shards(), 1, "Shard count should not have changed after a failed scale-up")
+			},
+		},
+		{
+			name:              "ShouldGracefullyDrain_OnScaleDown",
+			initialShardCount: 3,
+			targetShardCount:  2,
+			setup: func(h *registryTestHarness) any {
+				key := types.FlowKey{ID: "test-flow", Priority: 10}
+				require.NoError(t, h.fr.RegisterOrUpdateFlow(types.FlowSpecification{Key: key}),
+					"Test setup: failed to register flow")
+
+				allShards := h.fr.Shards()
+				require.Len(t, allShards, 3, "Test setup: Should start with 3 shards")
+				drainingShard := allShards[2] // The last shard will be chosen for draining.
+
+				mq, err := drainingShard.ManagedQueue(key)
+				require.NoError(t, err, "Test setup: failed to get queue on Draining shard")
+				item := mocks.NewMockQueueItemAccessor(100, "req", key)
+				require.NoError(t, mq.Add(item), "Test setup: failed to add item")
+				h.synchronize()
+
+				return &stateForDrainingTest{
+					drainingShardID: drainingShard.ID(),
+					item:            item,
+					flowKey:         key,
+				}
+			},
+			assertions: func(t *testing.T, h *registryTestHarness, state any) {
+				testState := state.(*stateForDrainingTest)
+				h.synchronize() // Ensure the Draining state has been processed.
+
+				// Assert the intermediate Draining state is correct.
+				shards := h.fr.Shards()
+				require.Len(t, shards, 3, "Registry should still track the Draining shard until it is empty")
+				var drainingShard contracts.RegistryShard
+				for _, s := range shards {
+					if s.ID() == testState.drainingShardID {
+						drainingShard = s
+					}
+				}
+				require.NotNil(t, drainingShard, "Draining shard should still be present in the list")
+				assert.False(t, drainingShard.IsActive(), "Target shard should be marked as not active")
+
+				// Assert that the item on the draining shard is still accessible.
+				mq, err := drainingShard.ManagedQueue(testState.flowKey)
+				require.NoError(t, err, "Should still be able to get queue from draining shard")
+				removedItem, err := mq.Remove(testState.item.Handle())
+				require.NoError(t, err, "Should be able to remove the item from the draining shard")
+				assert.Equal(t, testState.item.OriginalRequest().ID(), removedItem.OriginalRequest().ID(),
+					"Correct item was removed")
+
+				// After the item is removed, the shard becomes empty and should be fully garbage collected.
+				h.synchronize() // Process the `BecameDrained` event.
+				assert.Len(t, h.fr.Shards(), 2,
+					"Drained shard was not garbage collected from the registry after becoming empty")
+			},
+		},
+	}
+
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			t.Parallel()
+			h := newRegistryTestHarness(t, harnessOptions{initialShardCount: tc.initialShardCount})
+			var state any
+			if tc.setup != nil {
+				state = tc.setup(h)
+			}
+
+			err := h.fr.UpdateShardCount(tc.targetShardCount)
+
+			if tc.expectErrIs != nil || tc.expectErrStr != "" {
+				require.Error(t, err, "UpdateShardCount should have returned an error")
+				if tc.expectErrIs != nil {
+					assert.ErrorIs(t, err, tc.expectErrIs, "Error should be the expected type")
+				}
+				if tc.expectErrStr != "" {
+					assert.Contains(t, err.Error(), tc.expectErrStr, "Error message should contain expected substring")
+				}
+			} else {
+				require.NoError(t, err, "UpdateShardCount should not have returned an error")
+			}
+
+			if tc.assertions != nil {
+				tc.assertions(t, h, state)
+			}
+		})
+	}
+}
+
+// --- Stats and Observability Tests ---
+
+func TestFlowRegistry_Stats_And_ShardStats(t *testing.T) {
+	t.Parallel()
+	h := newRegistryTestHarness(t, harnessOptions{initialShardCount: 2})
+	keyHigh := types.FlowKey{ID: "flow-high", Priority: 10}
+	keyLow := types.FlowKey{ID: "flow-low", Priority: 20}
+	require.NoError(t, h.fr.RegisterOrUpdateFlow(types.FlowSpecification{Key: keyHigh}))
+	require.NoError(t, h.fr.RegisterOrUpdateFlow(types.FlowSpecification{Key: keyLow}))
+
+	// Add items to the queues. Note that these are distributed across 2 shards.
+	h.setFlowActive(keyHigh, true) // 100 bytes
+	h.setFlowActive(keyLow, true)  // 100 bytes
+	h.synchronize()
+
+	// Test global stats.
+	stats := h.fr.Stats()
+	assert.Equal(t, uint64(2), stats.TotalLen, "Global TotalLen should be correct")
+	assert.Equal(t, uint64(200), stats.TotalByteSize, "Global TotalByteSize should be correct")
+	assert.Equal(t, uint64(1), stats.PerPriorityBandStats[10].Len, "Global stats for priority 10 Len is incorrect")
+	assert.Equal(t, uint64(100), stats.PerPriorityBandStats[10].ByteSize,
+		"Global stats for priority 10 ByteSize is incorrect")
+
+	// Test shard stats.
+	shardStats := h.fr.ShardStats()
+	require.Len(t, shardStats, 2, "Should be stats for 2 shards")
+
+	var totalShardLen, totalShardBytes uint64
+	for _, ss := range shardStats {
+		totalShardLen += ss.TotalLen
+		totalShardBytes += ss.TotalByteSize
+	}
+	assert.Equal(t, stats.TotalLen, totalShardLen, "Sum of shard lengths should equal global length")
+	assert.Equal(t, stats.TotalByteSize, totalShardBytes, "Sum of shard byte sizes should equal global byte size")
+}
+
+// --- Garbage Collection Tests ---
+
+func TestFlowRegistry_GarbageCollection_IdleFlows(t *testing.T) {
+	t.Parallel()
+	key := types.FlowKey{ID: "gc-flow", Priority: 10}
+	spec := types.FlowSpecification{Key: key}
+
+	t.Run("ShouldCollectIdleFlow_AfterGracePeriod", func(t *testing.T) {
+		t.Parallel()
+		h := newRegistryTestHarness(t, harnessOptions{useFakeClock: true})
+		require.NoError(t, h.fr.RegisterOrUpdateFlow(spec), "Test setup: failed to register flow")
+		h.synchronize()
+
+		// A new flow is granted a one-cycle grace period. The Mark phase of the first GC cycle will see
+		// 1lastActiveGeneration==gcGenerationNewFlow` and "timestamp" it for survival.
+		h.waitForGCTick()
+		h.assertFlowExists(key, "A new Idle flow must survive its first GC cycle")
+
+		// In the second cycle, the flow is Idle and was not marked in the preceding cycle, so it is collected.
+		h.waitForGCTick()
+		h.assertFlowDoesNotExist(key, "An Idle flow must be collected after its grace period expires")
+	})
+
+	t.Run("ShouldNotCollectFlow_ThatWasRecentlyActive", func(t *testing.T) {
+		t.Parallel()
+		h := newRegistryTestHarness(t, harnessOptions{useFakeClock: true})
+		require.NoError(t, h.fr.RegisterOrUpdateFlow(spec), "Test setup: failed to register flow")
+		h.synchronize()
+
+		h.setFlowActive(key, true)
+		h.waitForGCTick()
+		h.assertFlowExists(key, "An Active flow should not be collected")
+		h.setFlowActive(key, false)
+
+		// The flow is now Idle, but it was marked as Active in the immediately preceding cycle, so it must survive this
+		// sweep.
+		h.waitForGCTick()
+		h.assertFlowExists(key, "A flow must not be collected in the cycle immediately after it becomes Idle")
+
+		// Having been Idle for a full cycle, it will now be collected.
+		h.waitForGCTick()
+		h.assertFlowDoesNotExist(key, "A flow must be collected after being Idle for a full cycle")
+	})
+
+	t.Run("ShouldNotCollectFlow_WhenActivityRacesWithGC", func(t *testing.T) {
+		t.Parallel()
+		h := newRegistryTestHarness(t, harnessOptions{useFakeClock: true})
+		require.NoError(t, h.fr.RegisterOrUpdateFlow(spec), "Test setup: failed to register flow")
+		h.synchronize()
+
+		// Establish a state where the flow is a candidate for GC on the *next* tick.
+		// This requires only getting it past its initial grace period.
+		h.waitForGCTick()
+		h.assertFlowExists(key, "Test setup failed: flow should exist after its grace period")
+
+		// Trigger the race: send a GC tick event but DO NOT wait for it to be processed.
+		h.fakeClock.Step(h.config.FlowGCTimeout + time.Millisecond)
+
+		// Immediately send a competing activity signal.
+		shard := h.getFirstActiveShard()
+		mq, err := shard.ManagedQueue(key)
+		require.NoError(t, err, "Test setup: failed to get managed queue for race")
+		require.NoError(t, mq.Add(mocks.NewMockQueueItemAccessor(100, "req", key)), "Test setup: failed to add item")
+
+		// Synchronize. The `onGCTick` runs first, but its "Verify" step will see the live item and abort.
+		h.synchronize()
+
+		// The flow must survive due to the "Trust but Verify" live check.
+		h.assertFlowExists(key, "Flow should survive GC due to the 'Trust but Verify' live check")
+	})
+
+	t.Run("ShouldBeBenign_WhenGCingAlreadyDeletedFlow", func(t *testing.T) {
+		t.Parallel()
+		h := newRegistryTestHarness(t, harnessOptions{useFakeClock: true})
+		require.NoError(t, h.fr.RegisterOrUpdateFlow(spec), "Test setup: failed to register flow")
+
+		h.waitForGCTick()
+		h.waitForGCTick() // The second tick collects the flow.
+		h.assertFlowDoesNotExist(key, "Test setup failed: flow was not collected")
+
+		// Manually (white-box) call the GC function again for the same key.
+		// It should return false and not panic.
+		var collected bool
+		assert.NotPanics(t, func() {
+			h.fr.mu.Lock()
+			collected = h.fr.garbageCollectFlowLocked(key)
+			h.fr.mu.Unlock()
+		}, "GCing a deleted flow should not panic")
+		assert.False(t, collected, "GCing a deleted flow should return false")
+	})
+
+	t.Run("ShouldAbortGC_WhenCacheIsActive", func(t *testing.T) {
+		t.Parallel()
+		h := newRegistryTestHarness(t, harnessOptions{useFakeClock: true})
+		require.NoError(t, h.fr.RegisterOrUpdateFlow(spec), "Test setup: failed to register flow")
+		h.setFlowActive(key, true) // Make the flow Active.
+
+		// Manually call the GC function. It should check the cache (`isIdle`) first and abort immediately without
+		// performing the "Verify" step.
+		var collected bool
+		assert.NotPanics(t, func() {
+			h.fr.mu.Lock()
+			collected = h.fr.garbageCollectFlowLocked(key)
+			h.fr.mu.Unlock()
+		}, "GCing an active flow should not panic")
+
+		assert.False(t, collected, "GCing an active flow should return false")
+		h.assertFlowExists(key, "Flow should still exist after aborted GC attempt")
+	})
+}
+
+func TestFlowRegistry_GarbageCollection_DrainedShards(t *testing.T) {
+	t.Parallel()
+	h := newRegistryTestHarness(t, harnessOptions{initialShardCount: 2})
+	key := types.FlowKey{ID: "test-flow", Priority: 10}
+	require.NoError(t, h.fr.RegisterOrUpdateFlow(types.FlowSpecification{Key: key}),
+		"Test setup: failed to register flow")
+
+	allShards := h.fr.Shards()
+	require.Len(t, allShards, 2, "Test setup: Should start with 2 shards")
+	drainingShard := allShards[1]
+
+	// Add an item to the shard that will be drained to prevent its immediate GC upon scale-down.
+	mq, err := drainingShard.ManagedQueue(key)
+	require.NoError(t, err, "Test setup: failed to get queue on Draining shard")
+	item := mocks.NewMockQueueItemAccessor(100, "req", key)
+	require.NoError(t, mq.Add(item), "Test setup: failed to add item")
+	h.synchronize()
+
+	// Scale down, which marks the shard as Draining.
+	require.NoError(t, h.fr.UpdateShardCount(1), "Scaling down should succeed")
+	h.synchronize()
+
+	require.Len(t, h.fr.Shards(), 2, "Registry should still track the Draining shard")
+	assert.False(t, drainingShard.IsActive(), "Target shard should be marked as Draining")
+
+	// Remove the last item, which triggers the `ShardBecameDrained` signal.
+	_, err = mq.Remove(item.Handle())
+	require.NoError(t, err, "Failed to remove last item from Draining shard")
+	h.synchronize() // Process the `BecameDrained` signal.
+
+	assert.Len(t, h.fr.Shards(), 1, "Drained shard was not garbage collected from the registry")
+
+	// Crucial memory leak check: ensure the shard's ID was purged from all flow states.
+	h.fr.mu.Lock()
+	defer h.fr.mu.Unlock()
+	flowState, exists := h.fr.flowStates[key]
+	require.True(t, exists, "Flow state should still exist for the Active flow")
+	assert.NotContains(t, flowState.emptyOnShards, drainingShard.ID(),
+		"Drained shard ID must be purged from flow state map to prevent memory leaks")
+}
+
+// --- Event Handling and State Machine Edge Cases ---
+
+func TestFlowRegistry_EventHandling_StaleSignals(t *testing.T) {
+	t.Parallel()
+
+	t.Run("ShouldIgnoreQueueSignal_ForGarbageCollectedFlow", func(t *testing.T) {
+		t.Parallel()
+		h := newRegistryTestHarness(t, harnessOptions{useFakeClock: true})
+		key := types.FlowKey{ID: "flow", Priority: 10}
+		require.NoError(t, h.fr.RegisterOrUpdateFlow(types.FlowSpecification{Key: key}),
+			"Test setup: failed to register flow")
+
+		h.setFlowActive(key, true)
+		h.synchronize()
+
+		// Manually (white-box) delete the flow from the registry's state map.
+		// This simulates a race where a signal is in-flight while the flow is being GC'd.
+		h.fr.mu.Lock()
+		delete(h.fr.flowStates, key)
+		h.fr.mu.Unlock()
+
+		// Now, trigger a `BecameEmpty` signal by making the flow Idle.
+		// The `onQueueStateChanged` handler should receive this, find no `flowState`, and return gracefully.
+		assert.NotPanics(t, func() {
+			h.setFlowActive(key, false)
+		}, "Registry should not panic when receiving a signal for a deleted flow")
+	})
+}
+
+// --- Invariant Panic Tests ---
+
+func TestFlowRegistry_InvariantPanics(t *testing.T) {
+	t.Parallel()
+
+	t.Run("ShouldPanic_WhenQueueIsMissingDuringGC", func(t *testing.T) {
+		t.Parallel()
+		h := newRegistryTestHarness(t, harnessOptions{})
+		key := types.FlowKey{ID: "flow", Priority: 10}
+		require.NoError(t, h.fr.RegisterOrUpdateFlow(types.FlowSpecification{Key: key}),
+			"Test setup: failed to register flow")
+
+		// Manually corrupt the state by removing the queue from a shard, creating an invariant violation.
+		// This is white-box testing to validate a critical failure path.
+		h.fr.mu.Lock()
+		shard := h.fr.activeShards[0]
+		shard.mu.Lock()
+		delete(shard.priorityBands[key.Priority].queues, key.ID)
+		shard.mu.Unlock()
+		h.fr.mu.Unlock()
+
+		// Manually prepare the flow for GC by setting its generation. This bypasses the need for the async `Run` loop,
+		// allowing us to catch the panic in this goroutine.
+		h.fr.mu.Lock()
+		h.fr.flowStates[key].lastActiveGeneration = h.fr.gcGeneration - 1 // Make it a candidate
+		h.fr.mu.Unlock()
+
+		assert.Panics(t, func() { // Value assertion is too brittle as it wraps an error.
+			h.fr.mu.Lock()
+			defer h.fr.mu.Unlock()
+			_ = h.fr.garbageCollectFlowLocked(key)
+		}, "GC must panic when a queue is missing for a tracked flow state")
+	})
+
+	t.Run("ShouldPanic_OnSignalFromUntrackedDrainingShard", func(t *testing.T) {
+		t.Parallel()
+		h := newRegistryTestHarness(t, harnessOptions{})
+		fakeEvent := &shardStateChangedEvent{
+			shardID: "shard-does-not-exist",
+			signal:  shardStateSignalBecameDrained,
+		}
+
+		assert.PanicsWithValue(t,
+			"invariant violation: shard shard-does-not-exist not found in draining map during GC",
+			func() {
+				h.fr.mu.Lock()
+				defer h.fr.mu.Unlock()
+				h.fr.onShardStateChanged(fakeEvent)
+			}, "Panic should occur when a non-existent shard signals it has drained")
+	})
+
+	t.Run("ShouldPanic_OnStatsForUnknownPriority", func(t *testing.T) {
+		t.Parallel()
+		h := newRegistryTestHarness(t, harnessOptions{})
+		assert.PanicsWithValue(t,
+			"invariant violation: priority band (999) stats missing during propagation",
+			func() {
+				h.fr.propagateStatsDelta(999, 1, 1) // 999 is not a configured priority.
+			},
+			"Panic should occur when stats are propagated for an unknown priority")
+	})
+
+	t.Run("ShouldPanic_OnComponentMismatchDuringSync", func(t *testing.T) {
+		t.Parallel()
+		h := newRegistryTestHarness(t, harnessOptions{})
+		spec := types.FlowSpecification{Key: types.FlowKey{ID: "flow", Priority: 10}}
+
+		assert.PanicsWithValue(t,
+			fmt.Sprintf("invariant violation: shard/queue/policy count mismatch during commit for flow %s", spec.Key),
+			func() {
+				h.fr.mu.Lock()
+				defer h.fr.mu.Unlock()
+				// Call with a mismatched number of components (0) vs. shards (1).
+				h.fr.applyFlowSynchronizationLocked(spec, []flowComponents{})
+			},
+			"Panic should occur when component count mismatches shard count")
+	})
+
+	t.Run("ShouldPanic_OnStatsAggregation_WithStateMismatch", func(t *testing.T) {
+		t.Parallel()
+		h := newRegistryTestHarness(t, harnessOptions{})
+
+		// Manually corrupt the state by adding a stats entry for a priority that does not exist in the configuration.
+		h.fr.mu.Lock()
+		h.fr.perPriorityBandStats[999] = &bandStats{}
+		h.fr.mu.Unlock()
+
+		assert.Panics(t, // Value assertion is too brittle as it wraps an error.
+			func() { h.fr.Stats() },
+			"Stats() must panic when perPriorityBandStats contains a key not in the config")
+	})
+}
diff --git a/pkg/epp/flowcontrol/registry/shard_test.go b/pkg/epp/flowcontrol/registry/shard_test.go
index b04bde4..aa1f06d 100644
--- a/pkg/epp/flowcontrol/registry/shard_test.go
+++ b/pkg/epp/flowcontrol/registry/shard_test.go
@@ -17,8 +17,7 @@ limitations under the License.
 package registry
 
 import (
-	"errors"
-	"slices"
+	"sync"
 	"testing"
 
 	"github.com/go-logr/logr"
@@ -27,314 +26,489 @@ import (
 
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/contracts"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework"
+	frameworkmocks "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/mocks"
 	inter "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/plugins/policies/interflow/dispatch"
-	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/plugins/policies/interflow/dispatch/besthead"
 	intra "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/plugins/policies/intraflow/dispatch"
-	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/plugins/policies/intraflow/dispatch/fcfs"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/plugins/queue"
-	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/framework/plugins/queue/listqueue"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/types"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/flowcontrol/types/mocks"
 )
 
-// shardTestFixture holds the components needed for a `registryShard` test.
-type shardTestFixture struct {
-	config *Config
-	shard  *registryShard
+// --- Test Harness and Mocks ---
+
+// shardTestHarness holds the components needed for a `registryShard` test.
+type shardTestHarness struct {
+	t               *testing.T
+	globalConfig    *Config
+	shard           *registryShard
+	shardSignaler   *mockShardSignalRecorder
+	statsPropagator *mockStatsPropagator
+	callbacks       shardCallbacks // Callbacks to be passed to `newShard`
 }
 
-// setupTestShard creates a new test fixture for testing the `registryShard`.
-func setupTestShard(t *testing.T) *shardTestFixture {
+// newShardTestHarness creates a new test harness for testing the `registryShard`.
+// It correctly simulates the parent registry's behavior by creating a global `Config`, partitioning it, and then
+// creating a shard from the partitioned `ShardConfig`.
+func newShardTestHarness(t *testing.T) *shardTestHarness {
 	t.Helper()
 
-	config := &Config{
+	globalConfig, err := NewConfig(Config{
 		PriorityBands: []PriorityBandConfig{
-			{
-				Priority:     10,
-				PriorityName: "High",
-			},
-			{
-				Priority:     20,
-				PriorityName: "Low",
-			},
+			{Priority: 10, PriorityName: "High"},
+			{Priority: 20, PriorityName: "Low"},
 		},
+	})
+	require.NoError(t, err, "Test setup: validating and defaulting config should not fail")
+
+	shardSignaler := &mockShardSignalRecorder{}
+	statsPropagator := &mockStatsPropagator{}
+	callbacks := shardCallbacks{
+		propagateStatsDelta: statsPropagator.propagate,
+		// For most tests, we don't care about queue signals, so this is a no-op.
+		signalQueueState: func(string, types.FlowKey, queueStateSignal) {},
+		signalShardState: shardSignaler.signal,
 	}
-	// Apply defaults to the master config first, as the parent registry would.
-	err := config.validateAndApplyDefaults()
-	require.NoError(t, err, "Setup: validating and defaulting config should not fail")
-
-	// The parent registry would partition the config. For a single shard test, we can use the defaulted one directly.
-	shard, err := newShard("test-shard-1", config, logr.Discard(), nil)
-	require.NoError(t, err, "Setup: newShard should not return an error")
-	require.NotNil(t, shard, "Setup: newShard should return a non-nil shard")
-
-	return &shardTestFixture{
-		config: config,
-		shard:  shard,
+
+	// Partition the global config to create a shard-specific config.
+	shardConfig := globalConfig.partition(0, 1)
+
+	shard, err := newShard("test-shard-1", shardConfig, logr.Discard(), callbacks, inter.NewPolicyFromName)
+	require.NoError(t, err, "Test setup: newShard should not return an error")
+
+	return &shardTestHarness{
+		t:               t,
+		globalConfig:    globalConfig,
+		shard:           shard,
+		shardSignaler:   shardSignaler,
+		statsPropagator: statsPropagator,
+		callbacks:       callbacks,
 	}
 }
 
-// _reconcileFlow_testOnly is a test helper that simulates the future admin logic for adding or updating a flow.
-// It creates a `managedQueue` and correctly populates the `priorityBands` map and the `flowKeys` slice.
-// This helper is intended to be replaced by the real `reconcileFlow` method in a future PR.
-func (s *registryShard) _reconcileFlow_testOnly(
-	t *testing.T,
-	flowSpec types.FlowSpecification,
-) *managedQueue {
-	t.Helper()
-
-	band, ok := s.priorityBands[flowSpec.Key.Priority]
-	require.True(t, ok, "Setup: priority band %d should exist", flowSpec.Key.Priority)
+// synchronizeFlowWithMocks is a test helper that simulates the parent registry's logic for calling `synchronizeFlow` on
+// the shard, but with mock plugins to ensure test isolation.
+func (h *shardTestHarness) synchronizeFlowWithMocks(key types.FlowKey, q framework.SafeQueue) {
+	h.t.Helper()
+	spec := types.FlowSpecification{Key: key}
+	mockPolicy := &frameworkmocks.MockIntraFlowDispatchPolicy{}
+	h.shard.synchronizeFlow(spec, mockPolicy, q)
+}
 
-	lq, err := queue.NewQueueFromName(listqueue.ListQueueName, nil)
-	require.NoError(t, err, "Setup: creating a real listqueue should not fail")
+// synchronizeFlowWithRealQueue is a test helper that uses a real queue implementation.
+// This is essential for integration and concurrency tests where the interaction between the shard and a real queue is
+// being validated.
+func (h *shardTestHarness) synchronizeFlowWithRealQueue(key types.FlowKey) {
+	h.t.Helper()
+	spec := types.FlowSpecification{Key: key}
+
+	// This logic correctly mimics the parent registry's instantiation process.
+	policy, err := intra.NewPolicyFromName(defaultIntraFlowDispatchPolicy)
+	require.NoError(h.t, err, "Test setup: failed to create real intra-flow policy")
+	q, err := queue.NewQueueFromName(defaultQueue, policy.Comparator())
+	require.NoError(h.t, err, "Test setup: failed to create real queue")
+	h.shard.synchronizeFlow(spec, policy, q)
+}
 
-	mq := newManagedQueue(
-		lq,
-		band.defaultIntraFlowDispatchPolicy,
-		flowSpec.Key,
-		logr.Discard(),
-		func(lenDelta, byteSizeDelta int64) { s.reconcileStats(flowSpec.Key.Priority, lenDelta, byteSizeDelta) },
-	)
-	require.NotNil(t, mq, "Setup: newManagedQueue should not return nil")
+// addItem adds an item to a specific flow on the shard, failing the test on any error.
+func (h *shardTestHarness) addItem(key types.FlowKey, size uint64) types.QueueItemAccessor {
+	h.t.Helper()
+	mq, err := h.shard.ManagedQueue(key)
+	require.NoError(h.t, err, "Helper addItem: failed to get queue for flow %v", key)
+	item := mocks.NewMockQueueItemAccessor(size, "req", key)
+	require.NoError(h.t, mq.Add(item), "Helper addItem: failed to add item to queue")
+	return item
+}
 
-	// Add the queue to the map and update the cached key slice.
-	band.queues[flowSpec.Key] = mq
-	band.flowKeys = append(band.flowKeys, flowSpec.Key)
+// removeItem removes an item from a specific flow, failing the test on any error.
+func (h *shardTestHarness) removeItem(key types.FlowKey, item types.QueueItemAccessor) {
+	h.t.Helper()
+	mq, err := h.shard.ManagedQueue(key)
+	require.NoError(h.t, err, "Helper removeItem: failed to get queue for flow %v", key)
+	_, err = mq.Remove(item.Handle())
+	require.NoError(h.t, err, "Helper removeItem: failed to remove item from queue")
+}
 
-	return mq
+// mockShardSignalRecorder is a thread-safe helper for recording shard state signals.
+type mockShardSignalRecorder struct {
+	mu      sync.Mutex
+	signals []shardStateSignal
 }
 
-func TestNewShard(t *testing.T) {
-	t.Parallel()
-	f := setupTestShard(t)
-
-	assert.Equal(t, "test-shard-1", f.shard.ID(), "ID should be set correctly")
-	assert.True(t, f.shard.IsActive(), "A new shard should be active")
-	require.Len(t, f.shard.priorityBands, 2, "Should have 2 priority bands")
-
-	// Check that priority levels are sorted correctly
-	assert.Equal(t, []uint{10, 20}, f.shard.AllOrderedPriorityLevels(), "Priority levels should be ordered")
-
-	// Check band 10
-	band10, ok := f.shard.priorityBands[10]
-	require.True(t, ok, "Priority band 10 should exist")
-	assert.Equal(t, uint(10), band10.config.Priority, "Band 10 should have correct priority")
-	assert.Equal(t, "High", band10.config.PriorityName, "Band 10 should have correct name")
-	assert.NotNil(t, band10.interFlowDispatchPolicy, "Inter-flow policy for band 10 should be instantiated")
-	assert.NotNil(t, band10.defaultIntraFlowDispatchPolicy,
-		"Default intra-flow policy for band 10 should be instantiated")
-	assert.Equal(t, besthead.BestHeadPolicyName, band10.interFlowDispatchPolicy.Name(),
-		"Correct default inter-flow policy should be used")
-	assert.Equal(t, fcfs.FCFSPolicyName, band10.defaultIntraFlowDispatchPolicy.Name(),
-		"Correct default intra-flow policy should be used")
-
-	// Check band 20
-	band20, ok := f.shard.priorityBands[20]
-	require.True(t, ok, "Priority band 20 should exist")
-	assert.Equal(t, uint(20), band20.config.Priority, "Band 20 should have correct priority")
-	assert.Equal(t, "Low", band20.config.PriorityName, "Band 20 should have correct name")
-	assert.NotNil(t, band20.interFlowDispatchPolicy, "Inter-flow policy for band 20 should be instantiated")
-	assert.NotNil(t, band20.defaultIntraFlowDispatchPolicy,
-		"Default intra-flow policy for band 20 should be instantiated")
+func (r *mockShardSignalRecorder) signal(_ string, signal shardStateSignal) {
+	r.mu.Lock()
+	defer r.mu.Unlock()
+	r.signals = append(r.signals, signal)
 }
 
-// TestNewShard_ErrorPaths modifies global plugin registries, so it cannot be run in parallel with other tests.
-func TestNewShard_ErrorPaths(t *testing.T) {
-	baseConfig := &Config{
-		PriorityBands: []PriorityBandConfig{{
-			Priority:                10,
-			PriorityName:            "High",
-			IntraFlowDispatchPolicy: fcfs.FCFSPolicyName,
-			InterFlowDispatchPolicy: besthead.BestHeadPolicyName,
-			Queue:                   listqueue.ListQueueName,
-		}},
-	}
-	require.NoError(t, baseConfig.validateAndApplyDefaults(), "Setup: base config should be valid")
+func (r *mockShardSignalRecorder) getSignals() []shardStateSignal {
+	r.mu.Lock()
+	defer r.mu.Unlock()
+	signalsCopy := make([]shardStateSignal, len(r.signals))
+	copy(signalsCopy, r.signals)
+	return signalsCopy
+}
 
-	t.Run("Invalid InterFlow Policy", func(t *testing.T) {
-		// Register a mock policy that always fails to instantiate
-		failingPolicyName := inter.RegisteredPolicyName("failing-inter-policy")
-		inter.MustRegisterPolicy(failingPolicyName, func() (framework.InterFlowDispatchPolicy, error) {
-			return nil, errors.New("inter-flow instantiation failed")
-		})
+// --- Basic Tests ---
 
-		badConfig := *baseConfig
-		badConfig.PriorityBands[0].InterFlowDispatchPolicy = failingPolicyName
+func TestShard_New(t *testing.T) {
+	t.Parallel()
+	h := newShardTestHarness(t)
 
-		_, err := newShard("test", &badConfig, logr.Discard(), nil)
-		require.Error(t, err, "newShard should fail with an invalid inter-flow policy")
-	})
+	assert.Equal(t, "test-shard-1", h.shard.ID(), "ID should be set correctly")
+	assert.True(t, h.shard.IsActive(), "A new shard should be active by default")
+	assert.Equal(t, []uint{10, 20}, h.shard.AllOrderedPriorityLevels(), "Priority levels should be correctly ordered")
 
-	t.Run("Invalid IntraFlow Policy", func(t *testing.T) {
-		// Register a mock policy that always fails to instantiate
-		failingPolicyName := intra.RegisteredPolicyName("failing-intra-policy")
-		intra.MustRegisterPolicy(failingPolicyName, func() (framework.IntraFlowDispatchPolicy, error) {
-			return nil, errors.New("intra-flow instantiation failed")
-		})
+	bandHigh, ok := h.shard.priorityBands[10]
+	require.True(t, ok, "High priority band should exist")
+	assert.Equal(t, "High", bandHigh.config.PriorityName, "High priority band should have correct name")
+	assert.NotNil(t, bandHigh.interFlowDispatchPolicy, "Inter-flow policy should be instantiated")
+	assert.Equal(t, string(defaultInterFlowDispatchPolicy), bandHigh.interFlowDispatchPolicy.Name(),
+		"Correct default inter-flow policy should be used")
+}
 
-		badConfig := *baseConfig
-		badConfig.PriorityBands[0].IntraFlowDispatchPolicy = failingPolicyName
+func TestShard_New_ErrorPaths(t *testing.T) {
+	t.Parallel()
 
-		_, err := newShard("test", &badConfig, logr.Discard(), nil)
-		require.Error(t, err, "newShard should fail with an invalid intra-flow policy")
+	t.Run("ShouldFail_WhenInterFlowPolicyIsMissing", func(t *testing.T) {
+		t.Parallel()
+		shardConfig := &ShardConfig{
+			PriorityBands: []ShardPriorityBandConfig{{Priority: 10, PriorityName: "High"}},
+		}
+		_, err := newShard("test-shard-1", shardConfig, logr.Discard(), shardCallbacks{}, inter.NewPolicyFromName)
+		assert.Error(t, err, "newShard should fail when missing a configured inter-flow policy")
 	})
 }
 
 func TestShard_Stats(t *testing.T) {
 	t.Parallel()
-	f := setupTestShard(t)
+	h := newShardTestHarness(t)
+	flowKeyHigh := types.FlowKey{ID: "flow1", Priority: 10}
+	h.synchronizeFlowWithMocks(flowKeyHigh, &frameworkmocks.MockSafeQueue{})
+	h.addItem(flowKeyHigh, 100)
+	h.addItem(flowKeyHigh, 50)
 
-	// Add a queue and some items to test stats aggregation
-	flowKey := types.FlowKey{ID: "flow1", Priority: 10}
-	mq := f.shard._reconcileFlow_testOnly(t, types.FlowSpecification{Key: flowKey})
+	stats := h.shard.Stats()
 
-	// Add items
-	require.NoError(t, mq.Add(mocks.NewMockQueueItemAccessor(100, "req1", flowKey)), "Adding item should not fail")
-	require.NoError(t, mq.Add(mocks.NewMockQueueItemAccessor(50, "req2", flowKey)), "Adding item should not fail")
-
-	stats := f.shard.Stats()
-
-	// Check shard-level stats
 	assert.Equal(t, uint64(2), stats.TotalLen, "Total length should be 2")
 	assert.Equal(t, uint64(150), stats.TotalByteSize, "Total byte size should be 150")
 
-	// Check per-band stats
-	require.Len(t, stats.PerPriorityBandStats, 2, "Should have stats for 2 bands")
-	band10Stats := stats.PerPriorityBandStats[10]
-	assert.Equal(t, uint(10), band10Stats.Priority, "Band 10 stats should have correct priority")
-	assert.Equal(t, uint64(2), band10Stats.Len, "Band 10 length should be 2")
-	assert.Equal(t, uint64(150), band10Stats.ByteSize, "Band 10 byte size should be 150")
-
-	band20Stats := stats.PerPriorityBandStats[20]
-	assert.Equal(t, uint(20), band20Stats.Priority, "Band 20 stats should have correct priority")
-	assert.Zero(t, band20Stats.Len, "Band 20 length should be 0")
-	assert.Zero(t, band20Stats.ByteSize, "Band 20 byte size should be 0")
+	bandHighStats := stats.PerPriorityBandStats[10]
+	assert.Equal(t, uint64(2), bandHighStats.Len, "High priority band length should be 2")
+	assert.Equal(t, uint64(150), bandHighStats.ByteSize, "High priority band byte size should be 150")
+
+	bandLowStats := stats.PerPriorityBandStats[20]
+	assert.Zero(t, bandLowStats.Len, "Low priority band length should be 0")
 }
 
-func TestShard_Accessors(t *testing.T) {
+func TestShard_Accessors_SuccessPaths(t *testing.T) {
 	t.Parallel()
-	f := setupTestShard(t)
-
-	key1 := types.FlowKey{ID: "flow1", Priority: 10}
-	key2 := types.FlowKey{ID: "flow2", Priority: 20}
+	h := newShardTestHarness(t)
+	flowKey := types.FlowKey{ID: "test-flow", Priority: 10}
+	h.synchronizeFlowWithRealQueue(flowKey)
 
-	// Setup state
-	queue1 := f.shard._reconcileFlow_testOnly(t, types.FlowSpecification{Key: key1})
-	f.shard._reconcileFlow_testOnly(t, types.FlowSpecification{Key: key2})
-
-	t.Run("ManagedQueue", func(t *testing.T) {
+	t.Run("ManagedQueue_ShouldReturnCorrectInstance", func(t *testing.T) {
 		t.Parallel()
-		retrievedQueue, err := f.shard.ManagedQueue(key1)
-		require.NoError(t, err, "ManagedQueue should not error for an existing key")
-		assert.Same(t, queue1, retrievedQueue, "Should return the correct queue")
-
-		_, err = f.shard.ManagedQueue(types.FlowKey{ID: "non-existent", Priority: 10})
-		require.Error(t, err, "ManagedQueue should error for a non-existent flow key")
-		assert.ErrorIs(t, err, contracts.ErrFlowInstanceNotFound, "Error should be ErrFlowInstanceNotFound")
+		mq, err := h.shard.ManagedQueue(flowKey)
 
-		_, err = f.shard.ManagedQueue(types.FlowKey{ID: "flow1", Priority: 99}) // Non-existent priority
-		require.Error(t, err, "ManagedQueue should error for a non-existent priority")
-		assert.ErrorIs(t, err, contracts.ErrPriorityBandNotFound, "Error should be ErrPriorityBandNotFound")
+		require.NoError(t, err, "ManagedQueue should not error for an existing flow")
+		require.NotNil(t, mq, "Returned ManagedQueue should not be nil")
+		accessor := mq.FlowQueueAccessor()
+		assert.Equal(t, flowKey, accessor.FlowKey(), "Returned queue should have the correct flow key")
 	})
 
-	t.Run("IntraFlowDispatchPolicy", func(t *testing.T) {
+	t.Run("IntraFlowDispatchPolicy_ShouldReturnCorrectInstance", func(t *testing.T) {
 		t.Parallel()
-		retrievedPolicy, err := f.shard.IntraFlowDispatchPolicy(key1)
-		require.NoError(t, err, "IntraFlowDispatchPolicy should not error for an existing key")
-		assert.Same(t, queue1.dispatchPolicy, retrievedPolicy, "Should return the policy from the correct instance")
+		policy, err := h.shard.IntraFlowDispatchPolicy(flowKey)
 
-		_, err = f.shard.IntraFlowDispatchPolicy(types.FlowKey{ID: "non-existent", Priority: 10})
-		require.Error(t, err, "IntraFlowDispatchPolicy should error for a non-existent flow")
-		assert.ErrorIs(t, err, contracts.ErrFlowInstanceNotFound, "Error should be ErrFlowInstanceNotFound")
+		require.NoError(t, err, "IntraFlowDispatchPolicy should not error for an existing flow")
+		require.NotNil(t, policy, "Returned policy should not be nil")
+		assert.Equal(t, string(defaultIntraFlowDispatchPolicy), policy.Name(),
+			"Should return the correct default policy for the band")
 	})
 
-	t.Run("InterFlowDispatchPolicy", func(t *testing.T) {
+	t.Run("InterFlowDispatchPolicy_ShouldReturnCorrectInstance", func(t *testing.T) {
 		t.Parallel()
-		retrievedInterPolicy, err := f.shard.InterFlowDispatchPolicy(10)
-		require.NoError(t, err, "InterFlowDispatchPolicy should not error for an existing priority")
-		assert.Same(t, f.shard.priorityBands[10].interFlowDispatchPolicy, retrievedInterPolicy,
-			"Should return the correct inter-flow policy")
+		policy, err := h.shard.InterFlowDispatchPolicy(uint(10))
 
-		_, err = f.shard.InterFlowDispatchPolicy(99) // Non-existent priority
-		require.Error(t, err, "InterFlowDispatchPolicy should error for a non-existent priority")
-		assert.ErrorIs(t, err, contracts.ErrPriorityBandNotFound, "Error should be ErrPriorityBandNotFound")
+		require.NoError(t, err, "InterFlowDispatchPolicy should not error for an existing priority")
+		require.NotNil(t, policy, "Returned policy should not be nil")
+		assert.Equal(t, string(defaultInterFlowDispatchPolicy), policy.Name(),
+			"Should return the correct default policy for the band")
 	})
 }
 
+func TestShard_Accessors_ErrorPaths(t *testing.T) {
+	t.Parallel()
+	h := newShardTestHarness(t)
+	flowKey := types.FlowKey{ID: "flow-a", Priority: 10}
+	h.synchronizeFlowWithMocks(flowKey, &frameworkmocks.MockSafeQueue{})
+
+	testCases := []struct {
+		name      string
+		action    func() error
+		expectErr error
+	}{
+		{
+			name:      "ManagedQueue_PriorityNotFound",
+			action:    func() error { _, err := h.shard.ManagedQueue(types.FlowKey{ID: "flow-a", Priority: 99}); return err },
+			expectErr: contracts.ErrPriorityBandNotFound,
+		},
+		{
+			name:      "ManagedQueue_FlowNotFound",
+			action:    func() error { _, err := h.shard.ManagedQueue(types.FlowKey{ID: "missing", Priority: 10}); return err },
+			expectErr: contracts.ErrFlowInstanceNotFound,
+		},
+		{
+			name:      "InterFlowDispatchPolicy_PriorityNotFound",
+			action:    func() error { _, err := h.shard.InterFlowDispatchPolicy(99); return err },
+			expectErr: contracts.ErrPriorityBandNotFound,
+		},
+		{
+			name: "IntraFlowDispatchPolicy_PriorityNotFound",
+			action: func() error {
+				_, err := h.shard.IntraFlowDispatchPolicy(types.FlowKey{ID: "flow-a", Priority: 99})
+				return err
+			},
+			expectErr: contracts.ErrPriorityBandNotFound,
+		},
+		{
+			name: "IntraFlowDispatchPolicy_FlowNotFound",
+			action: func() error {
+				_, err := h.shard.IntraFlowDispatchPolicy(types.FlowKey{ID: "missing", Priority: 10})
+				return err
+			},
+			expectErr: contracts.ErrFlowInstanceNotFound,
+		},
+	}
+
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			t.Parallel()
+			err := tc.action()
+			require.Error(t, err, "Action should have returned an error")
+			assert.ErrorIs(t, err, tc.expectErr, "Error should wrap the expected sentinel error")
+		})
+	}
+}
+
 func TestShard_PriorityBandAccessor(t *testing.T) {
 	t.Parallel()
-	f := setupTestShard(t)
 
-	// Setup shard state for the tests
-	p1, p2 := uint(10), uint(20)
-	key1P1 := types.FlowKey{ID: "flow1", Priority: p1}
-	key1P2 := types.FlowKey{ID: "flow1", Priority: p2}
-	key2P2 := types.FlowKey{ID: "flow2", Priority: p2}
+	// The shard will have two flows in the "High" priority band and one in the "Low" band.
+	h := newShardTestHarness(t)
+	highPriorityKey1 := types.FlowKey{ID: "flow1", Priority: 10}
+	highPriorityKey2 := types.FlowKey{ID: "flow2", Priority: 10}
+	lowPriorityKey := types.FlowKey{ID: "flow3", Priority: 20}
 
-	f.shard._reconcileFlow_testOnly(t, types.FlowSpecification{Key: key1P1})
-	f.shard._reconcileFlow_testOnly(t, types.FlowSpecification{Key: key1P2})
-	f.shard._reconcileFlow_testOnly(t, types.FlowSpecification{Key: key2P2})
+	h.synchronizeFlowWithMocks(highPriorityKey1, &frameworkmocks.MockSafeQueue{})
+	h.synchronizeFlowWithMocks(highPriorityKey2, &frameworkmocks.MockSafeQueue{})
+	h.synchronizeFlowWithMocks(lowPriorityKey, &frameworkmocks.MockSafeQueue{})
 
-	t.Run("Accessor for existing priority", func(t *testing.T) {
+	t.Run("ShouldFail_WhenPriorityDoesNotExist", func(t *testing.T) {
 		t.Parallel()
-		accessor, err := f.shard.PriorityBandAccessor(p2)
-		require.NoError(t, err, "PriorityBandAccessor should not fail for existing priority")
+		_, err := h.shard.PriorityBandAccessor(99)
+		require.Error(t, err, "PriorityBandAccessor should fail for a non-existent priority")
+		assert.ErrorIs(t, err, contracts.ErrPriorityBandNotFound, "Error should be ErrPriorityBandNotFound")
+	})
+
+	t.Run("ShouldSucceed_WhenPriorityExists", func(t *testing.T) {
+		t.Parallel()
+		accessor, err := h.shard.PriorityBandAccessor(10)
+		require.NoError(t, err, "PriorityBandAccessor should not fail for an existing priority")
 		require.NotNil(t, accessor, "Accessor should not be nil")
 
-		t.Run("Properties", func(t *testing.T) {
+		t.Run("Properties_ShouldReturnCorrectValues", func(t *testing.T) {
 			t.Parallel()
-			assert.Equal(t, p2, accessor.Priority(), "Accessor should have correct priority")
-			assert.Equal(t, "Low", accessor.PriorityName(), "Accessor should have correct priority name")
+			assert.Equal(t, uint(10), accessor.Priority(), "Accessor should have the correct priority")
+			assert.Equal(t, "High", accessor.PriorityName(), "Accessor should have the correct priority name")
 		})
 
-		t.Run("FlowKeys", func(t *testing.T) {
+		t.Run("FlowKeys_ShouldReturnAllKeysInBand", func(t *testing.T) {
 			t.Parallel()
-			flowKeys := accessor.FlowKeys()
-			// Sort for consistent comparison as map iteration order is not guaranteed.
-			slices.SortFunc(flowKeys, func(a, b types.FlowKey) int {
-				return a.Compare(b)
-			})
-			assert.Equal(t, []types.FlowKey{key1P2, key2P2}, flowKeys,
-				"Accessor should return correct flow keys for the priority band")
+			keys := accessor.FlowKeys()
+			expectedKeys := []types.FlowKey{highPriorityKey1, highPriorityKey2}
+			assert.ElementsMatch(t, expectedKeys, keys,
+				"Accessor should return all flow keys for the priority band")
 		})
 
-		t.Run("Queue", func(t *testing.T) {
+		t.Run("Queue_ShouldReturnCorrectAccessor", func(t *testing.T) {
 			t.Parallel()
 			q := accessor.Queue("flow1")
-			require.NotNil(t, q, "Accessor should return queue for flow1")
-			assert.Equal(t, p2, q.FlowKey().Priority, "Queue should have the correct priority")
-			assert.Nil(t, accessor.Queue("non-existent"), "Accessor should return nil for non-existent flow")
+			require.NotNil(t, q, "Accessor should return a non-nil accessor for an existing flow")
+			assert.Equal(t, highPriorityKey1, q.FlowKey(), "Queue accessor should have the correct flow key")
+			assert.Nil(t, accessor.Queue("non-existent"), "Accessor should return nil for a non-existent flow")
 		})
 
-		t.Run("IterateQueues", func(t *testing.T) {
+		t.Run("IterateQueues_ShouldVisitAllQueuesInBand", func(t *testing.T) {
 			t.Parallel()
 			var iteratedKeys []types.FlowKey
 			accessor.IterateQueues(func(queue framework.FlowQueueAccessor) bool {
 				iteratedKeys = append(iteratedKeys, queue.FlowKey())
 				return true
 			})
-			slices.SortFunc(iteratedKeys, func(a, b types.FlowKey) int {
-				return a.Compare(b)
-			})
-			assert.Equal(t, []types.FlowKey{key1P2, key2P2}, iteratedKeys, "IterateQueues should visit all flows in the band")
+			expectedKeys := []types.FlowKey{highPriorityKey1, highPriorityKey2}
+			assert.ElementsMatch(t, expectedKeys, iteratedKeys, "IterateQueues should visit all flows in the band")
 		})
 
-		t.Run("IterateQueues with early exit", func(t *testing.T) {
+		t.Run("IterateQueues_ShouldExitEarly_WhenCallbackReturnsFalse", func(t *testing.T) {
 			t.Parallel()
-			var iteratedKeys []types.FlowKey
+			var iterationCount int
 			accessor.IterateQueues(func(queue framework.FlowQueueAccessor) bool {
-				iteratedKeys = append(iteratedKeys, queue.FlowKey())
-				return false // Exit after first item
+				iterationCount++
+				return false // Signal to stop iteration immediately.
 			})
-			assert.Len(t, iteratedKeys, 1, "IterateQueues should exit early if callback returns false")
+			assert.Equal(t, 1, iterationCount, "IterateQueues should exit after the first item")
 		})
 	})
+}
+
+// --- Lifecycle and State Management Tests ---
+
+func TestShard_SynchronizeFlow(t *testing.T) {
+	t.Parallel()
+	h := newShardTestHarness(t)
+	flowKey := types.FlowKey{ID: "flow1", Priority: 10}
 
-	t.Run("Error on non-existent priority", func(t *testing.T) {
+	// Synchronization should create the queue.
+	h.synchronizeFlowWithMocks(flowKey, &frameworkmocks.MockSafeQueue{})
+	mq1, err := h.shard.ManagedQueue(flowKey)
+	require.NoError(t, err, "Queue should exist after first synchronization")
+	assert.Contains(t, h.shard.priorityBands[10].queues, flowKey.ID,
+		"Queue should be in the correct priority band map")
+
+	// Synchronization should be idempotent.
+	h.synchronizeFlowWithMocks(flowKey, &frameworkmocks.MockSafeQueue{})
+	mq2, err := h.shard.ManagedQueue(flowKey)
+	require.NoError(t, err, "Queue should still exist after second synchronization")
+	assert.Same(t, mq1, mq2, "Queue instance should not have been replaced on second sync")
+}
+
+func TestShard_GarbageCollect(t *testing.T) {
+	t.Parallel()
+	h := newShardTestHarness(t)
+	flowKey := types.FlowKey{ID: "flow1", Priority: 10}
+	h.synchronizeFlowWithMocks(flowKey, &frameworkmocks.MockSafeQueue{})
+	require.Contains(t, h.shard.priorityBands[10].queues, flowKey.ID, "Test setup: queue must exist before GC")
+
+	h.shard.garbageCollectLocked(flowKey)
+	assert.NotContains(t, h.shard.priorityBands[10].queues, flowKey.ID,
+		"Queue should have been removed from the priority band")
+}
+
+// --- Draining Lifecycle and Concurrency Tests ---
+
+func TestShard_Lifecycle_Draining(t *testing.T) {
+	t.Parallel()
+
+	t.Run("ShouldTransitionToDraining_WhenMarkedWhileNonEmpty", func(t *testing.T) {
 		t.Parallel()
-		_, err := f.shard.PriorityBandAccessor(99)
-		require.Error(t, err, "PriorityBandAccessor should fail for non-existent priority")
-		assert.ErrorIs(t, err, contracts.ErrPriorityBandNotFound, "Error should be ErrPriorityBandNotFound")
+		h := newShardTestHarness(t)
+		flowKey := types.FlowKey{ID: "flow1", Priority: 10}
+		h.synchronizeFlowWithMocks(flowKey, &frameworkmocks.MockSafeQueue{})
+		h.addItem(flowKey, 100)
+
+		h.shard.markAsDraining()
+		assert.False(t, h.shard.IsActive(), "Shard should no longer be active")
+		assert.Equal(t, componentStatusDraining, componentStatus(h.shard.status.Load()), "Shard status should be Draining")
+	})
+
+	t.Run("ShouldTransitionToDrainedAndSignal_WhenMarkedWhileEmpty", func(t *testing.T) {
+		t.Parallel()
+		h := newShardTestHarness(t)
+		h.shard.markAsDraining()
+		assert.Equal(t, componentStatusDrained, componentStatus(h.shard.status.Load()), "Shard status should be Drained")
+		assert.Equal(t, []shardStateSignal{shardStateSignalBecameDrained}, h.shardSignaler.getSignals(),
+			"Should have sent BecameDrained signal")
+	})
+
+	t.Run("ShouldTransitionToDrainedAndSignal_WhenLastItemIsRemoved", func(t *testing.T) {
+		t.Parallel()
+		h := newShardTestHarness(t)
+		flowKey := types.FlowKey{ID: "flow1", Priority: 10}
+		h.synchronizeFlowWithRealQueue(flowKey)
+		item := h.addItem(flowKey, 100)
+
+		h.shard.markAsDraining()
+		require.Equal(t, componentStatusDraining, componentStatus(h.shard.status.Load()),
+			"Shard should be Draining while it contains items")
+
+		h.removeItem(flowKey, item)
+		assert.Equal(t, componentStatusDrained, componentStatus(h.shard.status.Load()),
+			"Shard should become Drained after last item is removed")
+		assert.Len(t, h.shardSignaler.getSignals(), 1, "A signal should have been sent")
+	})
+}
+
+// TestShard_Concurrency_DrainingRace targets the race between `markAsDraining()` and the shard becoming empty via
+// concurrent item removals. It proves the atomic CAS correctly arbitrates the race and signals exactly once.
+func TestShard_Concurrency_DrainingRace(t *testing.T) {
+	t.Parallel()
+	h := newShardTestHarness(t)
+	flowKey := types.FlowKey{ID: "flow1", Priority: 10}
+	h.synchronizeFlowWithRealQueue(flowKey)
+	item := h.addItem(flowKey, 1)
+
+	var wg sync.WaitGroup
+	wg.Add(2)
+
+	// Goroutine 1: Attempts to mark the shard as draining.
+	go func() {
+		defer wg.Done()
+		h.shard.markAsDraining()
+	}()
+
+	// Goroutine 2: Concurrently removes the single item.
+	go func() {
+		defer wg.Done()
+		h.removeItem(flowKey, item)
+	}()
+
+	wg.Wait()
+
+	// Verification: No matter which operation "won" the race, the final state must be Drained, and the signal must have
+	// been sent exactly once.
+	assert.Equal(t, componentStatusDrained, componentStatus(h.shard.status.Load()), "Final state must be Drained")
+	assert.Len(t, h.shardSignaler.getSignals(), 1, "BecameDrained signal must be sent exactly once")
+}
+
+// --- Invariant Panic Tests ---
+
+func TestShard_PanicOnCorruption(t *testing.T) {
+	t.Parallel()
+
+	t.Run("ShouldPanic_WhenStatsPropagatedForUnknownPriority", func(t *testing.T) {
+		t.Parallel()
+		h := newShardTestHarness(t)
+		invalidPriority := uint(99)
+		assert.Panics(t, func() {
+			// This simulates a corrupted callback from a rogue `managedQueue`.
+			h.shard.propagateStatsDelta(invalidPriority, 1, 1)
+		}, "propagateStatsDelta must panic for an unknown priority")
+	})
+
+	t.Run("ShouldPanic_WhenUpdatingConfigWithMissingPriority", func(t *testing.T) {
+		t.Parallel()
+		h := newShardTestHarness(t)
+
+		// Create a new config that is missing one of the shard's existing bands (priority 20).
+		newGlobalConfig, _ := NewConfig(Config{
+			PriorityBands: []PriorityBandConfig{{Priority: 10, PriorityName: "High-Updated"}},
+		})
+		newShardConfig := newGlobalConfig.partition(0, 1)
+
+		assert.Panics(t, func() {
+			h.shard.updateConfig(newShardConfig)
+		}, "updateConfig must panic when an existing priority is missing from the new config")
+	})
+
+	t.Run("ShouldPanic_WhenSynchronizingFlowWithMissingPriority", func(t *testing.T) {
+		t.Parallel()
+		h := newShardTestHarness(t)
+		assert.Panics(t, func() {
+			h.shard.synchronizeFlow(
+				types.FlowSpecification{Key: types.FlowKey{ID: "flow", Priority: 99}},
+				&frameworkmocks.MockIntraFlowDispatchPolicy{},
+				&frameworkmocks.MockSafeQueue{})
+		}, "synchronizeFlow must panic for an unknown priority")
 	})
 }
diff --git a/pkg/epp/requestcontrol/director_test.go b/pkg/epp/requestcontrol/director_test.go
index e7968d4..a0cb7c3 100644
--- a/pkg/epp/requestcontrol/director_test.go
+++ b/pkg/epp/requestcontrol/director_test.go
@@ -34,6 +34,7 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/client/fake"
 
 	v1 "sigs.k8s.io/gateway-api-inference-extension/api/v1"
+	"sigs.k8s.io/gateway-api-inference-extension/apix/v1alpha2"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend"
 	backendmetrics "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend/metrics"
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/datastore"
@@ -53,7 +54,7 @@ type mockSaturationDetector struct {
 	isSaturated bool
 }
 
-func (m *mockSaturationDetector) IsSaturated(_ context.Context) bool {
+func (m *mockSaturationDetector) IsSaturated(_ context.Context, _ []backendmetrics.PodMetrics) bool {
 	return m.isSaturated
 }
 
@@ -66,6 +67,23 @@ func (m *mockScheduler) Schedule(_ context.Context, _ *schedulingtypes.LLMReques
 	return m.scheduleResults, m.scheduleErr
 }
 
+type mockDatastore struct {
+	pods []backendmetrics.PodMetrics
+}
+
+func (ds *mockDatastore) PoolGet() (*v1.InferencePool, error)                { return nil, nil }
+func (ds *mockDatastore) ObjectiveGet(_ string) *v1alpha2.InferenceObjective { return nil }
+func (ds *mockDatastore) PodList(predicate func(backendmetrics.PodMetrics) bool) []backendmetrics.PodMetrics {
+	res := []backendmetrics.PodMetrics{}
+	for _, pod := range ds.pods {
+		if predicate(pod) {
+			res = append(res, pod)
+		}
+	}
+
+	return res
+}
+
 func TestDirector_HandleRequest(t *testing.T) {
 	ctx := logutil.NewTestLoggerIntoContext(context.Background())
 
@@ -450,119 +468,72 @@ func TestGetCandidatePodsForScheduling(t *testing.T) {
 		}
 	}
 
-	testInput := []*corev1.Pod{
-		{
-			ObjectMeta: metav1.ObjectMeta{
-				Name: "pod1",
-			},
-			Status: corev1.PodStatus{
-				PodIP: "10.0.0.1",
-			},
-		},
-		{
-			ObjectMeta: metav1.ObjectMeta{
-				Name: "pod2",
-			},
-			Status: corev1.PodStatus{
-				PodIP: "10.0.0.2",
-			},
-		},
-	}
-
-	outputPod1 := &backend.Pod{
+	pod1 := &backend.Pod{
 		NamespacedName: types.NamespacedName{Name: "pod1"},
 		Address:        "10.0.0.1",
 		Labels:         map[string]string{},
 	}
 
-	outputPod2 := &backend.Pod{
+	pod2 := &backend.Pod{
 		NamespacedName: types.NamespacedName{Name: "pod2"},
 		Address:        "10.0.0.2",
 		Labels:         map[string]string{},
 	}
 
+	testInput := []backendmetrics.PodMetrics{
+		&backendmetrics.FakePodMetrics{Pod: pod1},
+		&backendmetrics.FakePodMetrics{Pod: pod2},
+	}
+
 	tests := []struct {
 		name     string
 		metadata map[string]any
-		output   []schedulingtypes.Pod
+		output   []backendmetrics.PodMetrics
 	}{
 		{
 			name:     "SubsetFilter, filter not present — return all pods",
 			metadata: map[string]any{},
-			output: []schedulingtypes.Pod{
-				&schedulingtypes.PodMetrics{
-					Pod:          outputPod1,
-					MetricsState: backendmetrics.NewMetricsState(),
-				},
-				&schedulingtypes.PodMetrics{
-					Pod:          outputPod2,
-					MetricsState: backendmetrics.NewMetricsState(),
-				},
-			},
+			output:   testInput,
 		},
 		{
 			name:     "SubsetFilter, namespace present filter not present — return all pods",
 			metadata: map[string]any{metadata.SubsetFilterNamespace: map[string]any{}},
-			output: []schedulingtypes.Pod{
-				&schedulingtypes.PodMetrics{
-					Pod:          outputPod1,
-					MetricsState: backendmetrics.NewMetricsState(),
-				},
-				&schedulingtypes.PodMetrics{
-					Pod:          outputPod2,
-					MetricsState: backendmetrics.NewMetricsState(),
-				},
-			},
+			output:   testInput,
 		},
 		{
 			name:     "SubsetFilter, filter present with empty list — return error",
 			metadata: makeFilterMetadata([]any{}),
-			output:   []schedulingtypes.Pod{},
+			output:   []backendmetrics.PodMetrics{},
 		},
 		{
 			name:     "SubsetFilter, subset with one matching pod",
 			metadata: makeFilterMetadata([]any{"10.0.0.1"}),
-			output: []schedulingtypes.Pod{
-				&schedulingtypes.PodMetrics{
-					Pod:          outputPod1,
-					MetricsState: backendmetrics.NewMetricsState(),
+			output: []backendmetrics.PodMetrics{
+				&backendmetrics.FakePodMetrics{
+					Pod: pod1,
 				},
 			},
 		},
 		{
 			name:     "SubsetFilter, subset with multiple matching pods",
 			metadata: makeFilterMetadata([]any{"10.0.0.1", "10.0.0.2", "10.0.0.3"}),
-			output: []schedulingtypes.Pod{
-				&schedulingtypes.PodMetrics{
-					Pod:          outputPod1,
-					MetricsState: backendmetrics.NewMetricsState(),
-				},
-				&schedulingtypes.PodMetrics{
-					Pod:          outputPod2,
-					MetricsState: backendmetrics.NewMetricsState(),
-				},
-			},
+			output:   testInput,
 		},
 		{
 			name:     "SubsetFilter, subset with no matching pods",
 			metadata: makeFilterMetadata([]any{"10.0.0.3"}),
-			output:   []schedulingtypes.Pod{},
+			output:   []backendmetrics.PodMetrics{},
 		},
 	}
 
-	pmf := backendmetrics.NewPodMetricsFactory(&backendmetrics.FakePodMetricsClient{}, time.Second)
-	ds := datastore.NewDatastore(t.Context(), pmf)
-	for _, testPod := range testInput {
-		ds.PodUpdateOrAddIfNotExist(testPod)
-	}
-
+	ds := &mockDatastore{pods: testInput}
 	for _, test := range tests {
 		t.Run(test.name, func(t *testing.T) {
 			director := NewDirectorWithConfig(ds, &mockScheduler{}, &mockSaturationDetector{}, NewConfig())
 
 			got := director.getCandidatePodsForScheduling(context.Background(), test.metadata)
 
-			diff := cmp.Diff(test.output, got, cmpopts.SortSlices(func(a, b schedulingtypes.Pod) bool {
+			diff := cmp.Diff(test.output, got, cmpopts.SortSlices(func(a, b backendmetrics.PodMetrics) bool {
 				return a.GetPod().NamespacedName.String() < b.GetPod().NamespacedName.String()
 			}))
 			if diff != "" {
diff --git a/pkg/epp/saturationdetector/saturationdetector_test.go b/pkg/epp/saturationdetector/saturationdetector_test.go
index f2530bd..0b861d9 100644
--- a/pkg/epp/saturationdetector/saturationdetector_test.go
+++ b/pkg/epp/saturationdetector/saturationdetector_test.go
@@ -25,27 +25,13 @@ import (
 	"time"
 
 	"github.com/go-logr/logr"
+	"github.com/google/go-cmp/cmp"
 	"k8s.io/apimachinery/pkg/types"
 
 	"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend"
 	backendmetrics "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend/metrics"
 )
 
-// --- Mock Implementations ---
-
-type mockDatastore struct {
-	pods []*backendmetrics.FakePodMetrics
-}
-
-// PodList lists pods matching the given predicate.
-func (fds *mockDatastore) PodList(predicate func(backendmetrics.PodMetrics) bool) []backendmetrics.PodMetrics {
-	pm := make([]backendmetrics.PodMetrics, 0, len(fds.pods))
-	for _, pod := range fds.pods {
-		pm = append(pm, pod)
-	}
-	return pm
-}
-
 func newMockPodMetrics(name string, metrics *backendmetrics.MetricsState) *backendmetrics.FakePodMetrics {
 	return &backendmetrics.FakePodMetrics{
 		Pod: &backend.Pod{
@@ -59,12 +45,9 @@ func newMockPodMetrics(name string, metrics *backendmetrics.MetricsState) *backe
 
 func TestNewDetector(t *testing.T) {
 	tests := []struct {
-		name                         string
-		config                       *Config
-		datastore                    Datastore
-		expectedQueueDepthThreshold  int
-		expectedKVCacheUtilThreshold float64
-		expectedStalenessThreshold   time.Duration
+		name           string
+		config         *Config
+		expectedConfig *Config
 	}{
 		{
 			name: "Valid config",
@@ -73,10 +56,11 @@ func TestNewDetector(t *testing.T) {
 				KVCacheUtilThreshold:      0.8,
 				MetricsStalenessThreshold: 100 * time.Millisecond,
 			},
-			datastore:                    &mockDatastore{},
-			expectedQueueDepthThreshold:  10,
-			expectedKVCacheUtilThreshold: 0.8,
-			expectedStalenessThreshold:   100 * time.Millisecond,
+			expectedConfig: &Config{
+				QueueDepthThreshold:       10,
+				KVCacheUtilThreshold:      0.8,
+				MetricsStalenessThreshold: 100 * time.Millisecond,
+			},
 		},
 		{
 			name: "invalid thresholds, fallback to default",
@@ -85,10 +69,11 @@ func TestNewDetector(t *testing.T) {
 				KVCacheUtilThreshold:      -5,
 				MetricsStalenessThreshold: 0,
 			},
-			datastore:                    &mockDatastore{},
-			expectedQueueDepthThreshold:  DefaultQueueDepthThreshold,
-			expectedKVCacheUtilThreshold: DefaultKVCacheUtilThreshold,
-			expectedStalenessThreshold:   DefaultMetricsStalenessThreshold,
+			expectedConfig: &Config{
+				QueueDepthThreshold:       DefaultQueueDepthThreshold,
+				KVCacheUtilThreshold:      DefaultKVCacheUtilThreshold,
+				MetricsStalenessThreshold: DefaultMetricsStalenessThreshold,
+			},
 		},
 		{
 			name: "kv cache threshold above range, fallback to default",
@@ -97,10 +82,11 @@ func TestNewDetector(t *testing.T) {
 				KVCacheUtilThreshold:      1.5,
 				MetricsStalenessThreshold: 100 * time.Millisecond,
 			},
-			datastore:                    &mockDatastore{},
-			expectedQueueDepthThreshold:  10,
-			expectedKVCacheUtilThreshold: DefaultKVCacheUtilThreshold,
-			expectedStalenessThreshold:   100 * time.Millisecond,
+			expectedConfig: &Config{
+				QueueDepthThreshold:       10,
+				KVCacheUtilThreshold:      DefaultKVCacheUtilThreshold,
+				MetricsStalenessThreshold: 100 * time.Millisecond,
+			},
 		},
 	}
 
@@ -111,19 +97,9 @@ func TestNewDetector(t *testing.T) {
 			os.Setenv(EnvSdKVCacheUtilThreshold, fmt.Sprintf("%v", test.config.KVCacheUtilThreshold))
 			os.Setenv(EnvSdMetricsStalenessThreshold, test.config.MetricsStalenessThreshold.String())
 
-			detector := NewDetector(LoadConfigFromEnv(), test.datastore, logr.Discard())
-			if detector == nil {
-				t.Fatalf("NewDetector() returned nil detector for valid config")
-				return // explicit return so staticcheck does not warn on potential nil detector below.
-			}
-			if detector.config.QueueDepthThreshold != test.expectedQueueDepthThreshold {
-				t.Errorf("NewDetector() QueueDepthThreshold = %d, want %d", detector.config.QueueDepthThreshold, test.expectedQueueDepthThreshold)
-			}
-			if detector.config.KVCacheUtilThreshold != test.expectedKVCacheUtilThreshold {
-				t.Errorf("NewDetector() KVCacheUtilThreshold = %f, want %f", detector.config.KVCacheUtilThreshold, test.expectedKVCacheUtilThreshold)
-			}
-			if detector.config.MetricsStalenessThreshold != test.expectedStalenessThreshold {
-				t.Errorf("NewDetector() MetricsStalenessThreshold = %v, want %v", detector.config.MetricsStalenessThreshold, test.expectedStalenessThreshold)
+			detector := NewDetector(LoadConfigFromEnv(), logr.Discard())
+			if diff := cmp.Diff(test.expectedConfig, detector.config); diff != "" {
+				t.Errorf("Unexpected output (-want +got): %v", diff)
 			}
 		})
 	}
@@ -138,77 +114,77 @@ func TestDetector_IsSaturated(t *testing.T) {
 	}
 
 	tests := []struct {
-		name            string
-		config          *Config
-		pods            []*backendmetrics.FakePodMetrics
-		expectedSaturat bool
+		name               string
+		config             *Config
+		pods               []backendmetrics.PodMetrics
+		expectedSaturation bool
 	}{
 		{
-			name:            "No pods in datastore",
-			config:          defaultConfig,
-			pods:            []*backendmetrics.FakePodMetrics{},
-			expectedSaturat: true, // No capacity = saturated
+			name:               "No candidate pods",
+			config:             defaultConfig,
+			pods:               []backendmetrics.PodMetrics{},
+			expectedSaturation: true, // No capacity = saturated
 		},
 		{
 			name:   "Single pod with good capacity",
 			config: defaultConfig,
-			pods: []*backendmetrics.FakePodMetrics{
+			pods: []backendmetrics.PodMetrics{
 				newMockPodMetrics("pod1", &backendmetrics.MetricsState{
 					UpdateTime:          baseTime,
 					WaitingQueueSize:    2,
 					KVCacheUsagePercent: 0.5,
 				}),
 			},
-			expectedSaturat: false,
+			expectedSaturation: false,
 		},
 		{
 			name:   "Single pod with stale metrics",
 			config: defaultConfig,
-			pods: []*backendmetrics.FakePodMetrics{
+			pods: []backendmetrics.PodMetrics{
 				newMockPodMetrics("pod1", &backendmetrics.MetricsState{
 					UpdateTime:          baseTime.Add(-200 * time.Millisecond), // Stale
 					WaitingQueueSize:    1,
 					KVCacheUsagePercent: 0.1,
 				}),
 			},
-			expectedSaturat: true,
+			expectedSaturation: true,
 		},
 		{
 			name:   "Single pod with high queue depth",
 			config: defaultConfig,
-			pods: []*backendmetrics.FakePodMetrics{
+			pods: []backendmetrics.PodMetrics{
 				newMockPodMetrics("pod1", &backendmetrics.MetricsState{
 					UpdateTime:          baseTime,
 					WaitingQueueSize:    10, // Exceeds threshold 5
 					KVCacheUsagePercent: 0.1,
 				}),
 			},
-			expectedSaturat: true,
+			expectedSaturation: true,
 		},
 		{
 			name:   "Single pod with high KV cache utilization",
 			config: defaultConfig,
-			pods: []*backendmetrics.FakePodMetrics{
+			pods: []backendmetrics.PodMetrics{
 				newMockPodMetrics("pod1", &backendmetrics.MetricsState{
 					UpdateTime:          baseTime,
 					WaitingQueueSize:    1,
 					KVCacheUsagePercent: 0.95, // Exceeds threshold 0.90
 				}),
 			},
-			expectedSaturat: true,
+			expectedSaturation: true,
 		},
 		{
 			name:   "Single pod with nil metrics",
 			config: defaultConfig,
-			pods: []*backendmetrics.FakePodMetrics{
+			pods: []backendmetrics.PodMetrics{
 				newMockPodMetrics("pod1", nil),
 			},
-			expectedSaturat: true,
+			expectedSaturation: true,
 		},
 		{
 			name:   "Multiple pods, all good capacity",
 			config: defaultConfig,
-			pods: []*backendmetrics.FakePodMetrics{
+			pods: []backendmetrics.PodMetrics{
 				newMockPodMetrics("pod1", &backendmetrics.MetricsState{
 					UpdateTime:          baseTime,
 					WaitingQueueSize:    1,
@@ -220,12 +196,12 @@ func TestDetector_IsSaturated(t *testing.T) {
 					KVCacheUsagePercent: 0.2,
 				}),
 			},
-			expectedSaturat: false,
+			expectedSaturation: false,
 		},
 		{
 			name:   "Multiple pods, one good, one bad (stale)",
 			config: defaultConfig,
-			pods: []*backendmetrics.FakePodMetrics{
+			pods: []backendmetrics.PodMetrics{
 				newMockPodMetrics("pod1", &backendmetrics.MetricsState{
 					UpdateTime:          baseTime, // Good
 					WaitingQueueSize:    1,
@@ -237,12 +213,12 @@ func TestDetector_IsSaturated(t *testing.T) {
 					KVCacheUsagePercent: 0.2,
 				}),
 			},
-			expectedSaturat: false, // One good pod is enough
+			expectedSaturation: false, // One good pod is enough
 		},
 		{
 			name:   "Multiple pods, one good, one bad (high queue)",
 			config: defaultConfig,
-			pods: []*backendmetrics.FakePodMetrics{
+			pods: []backendmetrics.PodMetrics{
 				newMockPodMetrics("pod1", &backendmetrics.MetricsState{
 					UpdateTime:          baseTime,
 					WaitingQueueSize:    1,
@@ -254,12 +230,12 @@ func TestDetector_IsSaturated(t *testing.T) {
 					KVCacheUsagePercent: 0.2,
 				}),
 			},
-			expectedSaturat: false,
+			expectedSaturation: false,
 		},
 		{
 			name:   "Multiple pods, all bad capacity",
 			config: defaultConfig,
-			pods: []*backendmetrics.FakePodMetrics{
+			pods: []backendmetrics.PodMetrics{
 				newMockPodMetrics("pod1", &backendmetrics.MetricsState{
 					UpdateTime:          baseTime.Add(-200 * time.Millisecond), // Stale
 					WaitingQueueSize:    1,
@@ -276,52 +252,52 @@ func TestDetector_IsSaturated(t *testing.T) {
 					KVCacheUsagePercent: 0.99, // High KV
 				}),
 			},
-			expectedSaturat: true,
+			expectedSaturation: true,
 		},
 		{
 			name:   "Queue depth exactly at threshold",
 			config: defaultConfig,
-			pods: []*backendmetrics.FakePodMetrics{
+			pods: []backendmetrics.PodMetrics{
 				newMockPodMetrics("pod1", &backendmetrics.MetricsState{
 					UpdateTime:          baseTime,
 					WaitingQueueSize:    defaultConfig.QueueDepthThreshold, // Exactly at threshold (good)
 					KVCacheUsagePercent: 0.1,
 				}),
 			},
-			expectedSaturat: false,
+			expectedSaturation: false,
 		},
 		{
 			name:   "KV cache exactly at threshold",
 			config: defaultConfig,
-			pods: []*backendmetrics.FakePodMetrics{
+			pods: []backendmetrics.PodMetrics{
 				newMockPodMetrics("pod1", &backendmetrics.MetricsState{
 					UpdateTime:          baseTime,
 					WaitingQueueSize:    1,
 					KVCacheUsagePercent: defaultConfig.KVCacheUtilThreshold, // Exactly at threshold (good)
 				}),
 			},
-			expectedSaturat: false,
+			expectedSaturation: false,
 		},
 		{
 			name:   "Metrics age just over staleness threshold",
 			config: defaultConfig,
-			pods: []*backendmetrics.FakePodMetrics{
+			pods: []backendmetrics.PodMetrics{
 				newMockPodMetrics("pod1", &backendmetrics.MetricsState{
 					UpdateTime:          baseTime.Add(-defaultConfig.MetricsStalenessThreshold - time.Nanosecond), // Just over (stale)
 					WaitingQueueSize:    1,
 					KVCacheUsagePercent: 0.1,
 				}),
 			},
-			expectedSaturat: true,
+			expectedSaturation: true,
 		},
 	}
 
 	for _, test := range tests {
 		t.Run(test.name, func(t *testing.T) {
-			detector := NewDetector(test.config, &mockDatastore{pods: test.pods}, logr.Discard())
+			detector := NewDetector(test.config, logr.Discard())
 
-			if got := detector.IsSaturated(context.Background()); got != test.expectedSaturat {
-				t.Errorf("IsSaturated() = %v, want %v", got, test.expectedSaturat)
+			if got := detector.IsSaturated(context.Background(), test.pods); got != test.expectedSaturation {
+				t.Errorf("IsSaturated() = %v, want %v", got, test.expectedSaturation)
 			}
 		})
 	}
diff --git a/pkg/epp/scheduling/framework/plugins/multi/prefix/plugin_test.go b/pkg/epp/scheduling/framework/plugins/multi/prefix/plugin_test.go
index 666d053..eee8f63 100644
--- a/pkg/epp/scheduling/framework/plugins/multi/prefix/plugin_test.go
+++ b/pkg/epp/scheduling/framework/plugins/multi/prefix/plugin_test.go
@@ -57,8 +57,8 @@ func TestPrefixPlugin(t *testing.T) {
 	assert.NoError(t, err)
 	t.Logf("Hashes %+v, cached servers: %+v", state.PrefixHashes, state.PrefixCacheServers)
 	// Input size is 6, hash block size is 4, the last 2 characters are ignored.
-	// Total hashes = 2 (the first one is for the model)
-	assert.Equal(t, 2, len(state.PrefixHashes), "number of hashes is incorrect")
+	// Total hashes = 1 (the first one is for the prefix with model)
+	assert.Equal(t, 1, len(state.PrefixHashes), "number of hashes is incorrect")
 	assert.Equal(t, 0, len(state.PrefixCacheServers), "there shouldn't be any cached servers")
 	assert.Equal(t, float64(0), scores[pod1], "score for pod1")
 	assert.Equal(t, float64(0), scores[pod2], "score for pod2")
@@ -84,8 +84,8 @@ func TestPrefixPlugin(t *testing.T) {
 	assert.NoError(t, err)
 	t.Logf("Hashes %+v, cached servers: %+v", state.PrefixHashes, state.PrefixCacheServers)
 	// Input size is 6, hash block size is 4, the last 2 characters are ignored.
-	// Total hashes = 2 (the first one is for the model)
-	assert.Equal(t, 2, len(state.PrefixHashes), "number of hashes is incorrect")
+	// Total hashes = 1 (the first one is for the prefix with model)
+	assert.Equal(t, 1, len(state.PrefixHashes), "number of hashes is incorrect")
 	assert.Equal(t, 0, len(state.PrefixCacheServers), "there shouldn't be any cached servers")
 	assert.Equal(t, float64(0), scores[pod1], "score for pod1")
 	assert.Equal(t, float64(0), scores[pod2], "score for pod2")
@@ -110,10 +110,10 @@ func TestPrefixPlugin(t *testing.T) {
 	assert.NoError(t, err)
 	t.Logf("Hashes %+v, cached servers: %+v", state.PrefixHashes, state.PrefixCacheServers)
 	// Input size is 8, hash block size is 4, so 2 hashes will be calculated.
-	// Total hashes = 3 (the first one is for the model)
-	assert.Equal(t, 3, len(state.PrefixHashes), "number of hashes is incorrect")
+	// Total hashes = 2 (the first one is for the prefix with model)
+	assert.Equal(t, 2, len(state.PrefixHashes), "number of hashes is incorrect")
 	assert.Equal(t, 1, len(state.PrefixCacheServers), "pod1 should have cached the aaaa prefix")
-	assert.Equal(t, float64(2)/float64(3), scores[pod1], "score should be 2/3 - the model and the first prefix block match")
+	assert.Equal(t, 0.5, scores[pod1], "score should be 0.5 - the model and the first prefix block match")
 	assert.Equal(t, float64(0), scores[pod2], "score for pod2")
 
 	schedulingResult = &types.SchedulingResult{
@@ -135,8 +135,8 @@ func TestPrefixPlugin(t *testing.T) {
 	assert.NoError(t, err)
 	t.Logf("Hashes %+v, cached servers: %+v", state.PrefixHashes, state.PrefixCacheServers)
 	// Input size is 8, hash block size is 4, so 2 hashes will be calculated.
-	// Total hashes = 3 (the first one is for the model)
-	assert.Equal(t, 3, len(state.PrefixHashes), "number of hashes is incorrect")
+	// Total hashes = 2 (the first one is for the prefix with model)
+	assert.Equal(t, 2, len(state.PrefixHashes), "number of hashes is incorrect")
 	assert.Equal(t, 0, len(state.PrefixCacheServers), "pod1 should have cached the aaaa prefix")
 	assert.Equal(t, float64(0), scores[pod1], "score for pod1")
 	assert.Equal(t, float64(0), scores[pod2], "score for pod2")
@@ -160,10 +160,10 @@ func TestPrefixPlugin(t *testing.T) {
 	assert.NoError(t, err)
 	t.Logf("Hashes %+v, cached servers: %+v", state.PrefixHashes, state.PrefixCacheServers)
 	// Input size is 12, hash block size is 4, so 3 hashes will be calculated.
-	// Total hashes = 4 (the first one is for the model)
-	assert.Equal(t, 4, len(state.PrefixHashes), "number of hashes is incorrect")
+	// Total hashes = 3 (the first one is for the prefix with model)
+	assert.Equal(t, 3, len(state.PrefixHashes), "number of hashes is incorrect")
 	assert.Equal(t, 1, len(state.PrefixCacheServers), "pod1 should have cached the aaaa prefix")
-	assert.Equal(t, 0.75, scores[pod1], "score should be 0.75 - the model and the first 2 prefix blocks match")
+	assert.Equal(t, 2./3, scores[pod1], "score should be 2./3 - the model and the first 2 prefix blocks match")
 	assert.Equal(t, float64(0), scores[pod2], "score for pod2")
 
 	schedulingResult = &types.SchedulingResult{
@@ -224,7 +224,7 @@ func BenchmarkPrefixPluginStress(b *testing.B) {
 		// Second cycle: validate internal state
 		state, err := plugins.ReadPluginStateKey[*SchedulingContextState](plugin.pluginState, req.RequestId, PrefixCachePluginType)
 		assert.NoError(b, err)
-		expectedHashes := int(math.Min(float64(maxPrefixBlocks+1), float64(len(req.Prompt)/blockSize+1))) // the extra one is for the model.
+		expectedHashes := int(math.Min(float64(maxPrefixBlocks), float64(len(req.Prompt)/blockSize)))
 		assert.Equal(b, expectedHashes, len(state.PrefixHashes), "number of hashes is incorrect")
 	}
 }
diff --git a/test/integration/epp/hermetic_test.go b/test/integration/epp/hermetic_test.go
index b421f7f..384ac5e 100644
--- a/test/integration/epp/hermetic_test.go
+++ b/test/integration/epp/hermetic_test.go
@@ -1125,7 +1125,7 @@ func BeforeSuite() func() {
 		KVCacheUtilThreshold:      saturationdetector.DefaultKVCacheUtilThreshold,
 		MetricsStalenessThreshold: saturationdetector.DefaultMetricsStalenessThreshold,
 	}
-	detector := saturationdetector.NewDetector(sdConfig, serverRunner.Datastore, logger.WithName("saturation-detector"))
+	detector := saturationdetector.NewDetector(sdConfig, logger.WithName("saturation-detector"))
 	serverRunner.SaturationDetector = detector
 	serverRunner.Director = requestcontrol.NewDirectorWithConfig(serverRunner.Datastore, scheduler, detector, requestcontrol.NewConfig())
 	serverRunner.SecureServing = false