diff --git a/resource_management/db/model.py b/resource_management/db/model.py
index 4203d874debb734dc58298affb2d93046354c59e..b8e3c54bd5456e1182a2cbf66ada2db37036fdd0 100644
--- a/resource_management/db/model.py
+++ b/resource_management/db/model.py
@@ -5,10 +5,11 @@ Resources Database
 This database holds information about router port resources
 
 """
+import enum
 import logging
 from typing import Any
 
-from sqlalchemy import Column, ForeignKey, Integer, String
+import sqlalchemy as sa
 from sqlalchemy.ext.declarative import declarative_base
 from sqlalchemy.orm import relationship
 
@@ -18,10 +19,16 @@ logger = logging.getLogger(__name__)
 base_schema: Any = declarative_base()
 
 
+class AvalabilityStates(enum.Enum):
+    AVAILABLE = enum.auto()
+    USED = enum.auto()
+    RESERVED = enum.auto()
+
+
 class Router(base_schema):
     __tablename__ = 'routers'
-    id = Column('id', Integer, primary_key=True)
-    fqdn = Column('fqdn', String, nullable=False)
+    id = sa.Column('id', sa.Integer, primary_key=True)
+    fqdn = sa.Column('fqdn', sa.String, nullable=False)
 
     physical = relationship(
         "PhysicalInterface",
@@ -36,13 +43,18 @@ class Router(base_schema):
 
 class LAG(base_schema):
     __tablename__ = 'lags'
-    id = Column('id', Integer, primary_key=True)
-    name = Column('name', String, nullable=False)
+    id = sa.Column('id', sa.Integer, primary_key=True)
+    name = sa.Column('name', sa.String, nullable=False)
+
+    availability = sa.Column(
+        'availability',
+        sa.Enum(*[a.name for a in AvalabilityStates]),
+        nullable=False)
 
-    router_id = Column(
+    router_id = sa.Column(
         'router_id',
-        Integer,
-        ForeignKey('routers.id'),
+        sa.Integer,
+        sa.ForeignKey('routers.id'),
         nullable=False)
     router = relationship('Router', back_populates='lags')
 
@@ -54,20 +66,25 @@ class LAG(base_schema):
 
 class PhysicalInterface(base_schema):
     __tablename__ = 'physical_interfaces'
-    id = Column('id', Integer, primary_key=True)
-    name = Column('name', String, nullable=False)
+    id = sa.Column('id', sa.Integer, primary_key=True)
+    name = sa.Column('name', sa.String, nullable=False)
+
+    availability = sa.Column(
+        'availability',
+        sa.Enum(*[a.name for a in AvalabilityStates]),
+        nullable=False)
 
-    router_id = Column(
+    router_id = sa.Column(
         'router_id',
-        Integer,
-        ForeignKey('routers.id'),
+        sa.Integer,
+        sa.ForeignKey('routers.id'),
         nullable=False)
     router = relationship('Router', back_populates='physical')
 
-    lag_id = Column(
+    lag_id = sa.Column(
         'lag_id',
-        Integer,
-        ForeignKey('lags.id'),
+        sa.Integer,
+        sa.ForeignKey('lags.id'),
         nullable=True)
     lag = relationship('LAG', back_populates='physical')
 
@@ -79,11 +96,11 @@ class PhysicalInterface(base_schema):
 
 class LogicalInterface(base_schema):
     __tablename__ = 'logical_interfaces'
-    id = Column('id', Integer, primary_key=True)
-    name = Column('name', String, nullable=False)
-    physical_id = Column(
+    id = sa.Column('id', sa.Integer, primary_key=True)
+    name = sa.Column('name', sa.String, nullable=False)
+    physical_id = sa.Column(
         'physical_id',
-        Integer,
-        ForeignKey('physical_interfaces.id'),
+        sa.Integer,
+        sa.ForeignKey('physical_interfaces.id'),
         nullable=False)
     physical = relationship('PhysicalInterface', back_populates='logical')
diff --git a/resource_management/router_interfaces.py b/resource_management/router_interfaces.py
index d0cbc8811520ea0083b8c91e3b4c4bd40f7ba2a0..5ef8d6c16ca43c67a92d721f91faaa55bef70347 100644
--- a/resource_management/router_interfaces.py
+++ b/resource_management/router_interfaces.py
@@ -6,12 +6,10 @@ from resource_management.db import model
 logger = logging.getLogger(__name__)
 
 
-def load_router_interfaces(fqdn: str):
+def load_new_router_interfaces(fqdn: str):
     """
     load all interface info from the router and
     update the db with the current information
-
-    TODO: merge, not just create new
     """
 
     params = config.load()
@@ -25,11 +23,19 @@ def load_router_interfaces(fqdn: str):
         physical = juniper.load_installed_ethernet_ports(dev)
         logical = juniper.load_logical_interfaces(dev)
 
-    def _find_lag_name(interface_name):
-        for name, interfaces in aggregates.items():
-            if interface_name in interfaces:
-                return name
-        return None
+    _inverted_aggregate_map = {}
+    for lag_name, physical_interfaces in aggregates.items():
+        for pn in physical_interfaces:
+            _inverted_aggregate_map[pn] = lag_name
+
+    def _interface_availability(ifc_name):
+        if physical[ifc_name]['oper']:
+            return model.AvalabilityStates.USED.name
+        if ifc_name in _inverted_aggregate_map:
+            return model.AvalabilityStates.USED.name
+        if ifc_name in logical:
+            return model.AvalabilityStates.USED.name
+        return model.AvalabilityStates.AVAILABLE.name
 
     with db.session_scope() as session:
 
@@ -38,13 +44,15 @@ def load_router_interfaces(fqdn: str):
 
         # add all the lag records
         # keep a map for referencing below when adding physical interfaces
-        agg_records = {}
+        lag_records = {}
         for a in aggregates.keys():
             record = model.LAG(
                 name=a,
+                # if present, then used
+                availability=model.AvalabilityStates.USED.name,
                 router=router_record)
             session.add(record)
-            agg_records[a] = record
+            lag_records[a] = record
 
         # add all the physical interface records
         # keep a map for referencing below when adding logical interfaces
@@ -52,10 +60,11 @@ def load_router_interfaces(fqdn: str):
         for physical_name, _ in physical.items():
             record = model.PhysicalInterface(
                 name=physical_name,
+                availability=_interface_availability(physical_name),
                 router=router_record)
-            lag_name = _find_lag_name(physical_name)
+            lag_name = _inverted_aggregate_map.get(physical_name, None)
             if lag_name:
-                record.lag = agg_records[lag_name]
+                record.lag = lag_records[lag_name]
             physical_records[physical_name] = record
             session.add(record)
 
diff --git a/resource_management/routes/interfaces.py b/resource_management/routes/interfaces.py
index 8a480c3b49c2d63a5bd8b618281d4efde9999492..51a26a912e6c431395a8ceea0afd9463bffe95f1 100644
--- a/resource_management/routes/interfaces.py
+++ b/resource_management/routes/interfaces.py
@@ -1,6 +1,8 @@
 from fastapi import APIRouter, HTTPException
 import pydantic
 
+import sqlalchemy as sa
+
 from resource_management import db
 from resource_management import config
 from resource_management.db import model
@@ -8,6 +10,8 @@ from resource_management import router_interfaces
 
 router = APIRouter()
 
+FIRST_LAG_INDEX = 0
+
 
 class InterfaceCounts(pydantic.BaseModel):
     total: int
@@ -31,13 +35,21 @@ class NextPhysicalInterface(pydantic.BaseModel):
     name: str
 
 
-@router.post('/import/{fqdn}')
-async def load_router_interfaces(fqdn: str) -> InterfacesSummary:
+@router.post('/initialize-router/{fqdn}')
+async def load_new_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:
+        num_routers = session.query(sa.func.count(model.Router.fqdn)) \
+            .filter_by(fqdn=fqdn).scalar()
+        if num_routers != 0:
+            raise HTTPException(
+                status_code=400,
+                detail=f'router "{fqdn}" already exists')
+
+    router_interfaces.load_new_router_interfaces(fqdn)
 
     with db.session_scope() as session:
         router = session.query(model.Router).filter_by(fqdn=fqdn).one()
@@ -55,6 +67,13 @@ async def load_router_interfaces(fqdn: str) -> InterfacesSummary:
     }
 
 
+@router.post('/reconcile-router/{fqdn}')
+async def reconcile_current_router_interfaces(fqdn: str):
+    raise HTTPException(
+        status_code=501,
+        detail='not implemented')
+
+
 @router.post('/next-lag/{fqdn}')
 async def reserve_next_lag(fqdn: str) -> NextLAG:
     """
@@ -68,22 +87,29 @@ async def reserve_next_lag(fqdn: str) -> NextLAG:
     db.init_db_model(params['db'])
 
     with db.session_scope() as session:
-        records = session.query(model.LAG.name) \
+        router_record = session.query(model.Router.id) \
+            .filter_by(fqdn=fqdn).one()
+        lag_rows = 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
+        lag_names = set(r[0] for r in lag_rows)
+
+        def _next_lag_name():
+            index = FIRST_LAG_INDEX
+            while True:
+                candidate_name = f'ae{index}'
+                if candidate_name not in lag_names:
+                    new_lag_record = model.LAG(
+                        name=candidate_name,
+                        router_id=router_record[0],
+                        availability=model.AvalabilityStates.RESERVED.name)
+                    session.add(new_lag_record)
+                    return candidate_name
+                index += 1
 
-    return {
-        'fqdn': fqdn,
-        'name': _next_lag_name()
-    }
+        return {
+            'fqdn': fqdn,
+            'name': _next_lag_name()
+        }
 
 
 @router.post('/next-physical/{fqdn}/{lag_name}')
@@ -104,8 +130,12 @@ async def reserve_physical_bundle_member(
 
         def _find_available_physical():
             for ifc in router.physical:
-                if not ifc.lag:
+                if ifc.availability \
+                        == model.AvalabilityStates.AVAILABLE.name:
+                    ifc.availability = model.AvalabilityStates.RESERVED.name
+                    session.add(ifc)
                     return ifc.name
+
             raise HTTPException(
                 status_code=404,
                 detail=f'no available physical ports for "{lag_name}"')
diff --git a/test/test_interfaces_routes.py b/test/test_interfaces_routes.py
index 6ffc443aae121e94605d38562f41f650d7fc8a76..ed0158d337778a411dcae2570f76c3919f82e9a3 100644
--- a/test/test_interfaces_routes.py
+++ b/test/test_interfaces_routes.py
@@ -3,6 +3,10 @@ import jsonschema
 from resource_management.routes.default import Version
 from resource_management.routes import interfaces
 from resource_management import router_interfaces
+from resource_management import db
+from resource_management.db import model
+
+import pytest
 
 
 def test_bad_method(client):
@@ -18,24 +22,57 @@ def test_version_request(client):
 
 def test_update_router_interfaces(
         client, resources_db, mocked_router, router_name):
-    rv = client.post(f'/api/interfaces/import/{router_name}')
+    rv = client.post(f'/api/interfaces/initialize-router/{router_name}')
     assert rv.status_code == 200
     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)
+    router_interfaces.load_new_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())
+    response = rv.json()
+    jsonschema.validate(response, interfaces.NextLAG.schema())
+
+    with db.session_scope() as session:
+        row = session.query(model.LAG). \
+            filter_by(name=response['name']). \
+            join(model.Router). \
+            filter_by(fqdn=router_name).one()
+        assert row.availability == model.AvalabilityStates.RESERVED.name
 
 
 def test_next_physical(client, resources_db, mocked_router, router_name):
 
-    router_interfaces.load_router_interfaces(router_name)
+    if '.lab.' in router_name:
+        pytest.skip('not all lab routers have available ports')
+    if router_name.startswith('rt'):
+        pytest.skip('not all rt* have available ports')
+
+    router_interfaces.load_new_router_interfaces(router_name)
+
+    with db.session_scope() as session:
+        rows = session.query(model.LAG.name). \
+            join(model.Router). \
+            filter_by(fqdn=router_name).all()
+        lag_name = rows[0][0]
 
-    rv = client.post(f'/api/interfaces/next-physical/{router_name}/ae123123')
+    rv = client.post(f'/api/interfaces/next-physical/{router_name}/{lag_name}')
     assert rv.status_code == 200
-    jsonschema.validate(rv.json(), interfaces.NextPhysicalInterface.schema())
+
+    response = rv.json()
+    jsonschema.validate(response, interfaces.NextPhysicalInterface.schema())
+
+    assert response['fqdn'] == router_name
+    assert response['lag'] == lag_name
+
+    with db.session_scope() as session:
+        ifc_row = session.query(model.PhysicalInterface). \
+            filter_by(name=response['name']). \
+            join(model.Router). \
+            filter_by(fqdn=router_name). \
+            join(model.LAG). \
+            filter_by(name=lag_name).one()
+        assert ifc_row.availability == model.AvalabilityStates.RESERVED.name
diff --git a/test/test_parse_router.py b/test/test_parse_router.py
index e6723d5f454de67d3a1b29c8d25266b17725ae41..ffe6157f9a4a80bba0cfb5a22b133a62a0d61aa9 100644
--- a/test/test_parse_router.py
+++ b/test/test_parse_router.py
@@ -83,7 +83,7 @@ def test_load_interfaces(
     new design for this app: no chassis info for now
     """
 
-    router_interfaces.load_router_interfaces(router_name)
+    router_interfaces.load_new_router_interfaces(router_name)
 
     with db.session_scope() as session:
         router = session.query(model.Router).filter_by(fqdn=router_name).one()