ADR: Ship new admin-api + admin-ui together — do not retrofit CodeIgniter
- Status: Accepted (recommendation from Claude, confirmed by Jeffrey)
- Date: 2026-04-23
- Decider: Jeffrey Lambert
- Project: Admin Dashboard Cloudflare Migration
Context
Section titled “Context”Jeffrey asked whether to (a) ship the new admin-api and admin-ui together, or (b) ship the admin-api first and point the existing CodeIgniter admin at it during a transition period. Option (b) would avoid a big-bang UI cutover but requires heavy modification of the CodeIgniter monolith.
Decision
Section titled “Decision”Ship admin-api and admin-ui together as a parallel deployment, run alongside the legacy CodeIgniter admin, migrate operators cohort-by-cohort, then decommission CodeIgniter. Do not retrofit the CodeIgniter app to consume the new API.
Why not retrofit
Section titled “Why not retrofit”A retrofit of the CodeIgniter app to call the new admin-api would:
- Require rewriting the data-access layer in PHP (essentially a rewrite inside a soon-to-be-retired app).
- Double the integration surface — both PHP and TypeScript/Hono consumers of the API at once.
- Create regression risk in a system that’s currently working, for no lasting value.
- Not deliver the brand/UI refresh (the other half of the project’s value).
- End with the CodeIgniter app retired anyway.
The retrofit path’s only benefit is avoiding a coordinated UI cutover. Cohort-based migration across the two running admins (old + new) solves the same problem more cheaply.
Deployment topology during transition
Section titled “Deployment topology during transition” ┌──────────────────────────────────────────┐ │ Cloudflare Access (shared auth edge) │ └───────┬──────────────────────┬───────────┘ │ │ ▼ ▼ ┌────────────────────┐ ┌────────────────────┐ │ admin.legacy.* │ │ admin.adventive.* │ │ (CodeIgniter, old) │ │ (Pages SPA, new) │ └─────────┬──────────┘ └──────────┬─────────┘ │ │ ▼ ▼ ┌────────────────────┐ ┌────────────────────┐ │ CodeIgniter DAL │ │ admin-api Worker │ └─────────┬──────────┘ └──────────┬─────────┘ │ │ └──────────┬─────────────┘ ▼ ┌─────────────────────┐ │ Shared billing / │ │ customer DB │ └─────────────────────┘Both admins read/write the same database during the transition. Cohort-by-cohort, operators migrate from the legacy URL to the new one. When all operator workflows have parity coverage in the new admin, the legacy admin is frozen (read-only), then decommissioned.
Feature-parity gate
Section titled “Feature-parity gate”The new admin does not have to reach 100% parity before first operators move. Each operator workflow gets a parity checkbox:
- Customer lookup ✓ → migrate customer-service operators
- Service-level change ✓ → migrate account managers
- Billing inquiry view ✓ → migrate billing-ops operators (but see: Stripe Billing Transition will reshape this surface)
- Report X ✓ → migrate last users
Per-cohort migration also de-risks the brand/UI changes — the new admin gets real-world feedback before everyone is on it.
Consequences
Section titled “Consequences”Positive:
- Clean separation: legacy PHP is never touched again, only replaced.
- Brand/UI refresh ships in the same cutover as the architecture change.
- Rollback is trivial — operators just go back to the legacy URL until the cohort has issues resolved.
- No wasted engineering on a soon-to-be-retired codebase.
Negative / to-mitigate:
- Two admins running simultaneously for a transition window → operator confusion risk (mitigate with clear rollout comms and per-cohort URLs).
- Both admins writing to the same DB → schema changes during transition must be backward-compatible with CodeIgniter (or avoided entirely).
- The transition window has to be bounded — define a decommission date up front, not “when we’re done.”
Follow-ups
Section titled “Follow-ups”- Inventory operator workflows in the legacy admin to build the parity checklist (Claude Code work, once the admin repo is analyzed).
- Define cohort migration order + success criteria per cohort.
- Set a decommission date for the CodeIgniter admin (proposal: 60 days after final cohort migration).
- Decide on DB schema-freeze policy during transition.