diff --git a/apis/elbv2/v1beta1/ingressclassparams_types.go b/apis/elbv2/v1beta1/ingressclassparams_types.go
index 4fc921694..27b9abcb6 100644
--- a/apis/elbv2/v1beta1/ingressclassparams_types.go
+++ b/apis/elbv2/v1beta1/ingressclassparams_types.go
@@ -107,6 +107,13 @@ type MinimumLoadBalancerCapacity struct {
 	CapacityUnits int32 `json:"capacityUnits"`
 }
 
+// IPAMConfiguration defines the IPAM configuration for an Ingress.
+type IPAMConfiguration struct {
+	// IPv4IPAMPoolId defines the IPAM pool ID used for IPv4 Addresses on the ALB.
+	// +optional
+	IPv4IPAMPoolId *string `json:"ipv4IPAMPoolId,omitempty"`
+}
+
 // IngressClassParamsSpec defines the desired state of IngressClassParams
 type IngressClassParamsSpec struct {
 	// CertificateArn specifies the ARN of the certificates for all Ingresses that belong to IngressClass with this IngressClassParams.
@@ -156,6 +163,10 @@ type IngressClassParamsSpec struct {
 	// MinimumLoadBalancerCapacity define the capacity reservation for LoadBalancers for all Ingress that belong to IngressClass with this IngressClassParams.
 	// +optional
 	MinimumLoadBalancerCapacity *MinimumLoadBalancerCapacity `json:"minimumLoadBalancerCapacity,omitempty"`
+
+	// IPAMConfiguration defines the IPAM settings for a Load Balancer.
+	// +optional
+	IPAMConfiguration *IPAMConfiguration `json:"ipamConfiguration,omitempty"`
 }
 
 // +kubebuilder:object:root=true
diff --git a/apis/elbv2/v1beta1/zz_generated.deepcopy.go b/apis/elbv2/v1beta1/zz_generated.deepcopy.go
index 108289a52..068b3dcf3 100644
--- a/apis/elbv2/v1beta1/zz_generated.deepcopy.go
+++ b/apis/elbv2/v1beta1/zz_generated.deepcopy.go
@@ -41,6 +41,26 @@ func (in *Attribute) DeepCopy() *Attribute {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *IPAMConfiguration) DeepCopyInto(out *IPAMConfiguration) {
+	*out = *in
+	if in.IPv4IPAMPoolId != nil {
+		in, out := &in.IPv4IPAMPoolId, &out.IPv4IPAMPoolId
+		*out = new(string)
+		**out = **in
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPAMConfiguration.
+func (in *IPAMConfiguration) DeepCopy() *IPAMConfiguration {
+	if in == nil {
+		return nil
+	}
+	out := new(IPAMConfiguration)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *IPBlock) DeepCopyInto(out *IPBlock) {
 	*out = *in
@@ -174,6 +194,11 @@ func (in *IngressClassParamsSpec) DeepCopyInto(out *IngressClassParamsSpec) {
 		*out = new(MinimumLoadBalancerCapacity)
 		**out = **in
 	}
+	if in.IPAMConfiguration != nil {
+		in, out := &in.IPAMConfiguration, &out.IPAMConfiguration
+		*out = new(IPAMConfiguration)
+		(*in).DeepCopyInto(*out)
+	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IngressClassParamsSpec.
diff --git a/config/crd/bases/elbv2.k8s.aws_ingressclassparams.yaml b/config/crd/bases/elbv2.k8s.aws_ingressclassparams.yaml
index 7f65f28ad..18da6634e 100644
--- a/config/crd/bases/elbv2.k8s.aws_ingressclassparams.yaml
+++ b/config/crd/bases/elbv2.k8s.aws_ingressclassparams.yaml
@@ -85,6 +85,15 @@ spec:
                 - dualstack
                 - dualstack-without-public-ipv4
                 type: string
+              ipamConfiguration:
+                description: IPAMConfiguration defines the IPAM settings for a Load
+                  Balancer.
+                properties:
+                  ipv4IPAMPoolId:
+                    description: IPv4IPAMPoolId defines the IPAM pool ID used for
+                      IPv4 Addresses on the ALB.
+                    type: string
+                type: object
               listeners:
                 description: Listeners define a list of listeners with their protocol,
                   port and attributes.
diff --git a/docs/guide/ingress/annotations.md b/docs/guide/ingress/annotations.md
index 0dd09ed56..c1c6c7fcd 100644
--- a/docs/guide/ingress/annotations.md
+++ b/docs/guide/ingress/annotations.md
@@ -14,54 +14,55 @@ You can add annotations to kubernetes Ingress and Service objects to customize t
         - Merge: such annotation can be specified on all Ingresses within IngressGroup, and will be merged together.
 
 ## Annotations
-| Name                                                                                                  | Type                        |Default| Location        | MergeBehavior |
-|-------------------------------------------------------------------------------------------------------|-----------------------------|------|-----------------|---------------|
-| [alb.ingress.kubernetes.io/load-balancer-name](#load-balancer-name)                                   | string                      |N/A| Ingress         | Exclusive     |
-| [alb.ingress.kubernetes.io/group.name](#group.name)                                                   | string                      |N/A| Ingress         | N/A           |
-| [alb.ingress.kubernetes.io/group.order](#group.order)                                                 | integer                     |0| Ingress         | N/A           |
-| [alb.ingress.kubernetes.io/tags](#tags)                                                               | stringMap                   |N/A| Ingress,Service | Merge         |
-| [alb.ingress.kubernetes.io/ip-address-type](#ip-address-type)                                         | ipv4 \| dualstack \|  dualstack-without-public-ipv4           |ipv4| Ingress         | Exclusive     |
-| [alb.ingress.kubernetes.io/scheme](#scheme)                                                           | internal \| internet-facing |internal| Ingress         | Exclusive     |
-| [alb.ingress.kubernetes.io/subnets](#subnets)                                                         | stringList                  |N/A| Ingress         | Exclusive     |
-| [alb.ingress.kubernetes.io/security-groups](#security-groups)                                         | stringList                  |N/A| Ingress         | Exclusive     |
-| [alb.ingress.kubernetes.io/manage-backend-security-group-rules](#manage-backend-security-group-rules) | boolean                     |N/A| Ingress         | Exclusive     |
-| [alb.ingress.kubernetes.io/customer-owned-ipv4-pool](#customer-owned-ipv4-pool)                       | string                      |N/A| Ingress         | Exclusive     |
-| [alb.ingress.kubernetes.io/load-balancer-attributes](#load-balancer-attributes)                       | stringMap                   |N/A| Ingress         | Exclusive     |
-| [alb.ingress.kubernetes.io/wafv2-acl-arn](#wafv2-acl-arn)                                             | string                      |N/A| Ingress         | Exclusive     |
-| [alb.ingress.kubernetes.io/waf-acl-id](#waf-acl-id)                                                   | string                      |N/A| Ingress         | Exclusive     |
-| [alb.ingress.kubernetes.io/shield-advanced-protection](#shield-advanced-protection)                   | boolean                     |N/A| Ingress         | Exclusive     |
-| [alb.ingress.kubernetes.io/listen-ports](#listen-ports)                                               | json                        |'[{"HTTP": 80}]' \| '[{"HTTPS": 443}]'| Ingress         | Merge         |
-| [alb.ingress.kubernetes.io/ssl-redirect](#ssl-redirect)                                               | integer                     |N/A| Ingress         | Exclusive     |
-| [alb.ingress.kubernetes.io/inbound-cidrs](#inbound-cidrs)                                             | stringList                  |0.0.0.0/0, ::/0| Ingress         | Exclusive     |
-| [alb.ingress.kubernetes.io/security-group-prefix-lists](#security-group-prefix-lists)                                               | stringList                        |pl-00000000, pl-1111111| Ingress         | Exclusive     |
-| [alb.ingress.kubernetes.io/certificate-arn](#certificate-arn)                                         | stringList                  |N/A| Ingress         | Merge         |
-| [alb.ingress.kubernetes.io/ssl-policy](#ssl-policy)                                                   | string                      |ELBSecurityPolicy-2016-08| Ingress         | Exclusive     |
-| [alb.ingress.kubernetes.io/target-type](#target-type)                                                 | instance \| ip              |instance| Ingress,Service | N/A           |
-| [alb.ingress.kubernetes.io/backend-protocol](#backend-protocol)                                       | HTTP \| HTTPS               |HTTP| Ingress,Service | N/A           |
-| [alb.ingress.kubernetes.io/backend-protocol-version](#backend-protocol-version)                       | string                      | HTTP1 | Ingress,Service | N/A           |
-| [alb.ingress.kubernetes.io/target-group-attributes](#target-group-attributes)                         | stringMap                   |N/A| Ingress,Service | N/A           |
-| [alb.ingress.kubernetes.io/healthcheck-port](#healthcheck-port)                                       | integer \| traffic-port     |traffic-port| Ingress,Service | N/A           |
-| [alb.ingress.kubernetes.io/healthcheck-protocol](#healthcheck-protocol)                               | HTTP \| HTTPS               |HTTP| Ingress,Service | N/A           |
-| [alb.ingress.kubernetes.io/healthcheck-path](#healthcheck-path)                                       | string                      |/ \| /AWS.ALB/healthcheck | Ingress,Service | N/A           |
-| [alb.ingress.kubernetes.io/healthcheck-interval-seconds](#healthcheck-interval-seconds)               | integer                     |'15'| Ingress,Service | N/A           |
-| [alb.ingress.kubernetes.io/healthcheck-timeout-seconds](#healthcheck-timeout-seconds)                 | integer                     |'5'| Ingress,Service | N/A           |
-| [alb.ingress.kubernetes.io/healthy-threshold-count](#healthy-threshold-count)                         | integer                     |'2'| Ingress,Service | N/A           |
-| [alb.ingress.kubernetes.io/unhealthy-threshold-count](#unhealthy-threshold-count)                     | integer                     |'2'| Ingress,Service | N/A           |
-| [alb.ingress.kubernetes.io/success-codes](#success-codes)                                             | string                      |'200' \| '12' | Ingress,Service | N/A           |
-| [alb.ingress.kubernetes.io/auth-type](#auth-type)                                                     | none\|oidc\|cognito         |none| Ingress,Service | N/A           |
-| [alb.ingress.kubernetes.io/auth-idp-cognito](#auth-idp-cognito)                                       | json                        |N/A| Ingress,Service | N/A           |
-| [alb.ingress.kubernetes.io/auth-idp-oidc](#auth-idp-oidc)                                             | json                        |N/A| Ingress,Service | N/A           |
-| [alb.ingress.kubernetes.io/auth-on-unauthenticated-request](#auth-on-unauthenticated-request)         | authenticate\|allow\|deny   |authenticate| Ingress,Service | N/A           |
-| [alb.ingress.kubernetes.io/auth-scope](#auth-scope)                                                   | string                      |openid| Ingress,Service | N/A           |
-| [alb.ingress.kubernetes.io/auth-session-cookie](#auth-session-cookie)                                 | string                      |AWSELBAuthSessionCookie| Ingress,Service | N/A           |
-| [alb.ingress.kubernetes.io/auth-session-timeout](#auth-session-timeout)                               | integer                     |'604800'| Ingress,Service | N/A           |
-| [alb.ingress.kubernetes.io/actions.${action-name}](#actions)                                          | json                        |N/A| Ingress         | N/A           |
-| [alb.ingress.kubernetes.io/conditions.${conditions-name}](#conditions)                                | json                        |N/A| Ingress         | N/A           |
-| [alb.ingress.kubernetes.io/target-node-labels](#target-node-labels)                                   | stringMap                   |N/A| Ingress,Service | N/A           |
-| [alb.ingress.kubernetes.io/mutual-authentication](#mutual-authentication)                             | json                        |N/A| Ingress         | Exclusive     |
-| [alb.ingress.kubernetes.io/multi-cluster-target-group](#multi-cluster-target-group)                   | boolean                     |N/A| Ingress, Service | N/A           |
-| [alb.ingress.kubernetes.io/listener-attributes.${Protocol}-${Port}](#listener-attributes)                           | stringMap                        |N/A| Ingress         |Merge|
-| [alb.ingress.kubernetes.io/minimum-load-balancer-capacity](#load-balancer-capacity-reservation)                       | stringMap                   |N/A| Ingress         | Exclusive     |
+| Name                                                                                                  | Type                                               |Default| Location        | MergeBehavior |
+|-------------------------------------------------------------------------------------------------------|----------------------------------------------------|------|-----------------|---------------|
+| [alb.ingress.kubernetes.io/load-balancer-name](#load-balancer-name)                                   | string                                             |N/A| Ingress         | Exclusive     |
+| [alb.ingress.kubernetes.io/group.name](#group.name)                                                   | string                                             |N/A| Ingress         | N/A           |
+| [alb.ingress.kubernetes.io/group.order](#group.order)                                                 | integer                                            |0| Ingress         | N/A           |
+| [alb.ingress.kubernetes.io/tags](#tags)                                                               | stringMap                                          |N/A| Ingress,Service | Merge         |
+| [alb.ingress.kubernetes.io/ip-address-type](#ip-address-type)                                         | ipv4 \| dualstack \|  dualstack-without-public-ipv4 |ipv4| Ingress         | Exclusive     |
+| [alb.ingress.kubernetes.io/scheme](#scheme)                                                           | internal \| internet-facing                        |internal| Ingress         | Exclusive     |
+| [alb.ingress.kubernetes.io/subnets](#subnets)                                                         | stringList                                         |N/A| Ingress         | Exclusive     |
+| [alb.ingress.kubernetes.io/security-groups](#security-groups)                                         | stringList                                         |N/A| Ingress         | Exclusive     |
+| [alb.ingress.kubernetes.io/manage-backend-security-group-rules](#manage-backend-security-group-rules) | boolean                                            |N/A| Ingress         | Exclusive     |
+| [alb.ingress.kubernetes.io/customer-owned-ipv4-pool](#customer-owned-ipv4-pool)                       | string                                             |N/A| Ingress         | Exclusive     |
+| [alb.ingress.kubernetes.io/load-balancer-attributes](#load-balancer-attributes)                       | stringMap                                          |N/A| Ingress         | Exclusive     |
+| [alb.ingress.kubernetes.io/wafv2-acl-arn](#wafv2-acl-arn)                                             | string                                             |N/A| Ingress         | Exclusive     |
+| [alb.ingress.kubernetes.io/waf-acl-id](#waf-acl-id)                                                   | string                                             |N/A| Ingress         | Exclusive     |
+| [alb.ingress.kubernetes.io/shield-advanced-protection](#shield-advanced-protection)                   | boolean                                            |N/A| Ingress         | Exclusive     |
+| [alb.ingress.kubernetes.io/listen-ports](#listen-ports)                                               | json                                               |'[{"HTTP": 80}]' \| '[{"HTTPS": 443}]'| Ingress         | Merge         |
+| [alb.ingress.kubernetes.io/ssl-redirect](#ssl-redirect)                                               | integer                                            |N/A| Ingress         | Exclusive     |
+| [alb.ingress.kubernetes.io/inbound-cidrs](#inbound-cidrs)                                             | stringList                                         |0.0.0.0/0, ::/0| Ingress         | Exclusive     |
+| [alb.ingress.kubernetes.io/security-group-prefix-lists](#security-group-prefix-lists)                                               | stringList                                         |pl-00000000, pl-1111111| Ingress         | Exclusive     |
+| [alb.ingress.kubernetes.io/certificate-arn](#certificate-arn)                                         | stringList                                         |N/A| Ingress         | Merge         |
+| [alb.ingress.kubernetes.io/ssl-policy](#ssl-policy)                                                   | string                                             |ELBSecurityPolicy-2016-08| Ingress         | Exclusive     |
+| [alb.ingress.kubernetes.io/target-type](#target-type)                                                 | instance \| ip                                     |instance| Ingress,Service | N/A           |
+| [alb.ingress.kubernetes.io/backend-protocol](#backend-protocol)                                       | HTTP \| HTTPS                                      |HTTP| Ingress,Service | N/A           |
+| [alb.ingress.kubernetes.io/backend-protocol-version](#backend-protocol-version)                       | string                                             | HTTP1 | Ingress,Service | N/A           |
+| [alb.ingress.kubernetes.io/target-group-attributes](#target-group-attributes)                         | stringMap                                          |N/A| Ingress,Service | N/A           |
+| [alb.ingress.kubernetes.io/healthcheck-port](#healthcheck-port)                                       | integer \| traffic-port                            |traffic-port| Ingress,Service | N/A           |
+| [alb.ingress.kubernetes.io/healthcheck-protocol](#healthcheck-protocol)                               | HTTP \| HTTPS                                      |HTTP| Ingress,Service | N/A           |
+| [alb.ingress.kubernetes.io/healthcheck-path](#healthcheck-path)                                       | string                                             |/ \| /AWS.ALB/healthcheck | Ingress,Service | N/A           |
+| [alb.ingress.kubernetes.io/healthcheck-interval-seconds](#healthcheck-interval-seconds)               | integer                                            |'15'| Ingress,Service | N/A           |
+| [alb.ingress.kubernetes.io/healthcheck-timeout-seconds](#healthcheck-timeout-seconds)                 | integer                                            |'5'| Ingress,Service | N/A           |
+| [alb.ingress.kubernetes.io/healthy-threshold-count](#healthy-threshold-count)                         | integer                                            |'2'| Ingress,Service | N/A           |
+| [alb.ingress.kubernetes.io/unhealthy-threshold-count](#unhealthy-threshold-count)                     | integer                                            |'2'| Ingress,Service | N/A           |
+| [alb.ingress.kubernetes.io/success-codes](#success-codes)                                             | string                                             |'200' \| '12' | Ingress,Service | N/A           |
+| [alb.ingress.kubernetes.io/auth-type](#auth-type)                                                     | none\|oidc\|cognito                                |none| Ingress,Service | N/A           |
+| [alb.ingress.kubernetes.io/auth-idp-cognito](#auth-idp-cognito)                                       | json                                               |N/A| Ingress,Service | N/A           |
+| [alb.ingress.kubernetes.io/auth-idp-oidc](#auth-idp-oidc)                                             | json                                               |N/A| Ingress,Service | N/A           |
+| [alb.ingress.kubernetes.io/auth-on-unauthenticated-request](#auth-on-unauthenticated-request)         | authenticate\|allow\|deny                          |authenticate| Ingress,Service | N/A           |
+| [alb.ingress.kubernetes.io/auth-scope](#auth-scope)                                                   | string                                             |openid| Ingress,Service | N/A           |
+| [alb.ingress.kubernetes.io/auth-session-cookie](#auth-session-cookie)                                 | string                                             |AWSELBAuthSessionCookie| Ingress,Service | N/A           |
+| [alb.ingress.kubernetes.io/auth-session-timeout](#auth-session-timeout)                               | integer                                            |'604800'| Ingress,Service | N/A           |
+| [alb.ingress.kubernetes.io/actions.${action-name}](#actions)                                          | json                                               |N/A| Ingress         | N/A           |
+| [alb.ingress.kubernetes.io/conditions.${conditions-name}](#conditions)                                | json                                               |N/A| Ingress         | N/A           |
+| [alb.ingress.kubernetes.io/target-node-labels](#target-node-labels)                                   | stringMap                                          |N/A| Ingress,Service | N/A           |
+| [alb.ingress.kubernetes.io/mutual-authentication](#mutual-authentication)                             | json                                               |N/A| Ingress         | Exclusive     |
+| [alb.ingress.kubernetes.io/multi-cluster-target-group](#multi-cluster-target-group)                   | boolean                                            |N/A| Ingress, Service | N/A           |
+| [alb.ingress.kubernetes.io/listener-attributes.${Protocol}-${Port}](#listener-attributes)                           | stringMap                                          |N/A| Ingress         |Merge|
+| [alb.ingress.kubernetes.io/minimum-load-balancer-capacity](#load-balancer-capacity-reservation)                       | stringMap                                          |N/A| Ingress         | Exclusive     |
+| [alb.ingress.kubernetes.io/ipam-ipv4-pool-id](#ipam-ipv4-pool-id)                       | string                                             |N/A| Ingress         | Exclusive     |
 
 ## IngressGroup
 IngressGroup feature enables you to group multiple Ingress resources together.
@@ -247,6 +248,20 @@ Traffic Routing can be controlled with following annotations:
         alb.ingress.kubernetes.io/subnets: subnet-xxxx, mySubnet
         ```
 
+- <a name="ipam-ipv4-pool-id">`alb.ingress.kubernetes.io/ipam-ipv4-pool-id`</a> Specifies the [IPv4 IPAM Pool ID](https://docs.aws.amazon.com/vpc/latest/ipam/tutorials-byoip-ipam-console-ipv4.html) which will be used by your load balancer to assign IP addresses.
+
+  !!!note ""
+  The chosen IPAM pool is always the prioritized source when assigning public IPv4 addresses.
+  If there are no more assignable IP addresses in the IPAM pool, AWS managed IPv4 addresses are assigned.
+
+  !!!tip
+  To remove an IPAM pool associated to your ALB, remove the annotation from your ingress.
+
+  !!!example
+  ```
+  alb.ingress.kubernetes.io/ipam-ipv4-pool-id: ipam-pool-0f995c17c00375b48
+  ```
+
 - <a name="actions">`alb.ingress.kubernetes.io/actions.${action-name}`</a> Provides a method for configuring custom actions on a listener, such as Redirect Actions.
 
     The `action-name` in the annotation must match the serviceName in the Ingress rules, and servicePort must be `use-annotation`.
diff --git a/docs/guide/ingress/ingress_class.md b/docs/guide/ingress/ingress_class.md
index fd5d6ee95..3a21487a5 100644
--- a/docs/guide/ingress/ingress_class.md
+++ b/docs/guide/ingress/ingress_class.md
@@ -251,4 +251,10 @@ They may specify `capacityUnits`. If the field is specified, LBC will ignore the
 
 ##### spec.minimumLoadBalancerCapacity.capacityUnits
 
-If `capacityUnits` is specified, it must be to valid positive value greater than 0. If set to 0, the LBC will reset the capacity reservation for the load balancer.
\ No newline at end of file
+If `capacityUnits` is specified, it must be to valid positive value greater than 0. If set to 0, the LBC will reset the capacity reservation for the load balancer.
+
+#### spec.ipv4IPAMPoolId
+
+The IPAM pool you choose will be the preferred source of public IPv4 addresses.
+If the pool is depleted, IPv4 addresses will be assigned by AWS.
+To remove the IPAM pool from your ALB, remove `spec.ipv4IPAMPoolId` from the IngressClass definition.
diff --git a/docs/install/iam_policy.json b/docs/install/iam_policy.json
index 0da4ee564..fe1976170 100644
--- a/docs/install/iam_policy.json
+++ b/docs/install/iam_policy.json
@@ -30,6 +30,7 @@
                 "ec2:GetCoipPoolUsage",
                 "ec2:DescribeCoipPools",
                 "ec2:GetSecurityGroupsForVpc",
+                "ec2:DescribeIpamPools",
                 "elasticloadbalancing:DescribeLoadBalancers",
                 "elasticloadbalancing:DescribeLoadBalancerAttributes",
                 "elasticloadbalancing:DescribeListeners",
@@ -193,7 +194,8 @@
                 "elasticloadbalancing:ModifyTargetGroupAttributes",
                 "elasticloadbalancing:DeleteTargetGroup",
                 "elasticloadbalancing:ModifyListenerAttributes",
-                "elasticloadbalancing:ModifyCapacityReservation"
+                "elasticloadbalancing:ModifyCapacityReservation",
+                "elasticloadbalancing:ModifyIpPools"
             ],
             "Resource": "*",
             "Condition": {
diff --git a/docs/install/iam_policy_cn.json b/docs/install/iam_policy_cn.json
index bb475f6ec..bd2b8b8c9 100644
--- a/docs/install/iam_policy_cn.json
+++ b/docs/install/iam_policy_cn.json
@@ -30,6 +30,7 @@
                 "ec2:GetCoipPoolUsage",
                 "ec2:DescribeCoipPools",
                 "ec2:GetSecurityGroupsForVpc",
+                "ec2:DescribeIpamPools",
                 "elasticloadbalancing:DescribeLoadBalancers",
                 "elasticloadbalancing:DescribeLoadBalancerAttributes",
                 "elasticloadbalancing:DescribeListeners",
@@ -215,7 +216,8 @@
                 "elasticloadbalancing:ModifyTargetGroupAttributes",
                 "elasticloadbalancing:DeleteTargetGroup",
                 "elasticloadbalancing:ModifyListenerAttributes",
-                "elasticloadbalancing:ModifyCapacityReservation"
+                "elasticloadbalancing:ModifyCapacityReservation",
+                "elasticloadbalancing:ModifyIpPools"
             ],
             "Resource": "*",
             "Condition": {
diff --git a/docs/install/iam_policy_iso.json b/docs/install/iam_policy_iso.json
index 46187d30e..9d032e395 100644
--- a/docs/install/iam_policy_iso.json
+++ b/docs/install/iam_policy_iso.json
@@ -30,6 +30,7 @@
                 "ec2:GetCoipPoolUsage",
                 "ec2:DescribeCoipPools",
                 "ec2:GetSecurityGroupsForVpc",
+                "ec2:DescribeIpamPools",
                 "elasticloadbalancing:DescribeLoadBalancers",
                 "elasticloadbalancing:DescribeLoadBalancerAttributes",
                 "elasticloadbalancing:DescribeListeners",
@@ -210,7 +211,8 @@
                 "elasticloadbalancing:DeleteLoadBalancer",
                 "elasticloadbalancing:ModifyTargetGroup",
                 "elasticloadbalancing:ModifyTargetGroupAttributes",
-                "elasticloadbalancing:DeleteTargetGroup"
+                "elasticloadbalancing:DeleteTargetGroup",
+                "elasticloadbalancing:ModifyIpPools"
             ],
             "Resource": "*",
             "Condition": {
diff --git a/docs/install/iam_policy_isob.json b/docs/install/iam_policy_isob.json
index c7107d710..6288c9c62 100644
--- a/docs/install/iam_policy_isob.json
+++ b/docs/install/iam_policy_isob.json
@@ -30,6 +30,7 @@
                 "ec2:GetCoipPoolUsage",
                 "ec2:DescribeCoipPools",
                 "ec2:GetSecurityGroupsForVpc",
+                "ec2:DescribeIpamPools",
                 "elasticloadbalancing:DescribeLoadBalancers",
                 "elasticloadbalancing:DescribeLoadBalancerAttributes",
                 "elasticloadbalancing:DescribeListeners",
@@ -210,7 +211,8 @@
                 "elasticloadbalancing:DeleteLoadBalancer",
                 "elasticloadbalancing:ModifyTargetGroup",
                 "elasticloadbalancing:ModifyTargetGroupAttributes",
-                "elasticloadbalancing:DeleteTargetGroup"
+                "elasticloadbalancing:DeleteTargetGroup",
+                "elasticloadbalancing:ModifyIpPools"
             ],
             "Resource": "*",
             "Condition": {
diff --git a/docs/install/iam_policy_isoe.json b/docs/install/iam_policy_isoe.json
index 6db25833e..499afd947 100644
--- a/docs/install/iam_policy_isoe.json
+++ b/docs/install/iam_policy_isoe.json
@@ -30,6 +30,7 @@
                 "ec2:GetCoipPoolUsage",
                 "ec2:DescribeCoipPools",
                 "ec2:GetSecurityGroupsForVpc",
+                "ec2:DescribeIpamPools",
                 "elasticloadbalancing:DescribeLoadBalancers",
                 "elasticloadbalancing:DescribeLoadBalancerAttributes",
                 "elasticloadbalancing:DescribeListeners",
@@ -210,7 +211,8 @@
                 "elasticloadbalancing:DeleteLoadBalancer",
                 "elasticloadbalancing:ModifyTargetGroup",
                 "elasticloadbalancing:ModifyTargetGroupAttributes",
-                "elasticloadbalancing:DeleteTargetGroup"
+                "elasticloadbalancing:DeleteTargetGroup",
+                "elasticloadbalancing:ModifyIpPools"
             ],
             "Resource": "*",
             "Condition": {
diff --git a/docs/install/iam_policy_isof.json b/docs/install/iam_policy_isof.json
index 7a43d3e40..08c1d1390 100644
--- a/docs/install/iam_policy_isof.json
+++ b/docs/install/iam_policy_isof.json
@@ -30,6 +30,7 @@
                 "ec2:GetCoipPoolUsage",
                 "ec2:DescribeCoipPools",
                 "ec2:GetSecurityGroupsForVpc",
+                "ec2:DescribeIpamPools",
                 "elasticloadbalancing:DescribeLoadBalancers",
                 "elasticloadbalancing:DescribeLoadBalancerAttributes",
                 "elasticloadbalancing:DescribeListeners",
@@ -210,7 +211,8 @@
                 "elasticloadbalancing:DeleteLoadBalancer",
                 "elasticloadbalancing:ModifyTargetGroup",
                 "elasticloadbalancing:ModifyTargetGroupAttributes",
-                "elasticloadbalancing:DeleteTargetGroup"
+                "elasticloadbalancing:DeleteTargetGroup",
+                "elasticloadbalancing:ModifyIpPools"
             ],
             "Resource": "*",
             "Condition": {
diff --git a/docs/install/iam_policy_us-gov.json b/docs/install/iam_policy_us-gov.json
index 790304851..e08541c3a 100644
--- a/docs/install/iam_policy_us-gov.json
+++ b/docs/install/iam_policy_us-gov.json
@@ -30,6 +30,7 @@
                 "ec2:GetCoipPoolUsage",
                 "ec2:DescribeCoipPools",
                 "ec2:GetSecurityGroupsForVpc",
+                "ec2:DescribeIpamPools",
                 "elasticloadbalancing:DescribeLoadBalancers",
                 "elasticloadbalancing:DescribeLoadBalancerAttributes",
                 "elasticloadbalancing:DescribeListeners",
@@ -215,7 +216,8 @@
                 "elasticloadbalancing:ModifyTargetGroupAttributes",
                 "elasticloadbalancing:DeleteTargetGroup",
                 "elasticloadbalancing:ModifyListenerAttributes",
-                "elasticloadbalancing:ModifyCapacityReservation"
+                "elasticloadbalancing:ModifyCapacityReservation",
+                "elasticloadbalancing:ModifyIpPools"
             ],
             "Resource": "*",
             "Condition": {
diff --git a/go.mod b/go.mod
index a2186f227..cd974f81d 100644
--- a/go.mod
+++ b/go.mod
@@ -4,21 +4,21 @@ go 1.23.6
 
 require (
 	github.com/aws/aws-sdk-go v1.55.5
-	github.com/aws/aws-sdk-go-v2 v1.32.6
+	github.com/aws/aws-sdk-go-v2 v1.36.3
 	github.com/aws/aws-sdk-go-v2/config v1.27.27
 	github.com/aws/aws-sdk-go-v2/credentials v1.17.27
 	github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11
 	github.com/aws/aws-sdk-go-v2/service/acm v1.28.4
 	github.com/aws/aws-sdk-go-v2/service/appmesh v1.27.7
 	github.com/aws/aws-sdk-go-v2/service/ec2 v1.173.0
-	github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.43.1
+	github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.45.0
 	github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.23.3
 	github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.31.7
 	github.com/aws/aws-sdk-go-v2/service/shield v1.27.3
 	github.com/aws/aws-sdk-go-v2/service/sts v1.30.3
 	github.com/aws/aws-sdk-go-v2/service/wafregional v1.23.3
 	github.com/aws/aws-sdk-go-v2/service/wafv2 v1.51.4
-	github.com/aws/smithy-go v1.22.1
+	github.com/aws/smithy-go v1.22.2
 	github.com/evanphx/json-patch v5.7.0+incompatible
 	github.com/gavv/httpexpect/v2 v2.9.0
 	github.com/go-logr/logr v1.4.2
@@ -58,8 +58,8 @@ require (
 	github.com/ajg/form v1.5.1 // indirect
 	github.com/andybalholm/brotli v1.0.4 // indirect
 	github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect
-	github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25 // indirect
-	github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25 // indirect
+	github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect
+	github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect
 	github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
 	github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 // indirect
 	github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 // indirect
diff --git a/go.sum b/go.sum
index 292ee96ce..1f07bb6f0 100644
--- a/go.sum
+++ b/go.sum
@@ -38,18 +38,18 @@ github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 h1:4daAzAu0
 github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
 github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU=
 github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
-github.com/aws/aws-sdk-go-v2 v1.32.6 h1:7BokKRgRPuGmKkFMhEg/jSul+tB9VvXhcViILtfG8b4=
-github.com/aws/aws-sdk-go-v2 v1.32.6/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U=
+github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM=
+github.com/aws/aws-sdk-go-v2 v1.36.3/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg=
 github.com/aws/aws-sdk-go-v2/config v1.27.27 h1:HdqgGt1OAP0HkEDDShEl0oSYa9ZZBSOmKpdpsDMdO90=
 github.com/aws/aws-sdk-go-v2/config v1.27.27/go.mod h1:MVYamCg76dFNINkZFu4n4RjDixhVr51HLj4ErWzrVwg=
 github.com/aws/aws-sdk-go-v2/credentials v1.17.27 h1:2raNba6gr2IfA0eqqiP2XiQ0UVOpGPgDSi0I9iAP+UI=
 github.com/aws/aws-sdk-go-v2/credentials v1.17.27/go.mod h1:gniiwbGahQByxan6YjQUMcW4Aov6bLC3m+evgcoN4r4=
 github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 h1:KreluoV8FZDEtI6Co2xuNk/UqI9iwMrOx/87PBNIKqw=
 github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11/go.mod h1:SeSUYBLsMYFoRvHE0Tjvn7kbxaUhl75CJi1sbfhMxkU=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25 h1:s/fF4+yDQDoElYhfIVvSNyeCydfbuTKzhxSXDXCPasU=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25/go.mod h1:IgPfDv5jqFIzQSNbUEMoitNooSMXjRSDkhXv8jiROvU=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25 h1:ZntTCl5EsYnhN/IygQEUugpdwbhdkom9uHcbCftiGgA=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25/go.mod h1:DBdPrgeocww+CSl1C8cEV8PN1mHMBhuCDLpXezyvWkE=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 h1:ZK5jHhnrioRkUNOc+hOgQKlUL5JeC3S6JgLxtQ+Rm0Q=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34/go.mod h1:p4VfIceZokChbA9FzMbRGz5OV+lekcVtHlPKEO0gSZY=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 h1:SZwFm17ZUNNg5Np0ioo/gq8Mn6u9w19Mri8DnJ15Jf0=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34/go.mod h1:dFZsC0BLo346mvKQLWmoJxT+Sjp+qcVR1tRVHQGOH9Q=
 github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
 github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
 github.com/aws/aws-sdk-go-v2/service/acm v1.28.4 h1:wiW1Y6/1lysA0eJZRq0I53YYKuV9MNAzL15z2eZRlEE=
@@ -58,8 +58,8 @@ github.com/aws/aws-sdk-go-v2/service/appmesh v1.27.7 h1:q44a6kysAfej9zZwRnraOg9s
 github.com/aws/aws-sdk-go-v2/service/appmesh v1.27.7/go.mod h1:ZYSmrgAMp0rTCHH+SGsoxZo+PPbgsDqBzewTp3tSJ60=
 github.com/aws/aws-sdk-go-v2/service/ec2 v1.173.0 h1:ta62lid9JkIpKZtZZXSj6rP2AqY5x1qYGq53ffxqD9Q=
 github.com/aws/aws-sdk-go-v2/service/ec2 v1.173.0/go.mod h1:o6QDjdVKpP5EF0dp/VlvqckzuSDATr1rLdHt3A5m0YY=
-github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.43.1 h1:L9Wt9zgtoYKIlaeFTy+EztGjL4oaXBBGtVXA+jaeYko=
-github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.43.1/go.mod h1:yxzLdxt7bVGvIOPYIKFtiaJCJnx2ChlIIvlhW4QgI6M=
+github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.45.0 h1:RB7V8wT9ypjE/YJVBgKjoydTOh4IFoqceGiKxFH70mY=
+github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.45.0/go.mod h1:xnCC3vFBfOKpU6PcsCKL2ktgBTZfOwTGxj6V8/X3IS4=
 github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 h1:dT3MqvGhSoaIhRseqw2I0yH81l7wiR2vjs57O51EAm8=
 github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3/go.mod h1:GlAeCkHwugxdHaueRr4nhPuY+WW+gR8UjlcqzPr1SPI=
 github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 h1:HGErhhrxZlQ044RiM+WdoZxp0p+EGM62y3L6pwA4olE=
@@ -80,8 +80,8 @@ github.com/aws/aws-sdk-go-v2/service/wafregional v1.23.3 h1:7dr6En0/6KRFoz8VmnYk
 github.com/aws/aws-sdk-go-v2/service/wafregional v1.23.3/go.mod h1:24TtlRsv4LKAE3VnRJQhpatr8cpX0yj8NSzg8/lxOCw=
 github.com/aws/aws-sdk-go-v2/service/wafv2 v1.51.4 h1:1khBA5uryBRJoCb4G2iR5RT06BkfPEjjDCHAiRb8P3Q=
 github.com/aws/aws-sdk-go-v2/service/wafv2 v1.51.4/go.mod h1:QpFImaPGKNwa+MiZ+oo6LbV1PVQBapc0CnrAMRScoxM=
-github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro=
-github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
+github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ=
+github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
diff --git a/helm/aws-load-balancer-controller/crds/crds.yaml b/helm/aws-load-balancer-controller/crds/crds.yaml
index ea31acc11..e5d1cc177 100644
--- a/helm/aws-load-balancer-controller/crds/crds.yaml
+++ b/helm/aws-load-balancer-controller/crds/crds.yaml
@@ -84,6 +84,15 @@ spec:
                 - dualstack
                 - dualstack-without-public-ipv4
                 type: string
+              ipamConfiguration:
+                description: IPAMConfiguration defines the IPAM settings for a Load
+                  Balancer.
+                properties:
+                  ipv4IPAMPoolId:
+                    description: IPv4IPAMPoolId defines the IPAM pool ID used for
+                      IPv4 Addresses on the ALB.
+                    type: string
+                type: object
               listeners:
                 description: Listeners define a list of listeners with their protocol,
                   port and attributes.
diff --git a/pkg/annotations/constants.go b/pkg/annotations/constants.go
index ba7021654..e10709fc9 100644
--- a/pkg/annotations/constants.go
+++ b/pkg/annotations/constants.go
@@ -58,6 +58,7 @@ const (
 	IngressSuffixlsAttsAnnotationPrefix          = "listener-attributes"
 	IngressLBSuffixMultiClusterTargetGroup       = "multi-cluster-target-group"
 	IngressSuffixLoadBalancerCapacityReservation = "minimum-load-balancer-capacity"
+	IngressSuffixIPAMIPv4PoolId                  = "ipam-ipv4-pool-id"
 
 	// NLB annotation suffixes
 	// prefixes service.beta.kubernetes.io, service.kubernetes.io
diff --git a/pkg/aws/services/elbv2.go b/pkg/aws/services/elbv2.go
index c2eb0d401..1db7d21b0 100644
--- a/pkg/aws/services/elbv2.go
+++ b/pkg/aws/services/elbv2.go
@@ -61,6 +61,7 @@ type ELBV2 interface {
 	ModifyListenerAttributesWithContext(ctx context.Context, input *elasticloadbalancingv2.ModifyListenerAttributesInput) (*elasticloadbalancingv2.ModifyListenerAttributesOutput, error)
 	ModifyCapacityReservationWithContext(ctx context.Context, input *elasticloadbalancingv2.ModifyCapacityReservationInput) (*elasticloadbalancingv2.ModifyCapacityReservationOutput, error)
 	DescribeCapacityReservationWithContext(ctx context.Context, input *elasticloadbalancingv2.DescribeCapacityReservationInput) (*elasticloadbalancingv2.DescribeCapacityReservationOutput, error)
+	ModifyIPPoolsWithContext(ctx context.Context, input *elasticloadbalancingv2.ModifyIpPoolsInput) (*elasticloadbalancingv2.ModifyIpPoolsOutput, error)
 	AssumeRole(ctx context.Context, assumeRoleArn string, externalId string) (ELBV2, error)
 }
 
@@ -485,6 +486,14 @@ func (c *elbv2Client) DescribeCapacityReservationWithContext(ctx context.Context
 	return client.DescribeCapacityReservation(ctx, input)
 }
 
+func (c *elbv2Client) ModifyIPPoolsWithContext(ctx context.Context, input *elasticloadbalancingv2.ModifyIpPoolsInput) (*elasticloadbalancingv2.ModifyIpPoolsOutput, error) {
+	client, err := c.getClient(ctx, "ModifyIpPools")
+	if err != nil {
+		return nil, err
+	}
+	return client.ModifyIpPools(ctx, input)
+}
+
 func (c *elbv2Client) getClient(ctx context.Context, operation string) (*elasticloadbalancingv2.Client, error) {
 	if c.staticELBClient != nil {
 		return c.staticELBClient, nil
diff --git a/pkg/aws/services/elbv2_mocks.go b/pkg/aws/services/elbv2_mocks.go
index e04343b2a..055a7aa80 100644
--- a/pkg/aws/services/elbv2_mocks.go
+++ b/pkg/aws/services/elbv2_mocks.go
@@ -471,6 +471,21 @@ func (mr *MockELBV2MockRecorder) ModifyCapacityReservationWithContext(arg0, arg1
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ModifyCapacityReservationWithContext", reflect.TypeOf((*MockELBV2)(nil).ModifyCapacityReservationWithContext), arg0, arg1)
 }
 
+// ModifyIPPoolsWithContext mocks base method.
+func (m *MockELBV2) ModifyIPPoolsWithContext(arg0 context.Context, arg1 *elasticloadbalancingv2.ModifyIpPoolsInput) (*elasticloadbalancingv2.ModifyIpPoolsOutput, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ModifyIPPoolsWithContext", arg0, arg1)
+	ret0, _ := ret[0].(*elasticloadbalancingv2.ModifyIpPoolsOutput)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// ModifyIPPoolsWithContext indicates an expected call of ModifyIPPoolsWithContext.
+func (mr *MockELBV2MockRecorder) ModifyIPPoolsWithContext(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ModifyIPPoolsWithContext", reflect.TypeOf((*MockELBV2)(nil).ModifyIPPoolsWithContext), arg0, arg1)
+}
+
 // ModifyListenerAttributesWithContext mocks base method.
 func (m *MockELBV2) ModifyListenerAttributesWithContext(arg0 context.Context, arg1 *elasticloadbalancingv2.ModifyListenerAttributesInput) (*elasticloadbalancingv2.ModifyListenerAttributesOutput, error) {
 	m.ctrl.T.Helper()
diff --git a/pkg/deploy/elbv2/load_balancer_manager.go b/pkg/deploy/elbv2/load_balancer_manager.go
index bc76c45aa..093991679 100644
--- a/pkg/deploy/elbv2/load_balancer_manager.go
+++ b/pkg/deploy/elbv2/load_balancer_manager.go
@@ -90,6 +90,10 @@ func (m *defaultLoadBalancerManager) Create(ctx context.Context, resLB *elbv2mod
 }
 
 func (m *defaultLoadBalancerManager) Update(ctx context.Context, resLB *elbv2model.LoadBalancer, sdkLB LoadBalancerWithTags) (elbv2model.LoadBalancerStatus, error) {
+	// It's important to remove ipam pools first, because we need to remove any ipam pools before changing the IP Address type.
+	if err := m.removeIPAMPools(ctx, resLB, sdkLB); err != nil {
+		return elbv2model.LoadBalancerStatus{}, err
+	}
 	if err := m.updateSDKLoadBalancerWithTags(ctx, resLB, sdkLB); err != nil {
 		return elbv2model.LoadBalancerStatus{}, err
 	}
@@ -108,6 +112,11 @@ func (m *defaultLoadBalancerManager) Update(ctx context.Context, resLB *elbv2mod
 	if err := m.checkSDKLoadBalancerWithCOIPv4Pool(ctx, resLB, sdkLB); err != nil {
 		return elbv2model.LoadBalancerStatus{}, err
 	}
+	// We can safely change the IPAM pool here after all other modifications are done.
+	if err := m.addIPAMPools(ctx, resLB, sdkLB); err != nil {
+		return elbv2model.LoadBalancerStatus{}, err
+	}
+
 	return buildResLoadBalancerStatus(sdkLB), nil
 }
 
@@ -278,6 +287,43 @@ func (m *defaultLoadBalancerManager) updateSDKLoadBalancerWithTags(ctx context.C
 		WithIgnoredTagKeys(m.externalManagedTags))
 }
 
+func (m *defaultLoadBalancerManager) removeIPAMPools(ctx context.Context, resLB *elbv2model.LoadBalancer, sdkLB LoadBalancerWithTags) error {
+	// No IPAM pool to remove or the request is to actually add / change IPAM pool.
+	if sdkLB.LoadBalancer.IpamPools == nil || resLB.Spec.IPv4IPAMPool != nil {
+		return nil
+	}
+
+	req := &elbv2sdk.ModifyIpPoolsInput{
+		RemoveIpamPools: []elbv2types.RemoveIpamPoolEnum{elbv2types.RemoveIpamPoolEnumIpv4},
+		LoadBalancerArn: sdkLB.LoadBalancer.LoadBalancerArn,
+	}
+
+	_, err := m.elbv2Client.ModifyIPPoolsWithContext(ctx, req)
+	return err
+}
+
+func (m *defaultLoadBalancerManager) addIPAMPools(ctx context.Context, resLB *elbv2model.LoadBalancer, sdkLB LoadBalancerWithTags) error {
+	// No IPAM pool to set, this case should be handled by removeIPAMPools
+	if resLB.Spec.IPv4IPAMPool == nil {
+		return nil
+	}
+
+	// IPAM pool is already correctly set
+	if sdkLB.LoadBalancer.IpamPools != nil && awssdk.ToString(sdkLB.LoadBalancer.IpamPools.Ipv4IpamPoolId) == awssdk.ToString(resLB.Spec.IPv4IPAMPool) {
+		return nil
+	}
+
+	req := &elbv2sdk.ModifyIpPoolsInput{
+		LoadBalancerArn: sdkLB.LoadBalancer.LoadBalancerArn,
+		IpamPools: &elbv2types.IpamPools{
+			Ipv4IpamPoolId: resLB.Spec.IPv4IPAMPool,
+		},
+	}
+
+	_, err := m.elbv2Client.ModifyIPPoolsWithContext(ctx, req)
+	return err
+}
+
 func buildSDKCreateLoadBalancerInput(lbSpec elbv2model.LoadBalancerSpec) (*elbv2sdk.CreateLoadBalancerInput, error) {
 	sdkObj := &elbv2sdk.CreateLoadBalancerInput{}
 	sdkObj.Name = awssdk.String(lbSpec.Name)
@@ -296,6 +342,12 @@ func buildSDKCreateLoadBalancerInput(lbSpec elbv2model.LoadBalancerSpec) (*elbv2
 		sdkObj.EnablePrefixForIpv6SourceNat = elbv2types.EnablePrefixForIpv6SourceNatEnum(lbSpec.EnablePrefixForIpv6SourceNat)
 	}
 
+	if lbSpec.IPv4IPAMPool != nil && awssdk.ToString(lbSpec.IPv4IPAMPool) != "" {
+		sdkObj.IpamPools = &elbv2types.IpamPools{
+			Ipv4IpamPoolId: lbSpec.IPv4IPAMPool,
+		}
+	}
+
 	sdkObj.CustomerOwnedIpv4Pool = lbSpec.CustomerOwnedIPv4Pool
 	return sdkObj, nil
 }
diff --git a/pkg/deploy/elbv2/load_balancer_manager_test.go b/pkg/deploy/elbv2/load_balancer_manager_test.go
index e2b8567d1..02cdb9b6e 100644
--- a/pkg/deploy/elbv2/load_balancer_manager_test.go
+++ b/pkg/deploy/elbv2/load_balancer_manager_test.go
@@ -213,6 +213,48 @@ func Test_buildSDKCreateLoadBalancerInput(t *testing.T) {
 				CustomerOwnedIpv4Pool: awssdk.String("coIP-pool-x"),
 			},
 		},
+		{
+			name: "application loadBalancer - with ipv4 ipam pool case",
+			args: args{
+				lbSpec: elbv2model.LoadBalancerSpec{
+					Name:          "my-alb",
+					Type:          elbv2model.LoadBalancerTypeApplication,
+					Scheme:        schemeInternetFacing,
+					IPAddressType: addressTypeDualStack,
+					SubnetMappings: []elbv2model.SubnetMapping{
+						{
+							SubnetID: "subnet-A",
+						},
+						{
+							SubnetID: "subnet-B",
+						},
+					},
+					SecurityGroups: []coremodel.StringToken{
+						coremodel.LiteralStringToken("sg-A"),
+						coremodel.LiteralStringToken("sg-B"),
+					},
+					IPv4IPAMPool: awssdk.String("my-ipv4-ipam-pool"),
+				},
+			},
+			want: &elbv2sdk.CreateLoadBalancerInput{
+				Name:          awssdk.String("my-alb"),
+				Type:          elbv2types.LoadBalancerTypeEnumApplication,
+				IpAddressType: elbv2types.IpAddressTypeDualstack,
+				Scheme:        elbv2types.LoadBalancerSchemeEnumInternetFacing,
+				SubnetMappings: []elbv2types.SubnetMapping{
+					{
+						SubnetId: awssdk.String("subnet-A"),
+					},
+					{
+						SubnetId: awssdk.String("subnet-B"),
+					},
+				},
+				SecurityGroups: []string{"sg-A", "sg-B"},
+				IpamPools: &elbv2types.IpamPools{
+					Ipv4IpamPoolId: awssdk.String("my-ipv4-ipam-pool"),
+				},
+			},
+		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
@@ -686,3 +728,308 @@ func Test_defaultLoadBalancerManager_updateSDKLoadBalancerWithSubnetMappings(t *
 		})
 	}
 }
+
+func Test_defaultLoadBalancerManager_removeIPAMPools(t *testing.T) {
+	stack := coremodel.NewDefaultStack(coremodel.StackID{Namespace: "namespace", Name: "name"})
+	tests := []struct {
+		name       string
+		resLB      *elbv2model.LoadBalancer
+		sdkLB      LoadBalancerWithTags
+		wantErr    error
+		wantModify int
+	}{
+		{
+			name: "remove ipam pools when ipam already not set",
+			sdkLB: LoadBalancerWithTags{
+				LoadBalancer: &elbv2types.LoadBalancer{
+					LoadBalancerArn:   awssdk.String("LoadBalancerArn"),
+					Type:              elbv2types.LoadBalancerTypeEnumApplication,
+					AvailabilityZones: []elbv2types.AvailabilityZone{{SubnetId: awssdk.String("subnet-A")}, {SubnetId: awssdk.String("subnet-B")}},
+					IpAddressType:     elbv2types.IpAddressTypeIpv4,
+				},
+			},
+			resLB: &elbv2model.LoadBalancer{
+				ResourceMeta: coremodel.NewResourceMeta(stack, "AWS::ElasticLoadBalancingV2::LoadBalancer", "id-1"),
+				Spec: elbv2model.LoadBalancerSpec{
+					SubnetMappings: []elbv2model.SubnetMapping{
+						{
+							SubnetID:    "subnet-A",
+							IPv6Address: aws.String("2600:1f18::1"),
+						},
+						{
+							SubnetID:    "subnet-B",
+							IPv6Address: aws.String("2600:1f18::2"),
+						},
+					},
+					Type:          elbv2model.LoadBalancerTypeNetwork,
+					IPAddressType: elbv2model.IPAddressTypeDualStack,
+				},
+			},
+		},
+		{
+			name: "remove ipam pools when ipam set",
+			sdkLB: LoadBalancerWithTags{
+				LoadBalancer: &elbv2types.LoadBalancer{
+					LoadBalancerArn:   awssdk.String("LoadBalancerArn"),
+					Type:              elbv2types.LoadBalancerTypeEnumApplication,
+					AvailabilityZones: []elbv2types.AvailabilityZone{{SubnetId: awssdk.String("subnet-A")}, {SubnetId: awssdk.String("subnet-B")}},
+					IpAddressType:     elbv2types.IpAddressTypeIpv4,
+					IpamPools:         &elbv2types.IpamPools{Ipv4IpamPoolId: awssdk.String("foo")},
+				},
+			},
+			resLB: &elbv2model.LoadBalancer{
+				ResourceMeta: coremodel.NewResourceMeta(stack, "AWS::ElasticLoadBalancingV2::LoadBalancer", "id-1"),
+				Spec: elbv2model.LoadBalancerSpec{
+					SubnetMappings: []elbv2model.SubnetMapping{
+						{
+							SubnetID:    "subnet-A",
+							IPv6Address: aws.String("2600:1f18::1"),
+						},
+						{
+							SubnetID:    "subnet-B",
+							IPv6Address: aws.String("2600:1f18::2"),
+						},
+					},
+					Type:          elbv2model.LoadBalancerTypeNetwork,
+					IPAddressType: elbv2model.IPAddressTypeDualStack,
+				},
+			},
+			wantModify: 1,
+		},
+		{
+			name: "add ipam pools when ipam set",
+			sdkLB: LoadBalancerWithTags{
+				LoadBalancer: &elbv2types.LoadBalancer{
+					LoadBalancerArn:   awssdk.String("LoadBalancerArn"),
+					Type:              elbv2types.LoadBalancerTypeEnumApplication,
+					AvailabilityZones: []elbv2types.AvailabilityZone{{SubnetId: awssdk.String("subnet-A")}, {SubnetId: awssdk.String("subnet-B")}},
+					IpAddressType:     elbv2types.IpAddressTypeIpv4,
+					IpamPools:         &elbv2types.IpamPools{Ipv4IpamPoolId: awssdk.String("foo")},
+				},
+			},
+			resLB: &elbv2model.LoadBalancer{
+				ResourceMeta: coremodel.NewResourceMeta(stack, "AWS::ElasticLoadBalancingV2::LoadBalancer", "id-1"),
+				Spec: elbv2model.LoadBalancerSpec{
+					SubnetMappings: []elbv2model.SubnetMapping{
+						{
+							SubnetID:    "subnet-A",
+							IPv6Address: aws.String("2600:1f18::1"),
+						},
+						{
+							SubnetID:    "subnet-B",
+							IPv6Address: aws.String("2600:1f18::2"),
+						},
+					},
+					Type:          elbv2model.LoadBalancerTypeNetwork,
+					IPAddressType: elbv2model.IPAddressTypeDualStack,
+					IPv4IPAMPool:  awssdk.String("bar"),
+				},
+			},
+		},
+		{
+			name: "add ipam pools when ipam not set",
+			sdkLB: LoadBalancerWithTags{
+				LoadBalancer: &elbv2types.LoadBalancer{
+					LoadBalancerArn:   awssdk.String("LoadBalancerArn"),
+					Type:              elbv2types.LoadBalancerTypeEnumApplication,
+					AvailabilityZones: []elbv2types.AvailabilityZone{{SubnetId: awssdk.String("subnet-A")}, {SubnetId: awssdk.String("subnet-B")}},
+					IpAddressType:     elbv2types.IpAddressTypeIpv4,
+				},
+			},
+			resLB: &elbv2model.LoadBalancer{
+				ResourceMeta: coremodel.NewResourceMeta(stack, "AWS::ElasticLoadBalancingV2::LoadBalancer", "id-1"),
+				Spec: elbv2model.LoadBalancerSpec{
+					SubnetMappings: []elbv2model.SubnetMapping{
+						{
+							SubnetID:    "subnet-A",
+							IPv6Address: aws.String("2600:1f18::1"),
+						},
+						{
+							SubnetID:    "subnet-B",
+							IPv6Address: aws.String("2600:1f18::2"),
+						},
+					},
+					Type:          elbv2model.LoadBalancerTypeNetwork,
+					IPAddressType: elbv2model.IPAddressTypeDualStack,
+					IPv4IPAMPool:  awssdk.String("bar"),
+				},
+			},
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			ctrl := gomock.NewController(t)
+			defer ctrl.Finish()
+			elbv2Client := services.NewMockELBV2(ctrl)
+			m := &defaultLoadBalancerManager{
+				logger:      logr.New(&log.NullLogSink{}),
+				elbv2Client: elbv2Client,
+			}
+
+			elbv2Client.EXPECT().ModifyIPPoolsWithContext(gomock.Any(), &elbv2sdk.ModifyIpPoolsInput{LoadBalancerArn: awssdk.String("LoadBalancerArn"), RemoveIpamPools: []elbv2types.RemoveIpamPoolEnum{elbv2types.RemoveIpamPoolEnumIpv4}}).Return(&elbv2sdk.ModifyIpPoolsOutput{}, tt.wantErr).Times(tt.wantModify)
+
+			err := m.removeIPAMPools(context.Background(), tt.resLB, tt.sdkLB)
+			if tt.wantErr != nil {
+				assert.EqualError(t, err, tt.wantErr.Error())
+			} else {
+				assert.NoError(t, err)
+			}
+
+		})
+	}
+}
+
+func Test_defaultLoadBalancerManager_addIPAMPools(t *testing.T) {
+	stack := coremodel.NewDefaultStack(coremodel.StackID{Namespace: "namespace", Name: "name"})
+	tests := []struct {
+		name       string
+		resLB      *elbv2model.LoadBalancer
+		sdkLB      LoadBalancerWithTags
+		wantErr    error
+		wantModify int
+	}{
+		{
+			name: "add ipam pools when ipam not set",
+			sdkLB: LoadBalancerWithTags{
+				LoadBalancer: &elbv2types.LoadBalancer{
+					LoadBalancerArn:   awssdk.String("LoadBalancerArn"),
+					Type:              elbv2types.LoadBalancerTypeEnumApplication,
+					AvailabilityZones: []elbv2types.AvailabilityZone{{SubnetId: awssdk.String("subnet-A")}, {SubnetId: awssdk.String("subnet-B")}},
+					IpAddressType:     elbv2types.IpAddressTypeIpv4,
+				},
+			},
+			resLB: &elbv2model.LoadBalancer{
+				ResourceMeta: coremodel.NewResourceMeta(stack, "AWS::ElasticLoadBalancingV2::LoadBalancer", "id-1"),
+				Spec: elbv2model.LoadBalancerSpec{
+					SubnetMappings: []elbv2model.SubnetMapping{
+						{
+							SubnetID:    "subnet-A",
+							IPv6Address: aws.String("2600:1f18::1"),
+						},
+						{
+							SubnetID:    "subnet-B",
+							IPv6Address: aws.String("2600:1f18::2"),
+						},
+					},
+					Type:          elbv2model.LoadBalancerTypeNetwork,
+					IPAddressType: elbv2model.IPAddressTypeDualStack,
+					IPv4IPAMPool:  awssdk.String("bar"),
+				},
+			},
+			wantModify: 1,
+		},
+		{
+			name: "change ipam pools when already ipam set",
+			sdkLB: LoadBalancerWithTags{
+				LoadBalancer: &elbv2types.LoadBalancer{
+					LoadBalancerArn:   awssdk.String("LoadBalancerArn"),
+					Type:              elbv2types.LoadBalancerTypeEnumApplication,
+					AvailabilityZones: []elbv2types.AvailabilityZone{{SubnetId: awssdk.String("subnet-A")}, {SubnetId: awssdk.String("subnet-B")}},
+					IpAddressType:     elbv2types.IpAddressTypeIpv4,
+					IpamPools:         &elbv2types.IpamPools{Ipv4IpamPoolId: awssdk.String("foo")},
+				},
+			},
+			resLB: &elbv2model.LoadBalancer{
+				ResourceMeta: coremodel.NewResourceMeta(stack, "AWS::ElasticLoadBalancingV2::LoadBalancer", "id-1"),
+				Spec: elbv2model.LoadBalancerSpec{
+					SubnetMappings: []elbv2model.SubnetMapping{
+						{
+							SubnetID:    "subnet-A",
+							IPv6Address: aws.String("2600:1f18::1"),
+						},
+						{
+							SubnetID:    "subnet-B",
+							IPv6Address: aws.String("2600:1f18::2"),
+						},
+					},
+					Type:          elbv2model.LoadBalancerTypeNetwork,
+					IPAddressType: elbv2model.IPAddressTypeDualStack,
+					IPv4IPAMPool:  awssdk.String("bar"),
+				},
+			},
+			wantModify: 1,
+		},
+		{
+			name: "ipam pool equal between sdk and res",
+			sdkLB: LoadBalancerWithTags{
+				LoadBalancer: &elbv2types.LoadBalancer{
+					LoadBalancerArn:   awssdk.String("LoadBalancerArn"),
+					Type:              elbv2types.LoadBalancerTypeEnumApplication,
+					AvailabilityZones: []elbv2types.AvailabilityZone{{SubnetId: awssdk.String("subnet-A")}, {SubnetId: awssdk.String("subnet-B")}},
+					IpAddressType:     elbv2types.IpAddressTypeIpv4,
+					IpamPools:         &elbv2types.IpamPools{Ipv4IpamPoolId: awssdk.String("bar")},
+				},
+			},
+			resLB: &elbv2model.LoadBalancer{
+				ResourceMeta: coremodel.NewResourceMeta(stack, "AWS::ElasticLoadBalancingV2::LoadBalancer", "id-1"),
+				Spec: elbv2model.LoadBalancerSpec{
+					SubnetMappings: []elbv2model.SubnetMapping{
+						{
+							SubnetID:    "subnet-A",
+							IPv6Address: aws.String("2600:1f18::1"),
+						},
+						{
+							SubnetID:    "subnet-B",
+							IPv6Address: aws.String("2600:1f18::2"),
+						},
+					},
+					Type:          elbv2model.LoadBalancerTypeNetwork,
+					IPAddressType: elbv2model.IPAddressTypeDualStack,
+					IPv4IPAMPool:  awssdk.String("bar"),
+				},
+			},
+		},
+		{
+			name: "ipam pool not set in res",
+			sdkLB: LoadBalancerWithTags{
+				LoadBalancer: &elbv2types.LoadBalancer{
+					LoadBalancerArn:   awssdk.String("LoadBalancerArn"),
+					Type:              elbv2types.LoadBalancerTypeEnumApplication,
+					AvailabilityZones: []elbv2types.AvailabilityZone{{SubnetId: awssdk.String("subnet-A")}, {SubnetId: awssdk.String("subnet-B")}},
+					IpAddressType:     elbv2types.IpAddressTypeIpv4,
+					IpamPools:         &elbv2types.IpamPools{Ipv4IpamPoolId: awssdk.String("foo")},
+				},
+			},
+			resLB: &elbv2model.LoadBalancer{
+				ResourceMeta: coremodel.NewResourceMeta(stack, "AWS::ElasticLoadBalancingV2::LoadBalancer", "id-1"),
+				Spec: elbv2model.LoadBalancerSpec{
+					SubnetMappings: []elbv2model.SubnetMapping{
+						{
+							SubnetID:    "subnet-A",
+							IPv6Address: aws.String("2600:1f18::1"),
+						},
+						{
+							SubnetID:    "subnet-B",
+							IPv6Address: aws.String("2600:1f18::2"),
+						},
+					},
+					Type:          elbv2model.LoadBalancerTypeNetwork,
+					IPAddressType: elbv2model.IPAddressTypeDualStack,
+				},
+			},
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			ctrl := gomock.NewController(t)
+			defer ctrl.Finish()
+			elbv2Client := services.NewMockELBV2(ctrl)
+			m := &defaultLoadBalancerManager{
+				logger:      logr.New(&log.NullLogSink{}),
+				elbv2Client: elbv2Client,
+			}
+
+			elbv2Client.EXPECT().ModifyIPPoolsWithContext(gomock.Any(), &elbv2sdk.ModifyIpPoolsInput{LoadBalancerArn: awssdk.String("LoadBalancerArn"), IpamPools: &elbv2types.IpamPools{Ipv4IpamPoolId: awssdk.String("bar")}}).Return(&elbv2sdk.ModifyIpPoolsOutput{}, tt.wantErr).Times(tt.wantModify)
+
+			err := m.addIPAMPools(context.Background(), tt.resLB, tt.sdkLB)
+			if tt.wantErr != nil {
+				assert.EqualError(t, err, tt.wantErr.Error())
+			} else {
+				assert.NoError(t, err)
+			}
+
+		})
+	}
+}
diff --git a/pkg/ingress/model_build_ipam.go b/pkg/ingress/model_build_ipam.go
new file mode 100644
index 000000000..86b238f88
--- /dev/null
+++ b/pkg/ingress/model_build_ipam.go
@@ -0,0 +1,50 @@
+package ingress
+
+import (
+	"github.com/pkg/errors"
+	"sigs.k8s.io/aws-load-balancer-controller/pkg/annotations"
+)
+
+func (t *defaultModelBuildTask) buildIPv4IPAMPoolID() (*string, error) {
+	// We give precedence to the IngressClass value for IPv4 IPAM pool ID.
+	if len(t.ingGroup.Members) > 0 {
+		poolId := t.getIPv4IPAMFromIngressClass(t.ingGroup.Members[0].IngClassConfig)
+		if poolId != nil {
+			return poolId, nil
+		}
+	}
+
+	var poolIdToReturn *string
+
+	for _, ing := range t.ingGroup.Members {
+		poolId := t.getIPv4IPAMFromAnnotation(ing)
+
+		if poolId != nil {
+			if poolIdToReturn != nil && *poolId != *poolIdToReturn {
+				return nil, errors.Errorf("conflicting ipv4 ipam pools %v: %v", *poolIdToReturn, *poolId)
+			}
+			poolIdToReturn = poolId
+		}
+	}
+
+	return poolIdToReturn, nil
+}
+
+// getIPv4IPAMFromAnnotation gets the ipv4 ipam value from the ingress annotation
+func (t *defaultModelBuildTask) getIPv4IPAMFromAnnotation(ing ClassifiedIngress) *string {
+	var ipamPool string
+	if exist := t.annotationParser.ParseStringAnnotation(annotations.IngressSuffixIPAMIPv4PoolId, &ipamPool, ing.Ing.Annotations); exist {
+		if len(ipamPool) > 0 {
+			return &ipamPool
+		}
+	}
+	return nil
+}
+
+// buildIngressClassIPv4IPAM builds the ipv4 ipam pool id for an IngressClass.
+func (t *defaultModelBuildTask) getIPv4IPAMFromIngressClass(ingClassConfig ClassConfiguration) *string {
+	if ingClassConfig.IngClassParams == nil || ingClassConfig.IngClassParams.Spec.IPAMConfiguration == nil || ingClassConfig.IngClassParams.Spec.IPAMConfiguration.IPv4IPAMPoolId == nil {
+		return nil
+	}
+	return ingClassConfig.IngClassParams.Spec.IPAMConfiguration.IPv4IPAMPoolId
+}
diff --git a/pkg/ingress/model_build_ipam_test.go b/pkg/ingress/model_build_ipam_test.go
new file mode 100644
index 000000000..2d87fadd9
--- /dev/null
+++ b/pkg/ingress/model_build_ipam_test.go
@@ -0,0 +1,387 @@
+package ingress
+
+import (
+	awssdk "github.com/aws/aws-sdk-go-v2/aws"
+	"github.com/stretchr/testify/assert"
+	v1 "k8s.io/api/networking/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	elbv2api "sigs.k8s.io/aws-load-balancer-controller/apis/elbv2/v1beta1"
+	"sigs.k8s.io/aws-load-balancer-controller/pkg/annotations"
+	"strings"
+	"testing"
+)
+
+func Test_buildIPv4IPAMPoolID(t *testing.T) {
+	testCases := []struct {
+		name           string
+		ingGroup       Group
+		expectedPoolId *string
+		errSubString   string
+	}{
+		{
+			name: "no ingresses configured",
+		},
+		{
+			name: "one ingress configured",
+			ingGroup: Group{
+				Members: []ClassifiedIngress{
+					{
+						Ing: &v1.Ingress{
+							ObjectMeta: metav1.ObjectMeta{
+								Namespace: "awesome-ns",
+								Name:      "awesome-ing",
+								Annotations: map[string]string{
+									"alb.ingress.kubernetes.io/ipam-ipv4-pool-id": "foo",
+								},
+							},
+						},
+					},
+				},
+			},
+			expectedPoolId: awssdk.String("foo"),
+		},
+		{
+			name: "multiple ingress configured",
+			ingGroup: Group{
+				Members: []ClassifiedIngress{
+					{
+						Ing: &v1.Ingress{
+							ObjectMeta: metav1.ObjectMeta{
+								Namespace: "awesome-ns",
+								Name:      "awesome-ing",
+								Annotations: map[string]string{
+									"alb.ingress.kubernetes.io/ipam-ipv4-pool-id": "foo",
+								},
+							},
+						},
+					},
+					{
+						Ing: &v1.Ingress{
+							ObjectMeta: metav1.ObjectMeta{
+								Namespace: "awesome-ns",
+								Name:      "awesome-ing2",
+								Annotations: map[string]string{
+									"alb.ingress.kubernetes.io/ipam-ipv4-pool-id": "foo",
+								},
+							},
+						},
+					},
+					{
+						Ing: &v1.Ingress{
+							ObjectMeta: metav1.ObjectMeta{
+								Namespace:   "awesome-ns3",
+								Name:        "awesome-ing",
+								Annotations: map[string]string{},
+							},
+						},
+					},
+					{
+						Ing: &v1.Ingress{
+							ObjectMeta: metav1.ObjectMeta{
+								Namespace: "awesome-ns",
+								Name:      "awesome-ing4",
+								Annotations: map[string]string{
+									"alb.ingress.kubernetes.io/ipam-ipv4-pool-id": "foo",
+								},
+							},
+						},
+					},
+				},
+			},
+			expectedPoolId: awssdk.String("foo"),
+		},
+		{
+			name: "multiple ingress configured with different pool ids",
+			ingGroup: Group{
+				Members: []ClassifiedIngress{
+					{
+						Ing: &v1.Ingress{
+							ObjectMeta: metav1.ObjectMeta{
+								Namespace: "awesome-ns",
+								Name:      "awesome-ing",
+								Annotations: map[string]string{
+									"alb.ingress.kubernetes.io/ipam-ipv4-pool-id": "foo",
+								},
+							},
+						},
+					},
+					{
+						Ing: &v1.Ingress{
+							ObjectMeta: metav1.ObjectMeta{
+								Namespace: "awesome-ns",
+								Name:      "awesome-ing2",
+								Annotations: map[string]string{
+									"alb.ingress.kubernetes.io/ipam-ipv4-pool-id": "bar",
+								},
+							},
+						},
+					},
+					{
+						Ing: &v1.Ingress{
+							ObjectMeta: metav1.ObjectMeta{
+								Namespace:   "awesome-ns3",
+								Name:        "awesome-ing",
+								Annotations: map[string]string{},
+							},
+						},
+					},
+					{
+						Ing: &v1.Ingress{
+							ObjectMeta: metav1.ObjectMeta{
+								Namespace: "awesome-ns",
+								Name:      "awesome-ing4",
+								Annotations: map[string]string{
+									"alb.ingress.kubernetes.io/ipam-ipv4-pool-id": "baz",
+								},
+							},
+						},
+					},
+				},
+			},
+			errSubString: "conflicting ipv4 ipam pools",
+		},
+		{
+			name: "no ing class params",
+			ingGroup: Group{
+				Members: []ClassifiedIngress{
+					{
+						IngClassConfig: ClassConfiguration{
+							IngClass:       nil,
+							IngClassParams: nil,
+						},
+						Ing: &v1.Ingress{
+							ObjectMeta: metav1.ObjectMeta{
+								Namespace: "awesome-ns",
+								Name:      "awesome-ing",
+								Annotations: map[string]string{
+									"alb.ingress.kubernetes.io/ipam-ipv4-pool-id": "foo",
+								},
+							},
+						},
+					},
+					{
+						Ing: &v1.Ingress{
+							ObjectMeta: metav1.ObjectMeta{
+								Namespace: "awesome-ns",
+								Name:      "awesome-ing2",
+								Annotations: map[string]string{
+									"alb.ingress.kubernetes.io/ipam-ipv4-pool-id": "bar",
+								},
+							},
+						},
+					},
+					{
+						Ing: &v1.Ingress{
+							ObjectMeta: metav1.ObjectMeta{
+								Namespace:   "awesome-ns3",
+								Name:        "awesome-ing",
+								Annotations: map[string]string{},
+							},
+						},
+					},
+					{
+						Ing: &v1.Ingress{
+							ObjectMeta: metav1.ObjectMeta{
+								Namespace: "awesome-ns",
+								Name:      "awesome-ing4",
+								Annotations: map[string]string{
+									"alb.ingress.kubernetes.io/ipam-ipv4-pool-id": "baz",
+								},
+							},
+						},
+					},
+				},
+			},
+			errSubString: "conflicting ipv4 ipam pools",
+		},
+		{
+			name: "no ipam configuration",
+			ingGroup: Group{
+				Members: []ClassifiedIngress{
+					{
+						IngClassConfig: ClassConfiguration{
+							IngClassParams: &elbv2api.IngressClassParams{
+								Spec: elbv2api.IngressClassParamsSpec{},
+							},
+						},
+						Ing: &v1.Ingress{
+							ObjectMeta: metav1.ObjectMeta{
+								Namespace: "awesome-ns",
+								Name:      "awesome-ing",
+								Annotations: map[string]string{
+									"alb.ingress.kubernetes.io/ipam-ipv4-pool-id": "foo",
+								},
+							},
+						},
+					},
+					{
+						Ing: &v1.Ingress{
+							ObjectMeta: metav1.ObjectMeta{
+								Namespace: "awesome-ns",
+								Name:      "awesome-ing2",
+								Annotations: map[string]string{
+									"alb.ingress.kubernetes.io/ipam-ipv4-pool-id": "bar",
+								},
+							},
+						},
+					},
+					{
+						Ing: &v1.Ingress{
+							ObjectMeta: metav1.ObjectMeta{
+								Namespace:   "awesome-ns3",
+								Name:        "awesome-ing",
+								Annotations: map[string]string{},
+							},
+						},
+					},
+					{
+						Ing: &v1.Ingress{
+							ObjectMeta: metav1.ObjectMeta{
+								Namespace: "awesome-ns",
+								Name:      "awesome-ing4",
+								Annotations: map[string]string{
+									"alb.ingress.kubernetes.io/ipam-ipv4-pool-id": "baz",
+								},
+							},
+						},
+					},
+				},
+			},
+			errSubString: "conflicting ipv4 ipam pools",
+		},
+		{
+			name: "no pool configuration",
+			ingGroup: Group{
+				Members: []ClassifiedIngress{
+					{
+						IngClassConfig: ClassConfiguration{
+							IngClassParams: &elbv2api.IngressClassParams{
+								Spec: elbv2api.IngressClassParamsSpec{
+									IPAMConfiguration: &elbv2api.IPAMConfiguration{},
+								},
+							},
+						},
+						Ing: &v1.Ingress{
+							ObjectMeta: metav1.ObjectMeta{
+								Namespace: "awesome-ns",
+								Name:      "awesome-ing",
+								Annotations: map[string]string{
+									"alb.ingress.kubernetes.io/ipam-ipv4-pool-id": "foo",
+								},
+							},
+						},
+					},
+					{
+						Ing: &v1.Ingress{
+							ObjectMeta: metav1.ObjectMeta{
+								Namespace: "awesome-ns",
+								Name:      "awesome-ing2",
+								Annotations: map[string]string{
+									"alb.ingress.kubernetes.io/ipam-ipv4-pool-id": "bar",
+								},
+							},
+						},
+					},
+					{
+						Ing: &v1.Ingress{
+							ObjectMeta: metav1.ObjectMeta{
+								Namespace:   "awesome-ns3",
+								Name:        "awesome-ing",
+								Annotations: map[string]string{},
+							},
+						},
+					},
+					{
+						Ing: &v1.Ingress{
+							ObjectMeta: metav1.ObjectMeta{
+								Namespace: "awesome-ns",
+								Name:      "awesome-ing4",
+								Annotations: map[string]string{
+									"alb.ingress.kubernetes.io/ipam-ipv4-pool-id": "baz",
+								},
+							},
+						},
+					},
+				},
+			},
+			errSubString: "conflicting ipv4 ipam pools",
+		},
+		{
+			name: "ingress class parameter preferred",
+			ingGroup: Group{
+				Members: []ClassifiedIngress{
+					{
+						IngClassConfig: ClassConfiguration{
+							IngClassParams: &elbv2api.IngressClassParams{
+								Spec: elbv2api.IngressClassParamsSpec{
+									IPAMConfiguration: &elbv2api.IPAMConfiguration{
+										IPv4IPAMPoolId: awssdk.String("ing-class-value"),
+									},
+								},
+							},
+						},
+						Ing: &v1.Ingress{
+							ObjectMeta: metav1.ObjectMeta{
+								Namespace: "awesome-ns",
+								Name:      "awesome-ing",
+								Annotations: map[string]string{
+									"alb.ingress.kubernetes.io/ipam-ipv4-pool-id": "foo",
+								},
+							},
+						},
+					},
+					{
+						Ing: &v1.Ingress{
+							ObjectMeta: metav1.ObjectMeta{
+								Namespace: "awesome-ns",
+								Name:      "awesome-ing2",
+								Annotations: map[string]string{
+									"alb.ingress.kubernetes.io/ipam-ipv4-pool-id": "bar",
+								},
+							},
+						},
+					},
+					{
+						Ing: &v1.Ingress{
+							ObjectMeta: metav1.ObjectMeta{
+								Namespace:   "awesome-ns3",
+								Name:        "awesome-ing",
+								Annotations: map[string]string{},
+							},
+						},
+					},
+					{
+						Ing: &v1.Ingress{
+							ObjectMeta: metav1.ObjectMeta{
+								Namespace: "awesome-ns",
+								Name:      "awesome-ing4",
+								Annotations: map[string]string{
+									"alb.ingress.kubernetes.io/ipam-ipv4-pool-id": "baz",
+								},
+							},
+						},
+					},
+				},
+			},
+			expectedPoolId: awssdk.String("ing-class-value"),
+		},
+	}
+
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			annotationParser := annotations.NewSuffixAnnotationParser("alb.ingress.kubernetes.io")
+			buildTask := &defaultModelBuildTask{
+				ingGroup:         tc.ingGroup,
+				annotationParser: annotationParser,
+			}
+
+			resolvedPoolId, err := buildTask.buildIPv4IPAMPoolID()
+			if len(tc.errSubString) > 0 {
+				assert.True(t, strings.Contains(err.Error(), tc.errSubString))
+			} else {
+				assert.Nil(t, err)
+				assert.Equal(t, tc.expectedPoolId, resolvedPoolId)
+			}
+		})
+	}
+}
diff --git a/pkg/ingress/model_build_load_balancer.go b/pkg/ingress/model_build_load_balancer.go
index 111905cbf..1db3b8a2f 100644
--- a/pkg/ingress/model_build_load_balancer.go
+++ b/pkg/ingress/model_build_load_balancer.go
@@ -75,6 +75,11 @@ func (t *defaultModelBuildTask) buildLoadBalancerSpec(ctx context.Context, liste
 	if err != nil {
 		return elbv2model.LoadBalancerSpec{}, err
 	}
+	ipv4IPAM, err := t.buildIPv4IPAMPoolID()
+	if err != nil {
+		return elbv2model.LoadBalancerSpec{}, err
+	}
+
 	return elbv2model.LoadBalancerSpec{
 		Name:                        name,
 		Type:                        elbv2model.LoadBalancerTypeApplication,
@@ -86,6 +91,7 @@ func (t *defaultModelBuildTask) buildLoadBalancerSpec(ctx context.Context, liste
 		LoadBalancerAttributes:      loadBalancerAttributes,
 		MinimumLoadBalancerCapacity: lbMinimumCapacity,
 		Tags:                        tags,
+		IPv4IPAMPool:                ipv4IPAM,
 	}, nil
 }
 
diff --git a/pkg/model/elbv2/load_balancer.go b/pkg/model/elbv2/load_balancer.go
index b52143096..62fb45417 100644
--- a/pkg/model/elbv2/load_balancer.go
+++ b/pkg/model/elbv2/load_balancer.go
@@ -201,6 +201,9 @@ type LoadBalancerSpec struct {
 	// The tags.
 	// +optional
 	Tags map[string]string `json:"tags,omitempty"`
+
+	// The IPv4 IPAM pool ID
+	IPv4IPAMPool *string `json:"ipv4IPAMPool,omitempty"`
 }
 
 // LoadBalancerStatus defines the observed state of LoadBalancer