DEV Community

Puneet Khandelwal
Puneet Khandelwal

Posted on

Rewriting City Hall's Code Base

Municipal form software rarely breaks with a dramatic crash. It rots in plain sight through undocumented patch files and globals scattered across twenty directories. Last month, our civic engineering team inherited one such artifact. It was a residency permit monolith written in ancient procedural PHP, patched by a rotating cast of contractors for two decades. Every submission was a roll of the dice. Input sanitization was treated as a suggestion rather than a security mandate.

We didn't rewrite it to chase trendy syntax. We rewrote it because public infrastructure demands predictability. When a resident applies for a building permit or registers a business, they interact with the state digitally. If that form fails silently or leaks headers, trust in local governance erodes alongside software reliability. We needed explicit types, guarded state transitions, and failure modes loud enough to catch before data hit the persistence layer.

The migration centered on moving core business logic into a TypeScript backend service running on Node. We started by drawing a strict boundary around domain models. In the old PHP codebase, a submission array contained virtually any key depending on which client-side script fired. By enforcing rigid interfaces using strict type definitions, we eliminated an entire class of input validation bugs on day one. If a payload lacks a verified municipal tax identifier, the compiler rejects it before it sniffs a database connection.

Type safety alone doesn't guarantee architectural hygiene. We had to rethink legacy database schemas resembling archaeological layers of forgotten features. Rather than mapping every historical quirk into new models, we built an anti-corruption layer. This translation boundary intercepted incoming requests, normalized the data into clean internal types, and only then handed the payload to domain handlers. It kept our core codebase pure and isolated us from database schema drift.

For developers in civic tech, refactoring is rarely about clever algorithms. It's debt reduction for public goods. When you replace fragile scripts with well-tested, typed backend services, you lower the barrier for the next engineer who maintains the system. Code that is easy to reason about stays secure under pressure. We need public sector software built with the structural integrity we expect from bridges and transit lines.

As we deploy these updated endpoints, error logs drop. Citizens submit forms and receive deterministic confirmations instead of blank screen timeouts. The real win is internal. We now have a foundation that lets municipal digital services evolve safely, keeping pace with policy changes without risking catastrophic production regressions.

Top comments (0)