diff --git a/resource_management/router_interfaces.py b/resource_management/router_interfaces.py
index 77a08c7eb94e5fa9fd787cb74855becc47f52d81..d0cbc8811520ea0083b8c91e3b4c4bd40f7ba2a0 100644
--- a/resource_management/router_interfaces.py
+++ b/resource_management/router_interfaces.py
@@ -15,7 +15,6 @@ def load_router_interfaces(fqdn: str):
     """
 
     params = config.load()
-    db.init_db_model(params['db'])
 
     with juniper.router(
             hostname=fqdn,
diff --git a/resource_management/routes/interfaces.py b/resource_management/routes/interfaces.py
index 771bc2a0047238e701e8a8cad9a96c0bf75e20c6..ca15f20d7de0cd47e7f560ce4d632057a477d6ae 100644
--- a/resource_management/routes/interfaces.py
+++ b/resource_management/routes/interfaces.py
@@ -2,6 +2,7 @@ from fastapi import APIRouter, HTTPException
 import pydantic
 
 from resource_management import db
+from resource_management import config
 from resource_management.db import model
 from resource_management import router_interfaces
 
@@ -19,9 +20,23 @@ class InterfacesSummary(pydantic.BaseModel):
     physical: InterfaceCounts
 
 
+class NextLAG(pydantic.BaseModel):
+    fqdn: str
+    name: str
+
+
+class NextPhysicalInterface(pydantic.BaseModel):
+    fqdn: str
+    lag: str
+    name: str
+
+
 @router.post('/import/{fqdn}')
 async def load_router_interfaces(fqdn: str) -> InterfacesSummary:
 
+    params = config.load()
+    db.init_db_model(params['db'])
+
     router_interfaces.load_router_interfaces(fqdn)
 
     with db.session_scope() as session:
@@ -38,3 +53,63 @@ async def load_router_interfaces(fqdn: str) -> InterfacesSummary:
             'available': num_available_physical
         }
     }
+
+@router.post('/next-lag/{fqdn}')
+async def reserve_next_lag(fqdn: str) -> NextLAG:
+    """
+    compute the next available lag name for the given router
+
+    TODO: _next_lag_name is a placeholder for
+        whatever logic turns out to be right
+    """
+
+    params = config.load()
+    db.init_db_model(params['db'])
+
+    with db.session_scope() as session:
+        records = session.query(model.LAG.name) \
+            .join(model.Router).filter_by(fqdn=fqdn).all()
+        names = set(r[0] for r in records)
+
+    def _next_lag_name():
+        index = 1
+        while True:
+            candidate = f'ae{index}'
+            if candidate not in names:
+                return candidate
+            index += 1
+
+    return {
+        'fqdn': fqdn,
+        'name': _next_lag_name()
+    }
+
+
+@router.post('/next-physical/{fqdn}/{lag_name}')
+async def reserve_physical_bundle_member(fqdn: str, lag_name: str) -> NextPhysicalInterface:
+    """
+    compute the next available lag name for the given router
+
+    TODO: _find_available_physical is a placeholder for
+        whatever logic turns out to be right (e.g. speeds, etc)
+    """
+
+    params = config.load()
+    db.init_db_model(params['db'])
+
+    with db.session_scope() as session:
+        router = session.query(model.Router).filter_by(fqdn=fqdn).one()
+
+        def _find_available_physical():
+            for ifc in router.physical:
+                if not ifc.lag:
+                    return ifc.name
+            raise HTTPException(
+                status_code=404,
+                detail=f'no available physical ports for "{lag_name}"')
+
+        return {
+            'fqdn': fqdn,
+            'lag': lag_name,
+            'name': _find_available_physical()
+        }
diff --git a/test/test_interfaces_routes.py b/test/test_interfaces_routes.py
index 09e1f933e8a4632ee47b5672d15cb5a57fb4c92e..4b5ece456010c0c419c3c040815323f6d03cb2af 100644
--- a/test/test_interfaces_routes.py
+++ b/test/test_interfaces_routes.py
@@ -2,6 +2,8 @@ import jsonschema
 
 from resource_management.routes.default import Version
 from resource_management.routes import interfaces
+from resource_management import router_interfaces
+
 
 def test_bad_method(client):
     rv = client.post('/api/version')
@@ -20,3 +22,19 @@ def test_update_router_interfaces(client, resources_db, mocked_router, router_na
     jsonschema.validate(rv.json(), interfaces.InterfacesSummary.schema())
 
 
+def test_next_lag(client, resources_db, mocked_router, router_name):
+
+    router_interfaces.load_router_interfaces(router_name)
+
+    rv = client.post(f'/api/interfaces/next-lag/{router_name}')
+    assert rv.status_code == 200
+    jsonschema.validate(rv.json(), interfaces.NextLAG.schema())
+
+
+def test_next_physical(client, resources_db, mocked_router, router_name):
+
+    router_interfaces.load_router_interfaces(router_name)
+
+    rv = client.post(f'/api/interfaces/next-physical/{router_name}/ae123123')
+    assert rv.status_code == 200
+    jsonschema.validate(rv.json(), interfaces.NextPhysicalInterface.schema())