Every resource was a snowflake
Two RDS instances doing the same job, configured slightly differently, because they were built on different days by different people.
Years of VPCs, RDS instances, S3 buckets and IAM roles, built by hand as the company scaled. Rebuilding from scratch was never on the table — the estate had to become reviewable while it kept running.
← Some of our past work · anonymised prior delivery, no client named
Stack
Rough timeline
| Phase | Typical duration |
|---|---|
| Discovery and inventory | 1–2 weeks |
| Import and modularisation, phased by service | 4–8 weeks |
| Pipeline and handover | 1–2 weeks |
Every resource had been built by hand, at a different time, by whoever was free that day. Individually reasonable. Collectively, nothing matched.
Two RDS instances doing the same job, configured slightly differently, because they were built on different days by different people.
The only acceptable migration path left production untouched until the code was proven to match it exactly.
Even a rough resource count required asking three people, and still came back short.
The discovery pass had to establish ground truth from the account itself, because nothing else could be trusted as a full record.
Security group rules, RDS parameter groups and S3 lifecycle settings that had never been written down anywhere.
A security group referenced by name had been manually edited since anyone last documented it — the import had to trust the account, not anyone’s memory of it.
A few RDS instances carried a default parameter group tied to console defaults, which needed a small manual correction before the plan came out clean.
The estate did not move. What changed was whether a resource could be read, reviewed and safely changed by someone other than whoever built it.
| Change | What it did |
|---|---|
| Discovered the live estate | Walked every account, service by service, against the AWS CLI and the console to build a real resource inventory rather than trust an existing document. |
| Imported into Terraform state | Used terraform import and import blocks to bring existing VPCs, RDS instances, S3 buckets and IAM roles under management without recreating them. |
| Reusable modules extracted | Once several resources of the same kind existed side by side, the common shape became a module, and the individual resources were refactored onto it. |
| Zero-diff plans as the bar | Each imported resource had to produce an empty terraform plan before it counted as done — a plan proposing a change nobody asked for is the first sign an import is wrong. |
| Future changes behind pull requests | From that point, changing an imported resource is a diff someone can read, not a console session someone has to trust. |
The estate is version-controlled and reviewable, and nothing was rebuilt to get there — which mattered most to a company that could not take downtime to modernise its own tooling.
A security group rule is now a line in a pull request, not a click three people ago that nobody remembers making. Where the client wanted a platform function of its own rather than an ongoing dependency on us, InfraEdge helped assess the role and vet the infrastructure engineer who took the modules on from there.
Twenty minutes, no charge. We work out what would actually help — which is sometimes us and sometimes not. Nothing is priced on the call; if there is work worth doing, a written scope and a price reach you within 24 hours.