diff --git a/gso/services/netbox_client.py b/gso/services/netbox_client.py
index aac06eea66fcd21281e030486c30e3c647fbbf5e..96d0cc8743e66a2c463cb6adbade8d197168de2a 100644
--- a/gso/services/netbox_client.py
+++ b/gso/services/netbox_client.py
@@ -3,6 +3,7 @@ from uuid import UUID
 
 import pydantic
 import pynetbox
+from infoblox_client.objects import Interface
 from pynetbox.models.dcim import Devices, DeviceTypes, Interfaces
 
 from gso.products.product_types.router import Router
@@ -256,6 +257,17 @@ class NetboxClient:
 
         return interface
 
+    def detach_interfaces_from_lag(self, device_name: str, lag_name: str) -> None:
+        """Detach all interfaces from a LAG."""
+        device = self.get_device_by_name(device_name)
+        lag = self.netbox.dcim.interfaces.get(device_id=device.id, name=lag_name)
+        for interface in self.netbox.dcim.interfaces.filter(
+            device_id=device.id, lag_id=lag.id, enabled=False, mark_connected=False
+        ):
+            interface.lag = None
+            interface.save()
+        return
+
     def deallocate_interface(self, device_name: str, iface_name: str) -> Interfaces:
         """Allocate an interface by marking it as connected."""
 
@@ -310,3 +322,13 @@ class NetboxClient:
         return self.netbox.dcim.interfaces.filter(
             device=device.name, enabled=False, mark_connected=False, speed=speed_bps
         )
+
+    def get_interface_by_name_and_device(self, router_id: UUID, interface_name: str) -> Interface:
+        """Return the interface object by name and device from netbox, or ``None`` if not found."""
+
+        router = Router.from_subscription(router_id).router.router_fqdn
+        device = self.get_device_by_name(router)
+        try:
+            return self.netbox.dcim.interfaces.get(device=device.name, name=interface_name)
+        except pynetbox.RequestError:
+            raise NotFoundError(f"Interface: {interface_name} on device: {device.name} not found.")
diff --git a/gso/services/provisioning_proxy.py b/gso/services/provisioning_proxy.py
index 5a6ba11d79fedcfa8431d1dc0c8a283e23c9d73e..c29d942915a537e1a9d64ad0ad449449dd2ae9e0 100644
--- a/gso/services/provisioning_proxy.py
+++ b/gso/services/provisioning_proxy.py
@@ -103,7 +103,12 @@ def provision_router(
 
 
 def provision_ip_trunk(
-    subscription: IptrunkProvisioning, process_id: UUIDstr, tt_number: str, config_object: str, dry_run: bool = True
+    subscription: IptrunkProvisioning,
+    process_id: UUIDstr,
+    tt_number: str,
+    config_object: str,
+    dry_run: bool = True,
+    removed_ae_members: list[str] | None = None,
 ) -> None:
     """Provision an IP trunk service using :term:`LSO`.
 
@@ -116,6 +121,8 @@ def provision_ip_trunk(
     :param dry_run: A boolean indicating whether this should be a dry run or not, defaults to `True`.
     :type dry_run: bool
     :rtype: None
+    :param removed_ae_members: A list of interfaces that are removed from the :term:`LAG`, defaults to `None`.
+     it's only used when we removed some interfaces from the LAG in modify_ip_trunk.
     """
     parameters = {
         "subscription": json.loads(json_dumps(subscription)),
@@ -124,6 +131,7 @@ def provision_ip_trunk(
         "tt_number": tt_number,
         "process_id": process_id,
         "object": config_object,
+        "removed_ae_members": removed_ae_members,
     }
 
     _send_request("ip_trunk", parameters, process_id, CUDOperation.POST)
@@ -175,7 +183,7 @@ def migrate_ip_trunk(
     subscription: Iptrunk,
     new_node: Router,
     new_lag_interface: str,
-    new_lag_member_interfaces: list[str],
+    new_lag_member_interfaces: list[dict],
     replace_index: int,
     process_id: UUIDstr,
     tt_number: str,
diff --git a/gso/utils/helpers.py b/gso/utils/helpers.py
index ff37395b92b3c3d7a8c9b5c61e392afa7b7bbe31..fabfddecfd69aa90151d331bf0c0a205eedda26b 100644
--- a/gso/utils/helpers.py
+++ b/gso/utils/helpers.py
@@ -7,6 +7,7 @@ from orchestrator.types import State, UUIDstr
 from pydantic import BaseModel
 from pydantic_forms.validators import Choice
 
+from gso.products.product_blocks.iptrunk import IptrunkInterfaceBlock
 from gso.products.product_blocks.router import RouterVendor
 from gso.products.product_types.iptrunk import Iptrunk
 from gso.products.product_types.router import Router
@@ -51,6 +52,30 @@ def available_interfaces_choices(router_id: UUID, speed: str) -> Choice | None:
     return Choice("ae member", zip(interfaces.keys(), interfaces.items()))  # type: ignore[arg-type]
 
 
+def available_interfaces_choices_including_current_members(
+    router_id: UUID, speed: str, interfaces: list[IptrunkInterfaceBlock]
+) -> Choice | None:
+    """Return a list of available interfaces for a given router and speed including the current members.
+
+    For Nokia routers, return a list of available interfaces.
+    For Juniper routers, return a string.
+    """
+    if Router.from_subscription(router_id).router.router_vendor != RouterVendor.NOKIA:
+        return None
+    available_interfaces = list(NetboxClient().get_available_interfaces(router_id, speed))
+    available_interfaces.extend(
+        [
+            NetboxClient().get_interface_by_name_and_device(router_id, interface.interface_name)
+            for interface in interfaces
+        ]
+    )
+    options = {
+        interface["name"]: f"{interface['name']} - {interface['module']['display']} - {interface['description']}"
+        for interface in available_interfaces
+    }
+    return Choice("ae member", zip(options.keys(), options.items()))  # type: ignore[arg-type]
+
+
 def available_lags_choices(router_id: UUID) -> Choice | None:
     """Return a list of available lags for a given router.
 
diff --git a/gso/workflows/iptrunk/migrate_iptrunk.py b/gso/workflows/iptrunk/migrate_iptrunk.py
index b1e48b57091f0f0ca971b8eab07e94401b064dd0..e31d0011e5968a51de9276a17626f33e98715c99 100644
--- a/gso/workflows/iptrunk/migrate_iptrunk.py
+++ b/gso/workflows/iptrunk/migrate_iptrunk.py
@@ -1,6 +1,8 @@
+import copy
 import re
 from logging import getLogger
 from typing import NoReturn
+from uuid import uuid4
 
 from orchestrator import step, workflow
 from orchestrator.config.assignee import Assignee
@@ -12,8 +14,10 @@ from orchestrator.workflow import StepList, done, init, inputstep
 from orchestrator.workflows.steps import resync, store_process_subscription, unsync
 from orchestrator.workflows.utils import wrap_modify_initial_input_form
 from pydantic import validator
+from pydantic_forms.core import ReadOnlyField
 from pynetbox.models.dcim import Interfaces
 
+from gso.products.product_blocks.iptrunk import IptrunkInterfaceBlock
 from gso.products.product_blocks.router import RouterVendor
 from gso.products.product_types.iptrunk import Iptrunk
 from gso.products.product_types.router import Router
@@ -21,7 +25,13 @@ from gso.services import provisioning_proxy
 from gso.services.netbox_client import NetboxClient
 from gso.services.provisioning_proxy import pp_interaction
 from gso.services.subscriptions import get_active_router_subscriptions
-from gso.utils.helpers import available_interfaces_choices, available_lags_choices, get_router_vendor, set_isis_to_90000
+from gso.utils.helpers import (
+    LAGMember,
+    available_interfaces_choices,
+    available_lags_choices,
+    get_router_vendor,
+    set_isis_to_90000,
+)
 
 logger = getLogger(__name__)
 
@@ -55,9 +65,9 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
     migrate_form_input = yield IPTrunkMigrateForm
 
     current_routers = [
-        subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.subscription.subscription_id,
-        subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node.subscription.subscription_id,
+        side.iptrunk_side_node.subscription.subscription_id for side in subscription.iptrunk.iptrunk_sides
     ]
+
     routers = {}
     for router_id, router_description in get_active_router_subscriptions(fields=["subscription_id", "description"]):
         if router_id not in current_routers:
@@ -82,25 +92,44 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
     new_router = new_side_iptrunk_router_input.new_node
     side_a_ae_iface = available_lags_choices(new_router) or str
 
-    class LagMemberList(UniqueConstrainedList[str]):
-        min_items = len(subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_members)
-        max_items = len(subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_members)
-        item_type = available_interfaces_choices(new_router, subscription.iptrunk.iptrunk_speed)  # type: ignore
-        unique_items = True
+    if get_router_vendor(new_router) == RouterVendor.NOKIA:
+
+        class NokiaLAGMember(LAGMember):
+            interface_name: available_interfaces_choices(  # type: ignore[valid-type]
+                new_router, subscription.iptrunk.iptrunk_speed
+            )
+
+        class NokiaAeMembers(UniqueConstrainedList[NokiaLAGMember]):
+            min_items = len(subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_members)
+            max_items = len(subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_members)
+
+        ae_members = NokiaAeMembers
+    else:
 
-    class JuniperLagMemberList(UniqueConstrainedList[str]):
-        min_items = len(subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_members)
-        max_items = len(subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_members)
-        unique_items = True
+        class JuniperLagMember(UniqueConstrainedList[LAGMember]):
+            min_items = len(subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_members)
+            max_items = len(subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_members)
 
-    ae_members_side_a = LagMemberList if get_router_vendor(new_router) == RouterVendor.NOKIA else JuniperLagMemberList
+        ae_members = JuniperLagMember  # type: ignore[assignment]
+
+    replace_index = (
+        0
+        if str(subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.subscription.subscription_id)
+        == migrate_form_input.replace_side
+        else 1
+    )
+    existing_lag_ae_members = [
+        {"interface_name": iface.interface_name, "interface_description": iface.interface_description}
+        for iface in subscription.iptrunk.iptrunk_sides[replace_index].iptrunk_side_ae_members
+    ]
 
     class NewSideIPTrunkForm(FormPage):
         class Config:
             title = form_title
 
         new_lag_interface: side_a_ae_iface  # type: ignore[valid-type]
-        new_lag_member_interfaces: ae_members_side_a  # type: ignore[valid-type]
+        existing_lag_interface: list[LAGMember] = ReadOnlyField(existing_lag_ae_members)
+        new_lag_member_interfaces: ae_members  # type: ignore[valid-type]
 
         @validator("new_lag_interface", allow_reuse=True, pre=True, always=True)
         def lag_interface_proper_name(cls, new_lag_interface: str) -> str | NoReturn:
@@ -111,18 +140,11 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
             return new_lag_interface
 
     new_side_input = yield NewSideIPTrunkForm
-
-    def _find_updated_side_of_trunk(trunk: Iptrunk, new_side: str) -> int:
-        for side in trunk.iptrunk.iptrunk_sides:
-            if str(side.iptrunk_side_node.subscription.subscription_id) == new_side:
-                return trunk.iptrunk.iptrunk_sides.index(side)
-        raise ValueError("Invalid Router id provided to be replaced!")
-
     return (
         migrate_form_input.dict()
         | new_side_iptrunk_router_input.dict()
         | new_side_input.dict()
-        | {"replace_index": _find_updated_side_of_trunk(subscription, migrate_form_input.replace_side)}
+        | {"replace_index": replace_index}
     )
 
 
@@ -131,7 +153,7 @@ def disable_old_config_dry(
     subscription: Iptrunk,
     new_node: Router,
     new_lag_interface: str,
-    new_lag_member_interfaces: list[str],
+    new_lag_member_interfaces: list[dict],
     replace_index: int,
     process_id: UUIDstr,
     tt_number: str,
@@ -159,7 +181,7 @@ def disable_old_config_real(
     subscription: Iptrunk,
     new_node: Router,
     new_lag_interface: str,
-    new_lag_member_interfaces: list[str],
+    new_lag_member_interfaces: list[dict],
     replace_index: int,
     process_id: UUIDstr,
     tt_number: str,
@@ -188,7 +210,7 @@ def deploy_new_config_dry(
     subscription: Iptrunk,
     new_node: Router,
     new_lag_interface: str,
-    new_lag_member_interfaces: list[str],
+    new_lag_member_interfaces: list[dict],
     replace_index: int,
     process_id: UUIDstr,
     tt_number: str,
@@ -218,7 +240,7 @@ def deploy_new_config_real(
     subscription: Iptrunk,
     new_node: Router,
     new_lag_interface: str,
-    new_lag_member_interfaces: list[str],
+    new_lag_member_interfaces: list[dict],
     replace_index: int,
     process_id: UUIDstr,
     tt_number: str,
@@ -268,7 +290,7 @@ def deploy_new_isis(
     subscription: Iptrunk,
     new_node: Router,
     new_lag_interface: str,
-    new_lag_member_interfaces: list[str],
+    new_lag_member_interfaces: list[dict],
     replace_index: int,
     process_id: UUIDstr,
     tt_number: str,
@@ -322,7 +344,7 @@ def delete_old_config_dry(
     subscription: Iptrunk,
     new_node: Router,
     new_lag_interface: str,
-    new_lag_member_interfaces: list[str],
+    new_lag_member_interfaces: list[dict],
     replace_index: int,
     process_id: UUIDstr,
     tt_number: str,
@@ -353,7 +375,7 @@ def delete_old_config_real(
     subscription: Iptrunk,
     new_node: Router,
     new_lag_interface: str,
-    new_lag_member_interfaces: list[str],
+    new_lag_member_interfaces: list[dict],
     replace_index: int,
     process_id: UUIDstr,
     tt_number: str,
@@ -392,16 +414,23 @@ def update_subscription_model(
     replace_index: int,
     new_node: UUIDstr,
     new_lag_interface: str,
-    new_lag_member_interfaces: list[str],
+    new_lag_member_interfaces: list[dict],
 ) -> State:
+    # Deep copy of subscription data
+    old_subscription = copy.deepcopy(subscription)
     old_side_data = {
-        "iptrunk_side_node": subscription.iptrunk.iptrunk_sides[replace_index].iptrunk_side_node,
-        "iptrunk_side_ae_iface": subscription.iptrunk.iptrunk_sides[replace_index].iptrunk_side_ae_iface,
-        "iptrunk_side_ae_members": subscription.iptrunk.iptrunk_sides[replace_index].iptrunk_side_ae_members,
+        "iptrunk_side_node": old_subscription.iptrunk.iptrunk_sides[replace_index].iptrunk_side_node,
+        "iptrunk_side_ae_iface": old_subscription.iptrunk.iptrunk_sides[replace_index].iptrunk_side_ae_iface,
+        "iptrunk_side_ae_members": old_subscription.iptrunk.iptrunk_sides[replace_index].iptrunk_side_ae_members,
     }
     subscription.iptrunk.iptrunk_sides[replace_index].iptrunk_side_node = Router.from_subscription(new_node).router
     subscription.iptrunk.iptrunk_sides[replace_index].iptrunk_side_ae_iface = new_lag_interface
-    subscription.iptrunk.iptrunk_sides[replace_index].iptrunk_side_ae_members = new_lag_member_interfaces
+    subscription.iptrunk.iptrunk_sides[replace_index].iptrunk_side_ae_members.clear()
+    #  And update the list to only include the new member interfaces
+    for member in new_lag_member_interfaces:
+        subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_members.append(
+            IptrunkInterfaceBlock.new(subscription_id=uuid4(), **member)
+        )
 
     return {"subscription": subscription, "old_side_data": old_side_data}
 
@@ -411,7 +440,7 @@ def reserve_interfaces_in_netbox(
     subscription: Iptrunk,
     new_node: UUIDstr,
     new_lag_interface: str,
-    new_lag_member_interfaces: list[str],
+    new_lag_member_interfaces: list[dict],
 ) -> State:
     new_side = Router.from_subscription(new_node).router
 
@@ -431,17 +460,17 @@ def reserve_interfaces_in_netbox(
             nbclient.attach_interface_to_lag(
                 device_name=new_side.router_fqdn,
                 lag_name=lag_interface.name,
-                iface_name=interface,
+                iface_name=interface["interface_name"],
                 description=str(subscription.subscription_id),
             )
             nbclient.reserve_interface(
                 device_name=new_side.router_fqdn,
-                iface_name=interface,
+                iface_name=interface["interface_name"],
             )
     return {"subscription": subscription}
 
 
-@step("Update Netbox.")
+@step("Update Netbox. Allocate new interfaces and deallocate old ones.")
 def update_netbox(
     subscription: Iptrunk,
     replace_index: int,
@@ -453,12 +482,12 @@ def update_netbox(
         for interface in new_side.iptrunk_side_ae_members:
             nbclient.allocate_interface(
                 device_name=new_side.iptrunk_side_node.router_fqdn,
-                iface_name=interface,
+                iface_name=interface.interface_name,
             )
     if old_side_data["iptrunk_side_node"]["router_vendor"] == RouterVendor.NOKIA:
         # Set interfaces to free
         for iface in old_side_data["iptrunk_side_ae_members"]:
-            nbclient.free_interface(old_side_data["iptrunk_side_node"]["router_fqdn"], iface)
+            nbclient.free_interface(old_side_data["iptrunk_side_node"]["router_fqdn"], iface["interface_name"])
 
         # Delete LAG interfaces
         nbclient.delete_interface(
diff --git a/gso/workflows/iptrunk/modify_trunk_interface.py b/gso/workflows/iptrunk/modify_trunk_interface.py
index 284602504eb7af3d7d7563728fbe401a1ce0f424..a2448438769d53077773d79586f9c1fbdc586a0e 100644
--- a/gso/workflows/iptrunk/modify_trunk_interface.py
+++ b/gso/workflows/iptrunk/modify_trunk_interface.py
@@ -1,4 +1,5 @@
 import ipaddress
+from typing import List, Type
 from uuid import uuid4
 
 from orchestrator.forms import FormPage, ReadOnlyField
@@ -8,12 +9,50 @@ from orchestrator.types import FormGenerator, State, UUIDstr
 from orchestrator.workflow import StepList, done, init, step, workflow
 from orchestrator.workflows.steps import resync, store_process_subscription, unsync
 from orchestrator.workflows.utils import wrap_modify_initial_input_form
+from pydantic import validator
+from pydantic_forms.validators import Label
 
 from gso.products.product_blocks.iptrunk import IptrunkInterfaceBlock, IptrunkType, PhyPortCapacity
+from gso.products.product_blocks.router import RouterVendor
 from gso.products.product_types.iptrunk import Iptrunk
 from gso.services import provisioning_proxy
+from gso.services.netbox_client import NetboxClient
 from gso.services.provisioning_proxy import pp_interaction
-from gso.utils.helpers import LAGMember
+from gso.utils.helpers import (
+    LAGMember,
+    available_interfaces_choices,
+    available_interfaces_choices_including_current_members,
+    validate_iptrunk_unique_interface,
+)
+
+
+def initialize_ae_members(subscription: Iptrunk, initial_user_input: dict, side_index: int) -> Type[LAGMember]:
+    """Initialize the list of AE members."""
+    router = subscription.iptrunk.iptrunk_sides[side_index].iptrunk_side_node
+    iptrunk_minimum_link = initial_user_input["iptrunk_minimum_links"]
+    if router.router_vendor == RouterVendor.NOKIA:
+        iptrunk_speed = initial_user_input["iptrunk_speed"]
+
+        class NokiaLAGMember(LAGMember):
+            interface_name: available_interfaces_choices_including_current_members(  # type: ignore[valid-type]
+                router.owner_subscription_id,
+                iptrunk_speed,
+                subscription.iptrunk.iptrunk_sides[side_index].iptrunk_side_ae_members,
+            ) if iptrunk_speed == subscription.iptrunk.iptrunk_speed else (
+                available_interfaces_choices(router.owner_subscription_id, initial_user_input["iptrunk_speed"])
+            )
+
+        class NokiaAeMembers(UniqueConstrainedList[NokiaLAGMember]):
+            min_items = iptrunk_minimum_link
+
+        ae_members = NokiaAeMembers
+    else:
+
+        class JuniperAeMembers(UniqueConstrainedList[LAGMember]):
+            min_items = iptrunk_minimum_link
+
+        ae_members = JuniperAeMembers  # type: ignore[assignment]
+    return ae_members  # type: ignore[return-value]
 
 
 def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
@@ -24,6 +63,10 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
         geant_s_sid: str = subscription.iptrunk.geant_s_sid
         iptrunk_description: str = subscription.iptrunk.iptrunk_description
         iptrunk_type: IptrunkType = subscription.iptrunk.iptrunk_type
+        warning_label: Label = (
+            "Changing the PhyPortCapacity will result in the deletion of all AE members. "
+            "You will need to add the new AE members in the next steps."  # type: ignore[assignment]
+        )
         iptrunk_speed: PhyPortCapacity = subscription.iptrunk.iptrunk_speed
         iptrunk_minimum_links: int = subscription.iptrunk.iptrunk_minimum_links
         iptrunk_isis_metric: int = ReadOnlyField(subscription.iptrunk.iptrunk_isis_metric)
@@ -31,9 +74,7 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
         iptrunk_ipv6_network: ipaddress.IPv6Network = ReadOnlyField(subscription.iptrunk.iptrunk_ipv6_network)
 
     initial_user_input = yield ModifyIptrunkForm
-
-    class AeMembersListA(UniqueConstrainedList[LAGMember]):
-        min_items = initial_user_input.iptrunk_minimum_links
+    ae_members_side_a = initialize_ae_members(subscription, initial_user_input.dict(), 0)
 
     class ModifyIptrunkSideAForm(FormPage):
         class Config:
@@ -42,13 +83,18 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
         side_a_node: str = ReadOnlyField(subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_fqdn)
         side_a_ae_iface: str = ReadOnlyField(subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_iface)
         side_a_ae_geant_a_sid: str = subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_geant_a_sid
-        side_a_ae_members: AeMembersListA = subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_members
+        side_a_ae_members: ae_members_side_a = (  # type: ignore[valid-type]
+            subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_members
+            if initial_user_input.iptrunk_speed == subscription.iptrunk.iptrunk_speed
+            else []
+        )
 
-    user_input_side_a = yield ModifyIptrunkSideAForm
+        @validator("side_a_ae_members", allow_reuse=True)
+        def validate_iptrunk_unique_interface_side_a(cls, side_a_ae_members: list[LAGMember]) -> list[LAGMember]:
+            return validate_iptrunk_unique_interface(side_a_ae_members)
 
-    class AeMembersListB(UniqueConstrainedList[LAGMember]):
-        min_items = len(user_input_side_a.side_a_ae_members)
-        max_items = len(user_input_side_a.side_a_ae_members)
+    user_input_side_a = yield ModifyIptrunkSideAForm
+    ae_members_side_b = initialize_ae_members(subscription, initial_user_input.dict(), 1)
 
     class ModifyIptrunkSideBForm(FormPage):
         class Config:
@@ -57,7 +103,15 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
         side_b_node: str = ReadOnlyField(subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_fqdn)
         side_b_ae_iface: str = ReadOnlyField(subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_iface)
         side_b_ae_geant_a_sid: str = subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_geant_a_sid
-        side_b_ae_members: AeMembersListB = subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_members
+        side_b_ae_members: ae_members_side_b = (  # type: ignore[valid-type]
+            subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_members
+            if initial_user_input.iptrunk_speed == subscription.iptrunk.iptrunk_speed
+            else []
+        )
+
+        @validator("side_b_ae_members", allow_reuse=True)
+        def validate_iptrunk_unique_interface_side_b(cls, side_b_ae_members: list[LAGMember]) -> list[LAGMember]:
+            return validate_iptrunk_unique_interface(side_b_ae_members)
 
     user_input_side_b = yield ModifyIptrunkSideBForm
 
@@ -77,6 +131,20 @@ def modify_iptrunk_subscription(
     side_b_ae_geant_a_sid: str,
     side_b_ae_members: list[dict],
 ) -> State:
+    # Prepare the list of removed AE members
+    previous_ae_members = {}
+    removed_ae_members = {}
+    for side_index in range(2):
+        previous_ae_members[side_index] = [
+            {"interface_name": member.interface_name, "interface_description": member.interface_description}
+            for member in subscription.iptrunk.iptrunk_sides[side_index].iptrunk_side_ae_members
+        ]
+    for side_index in range(2):
+        previous_members = previous_ae_members[side_index]
+        current_members = side_a_ae_members if side_index == 0 else side_b_ae_members
+        removed_ae_members[side_index] = [
+            ae_member for ae_member in previous_members if ae_member not in current_members
+        ]
     subscription.iptrunk.geant_s_sid = geant_s_sid
     subscription.iptrunk.iptrunk_description = iptrunk_description
     subscription.iptrunk.iptrunk_type = iptrunk_type
@@ -101,12 +169,20 @@ def modify_iptrunk_subscription(
 
     subscription.description = f"IP trunk, geant_s_sid:{geant_s_sid}"
 
-    return {"subscription": subscription}
+    return {
+        "subscription": subscription,
+        "removed_ae_members": removed_ae_members,
+        "previous_ae_members": previous_ae_members,
+    }
 
 
 @step("Provision IP trunk interface [DRY RUN]")
-def provision_ip_trunk_iface_dry(subscription: Iptrunk, process_id: UUIDstr, tt_number: str) -> State:
-    provisioning_proxy.provision_ip_trunk(subscription, process_id, tt_number, "trunk_interface")
+def provision_ip_trunk_iface_dry(
+    subscription: Iptrunk, process_id: UUIDstr, tt_number: str, removed_ae_members: List[str]
+) -> State:
+    provisioning_proxy.provision_ip_trunk(
+        subscription, process_id, tt_number, "trunk_interface", True, removed_ae_members
+    )
 
     return {
         "subscription": subscription,
@@ -115,8 +191,12 @@ def provision_ip_trunk_iface_dry(subscription: Iptrunk, process_id: UUIDstr, tt_
 
 
 @step("Provision IP trunk interface [FOR REAL]")
-def provision_ip_trunk_iface_real(subscription: Iptrunk, process_id: UUIDstr, tt_number: str) -> State:
-    provisioning_proxy.provision_ip_trunk(subscription, process_id, tt_number, "trunk_interface", False)
+def provision_ip_trunk_iface_real(
+    subscription: Iptrunk, process_id: UUIDstr, tt_number: str, removed_ae_members: List[str]
+) -> State:
+    provisioning_proxy.provision_ip_trunk(
+        subscription, process_id, tt_number, "trunk_interface", False, removed_ae_members
+    )
 
     return {
         "subscription": subscription,
@@ -124,6 +204,69 @@ def provision_ip_trunk_iface_real(subscription: Iptrunk, process_id: UUIDstr, tt
     }
 
 
+@step("Update interfaces in Netbox. Reserving interfaces.")
+def update_interfaces_in_netbox(subscription: Iptrunk, removed_ae_members: dict, previous_ae_members: dict) -> State:
+    nbclient = NetboxClient()
+    for side in range(0, 2):
+        if subscription.iptrunk.iptrunk_sides[side].iptrunk_side_node.router_vendor == RouterVendor.NOKIA:
+            lag_interface = subscription.iptrunk.iptrunk_sides[side].iptrunk_side_ae_iface
+            router_name = subscription.iptrunk.iptrunk_sides[side].iptrunk_side_node.router_fqdn
+            # Free removed interfaces
+            for member in removed_ae_members[str(side)]:
+                nbclient.free_interface(router_name, member["interface_name"])
+            # Attach physical interfaces to LAG
+            # Update interface description to subscription ID
+            # Reserve interfaces
+            for interface in subscription.iptrunk.iptrunk_sides[side].iptrunk_side_ae_members:
+                if any(
+                    ae_member.get("interface_name") == interface.interface_name
+                    for ae_member in previous_ae_members[str(side)]
+                ):
+                    continue
+                nbclient.attach_interface_to_lag(
+                    device_name=subscription.iptrunk.iptrunk_sides[side].iptrunk_side_node.router_fqdn,
+                    lag_name=lag_interface,
+                    iface_name=interface.interface_name,
+                    description=str(subscription.subscription_id),
+                )
+                nbclient.reserve_interface(
+                    device_name=subscription.iptrunk.iptrunk_sides[side].iptrunk_side_node.router_fqdn,
+                    iface_name=interface.interface_name,
+                )
+    return {
+        "subscription": subscription,
+    }
+
+
+@step("Allocate interfaces in Netbox")
+def allocate_interfaces_in_netbox(subscription: Iptrunk, previous_ae_members: dict) -> State:
+    """Allocate the LAG interfaces in NetBox.
+
+    attach the lag interfaces to the physical interfaces detach old ones from the LAG.
+    """
+
+    for side in range(0, 2):
+        nbclient = NetboxClient()
+        if subscription.iptrunk.iptrunk_sides[side].iptrunk_side_node.router_vendor == RouterVendor.NOKIA:
+            for interface in subscription.iptrunk.iptrunk_sides[side].iptrunk_side_ae_members:
+                if any(
+                    ae_member.get("interface_name") == interface.interface_name
+                    for ae_member in previous_ae_members[str(side)]
+                ):
+                    continue
+                nbclient.allocate_interface(
+                    device_name=subscription.iptrunk.iptrunk_sides[side].iptrunk_side_node.router_fqdn,
+                    iface_name=interface.interface_name,
+                )
+                # detach the old interfaces from lag
+                nbclient.detach_interfaces_from_lag(
+                    device_name=subscription.iptrunk.iptrunk_sides[side].iptrunk_side_node.router_fqdn,
+                    lag_name=subscription.iptrunk.iptrunk_sides[side].iptrunk_side_ae_iface,
+                )
+
+    return {"subscription": subscription}
+
+
 @workflow(
     "Modify IP Trunk interface",
     initial_input_form=wrap_modify_initial_input_form(initial_input_form_generator),
@@ -135,8 +278,10 @@ def modify_trunk_interface() -> StepList:
         >> store_process_subscription(Target.MODIFY)
         >> unsync
         >> modify_iptrunk_subscription
+        >> update_interfaces_in_netbox
         >> pp_interaction(provision_ip_trunk_iface_dry, 3)
         >> pp_interaction(provision_ip_trunk_iface_real, 3)
+        >> allocate_interfaces_in_netbox
         >> resync
         >> done
     )