Anti-Patterns & Pitfalls
Some migrations fail not because the cloud is hard, but because a well-meaning team walked into a trap that looked like a shortcut. This page collects the classic mistakes — each one framed as a snare that Gizmo the Gremlin loves to set — and shows you the safer path around it. Learn the traps once, and you will spot them a mile away for the rest of your career.
Imagine moving your whole house in one single midnight trip, with no list of what you own, no labels on the boxes, and no way to move back if the new place floods. That is basically every migration disaster — and every trap on this page is one of those bad ideas dressed up to look clever.
What is an anti-pattern, anyway?
☺ Like you’re 10: An anti-pattern is a habit that feels smart and saves time today, but quietly causes a big mess later.
A repeatable bad idea, not a one-off slip
An anti-pattern is a common solution to a recurring problem that looks reasonable but reliably makes things worse. It is different from a simple mistake: a mistake is a one-off slip, while an anti-pattern is a repeatable bad idea that teams keep reinventing because it seems logical in the moment. In migration, the danger is that most anti-patterns save effort early (skip the boring planning!) and only bill you later (surprise outage, surprise invoice, surprise rewrite).
Meet Gizmo: impatience with a straight face
Gizmo the Gremlin is the personification of every one of these shortcuts. He is not evil, exactly — he is impatient. Every trap below is something Gizmo would genuinely suggest with a straight face. Timmy the Turtle, slow and careful, is here to defuse each one. Think of this page as the counter-part to best practices: the do-nots that make the do’s make sense.
To keep them straight, the fifteen traps below are sorted into four families by where in the move they bite: planning traps you spring before you touch a server, foundation and architecture traps baked into what you build, execution traps that strike at cutover, and cost and lock-in traps whose bill arrives long after the switch is flipped. Each trap gets the same three-part treatment — the symptom (how you spot it), why it hurts, and the fix — after Gizmo’s tempting pitch for it.
Planning traps — skip the homework, pay at the move
☺ Like you’re 10: These are the corners you cut before moving day — and every later step inherits the mess.
This first family happens before you touch a single server, in the assess-and-plan work that feels optional when a deadline looms. Skip it and everything downstream wobbles. This is exactly the discipline the migration journey front-loads on purpose.
Skipping discovery & dependency mapping
☺ Like you’re 10: You can’t safely move a box when you don’t know what’s inside it or what it’s tied to.
Gizmo’s pitch 👺: “We don’t have time for a full inventory — we know our own systems. Let’s just start moving.”
Symptom: there’s no complete server inventory and no dependency map; people describe the estate from memory, and sentences start with “I think that app talks to… something.”
Why it hurts: you cut over an app and discover it secretly depended on a database you left behind. Hidden links break in production, where they are most expensive to find.
The fix 🐢: do full discovery — inventory every server and map dependencies before grouping into waves. That map is the raw material wave planning is built on.
Migrating the junk (no rationalization)
☺ Like you’re 10: Don’t pack and carry boxes of stuff you were going to throw away anyway.
Gizmo’s pitch 👺: “Move everything as-is — we’ll sort out what we actually need once it’s all up there.”
Symptom: the migration scope is simply “all of it.” Nobody has marked any app to retire or to retain on-prem.
Why it hurts: you spend money and effort moving apps nobody uses. Complexity and cost travel with you to the new home.
The fix 🐢: run portfolio rationalization first — decide the retire and retain candidates before you move anything. See the 7 R’s.
Big-bang everything
☺ Like you’re 10: Moving your whole house in one single midnight trip is how everything breaks at once.
Gizmo’s pitch 👺: “One weekend, one giant cutover, every app at once. Rip the plaster off!”
Symptom: the plan has a single enormous cutover date and no phasing — there is no “Wave 1,” just “the migration.”
Why it hurts: one failure takes down everything at once, with no safe place to stand. Rollback is enormous and rehearsal is impossible.
The fix 🐢: move in small waves (groups of related apps). Prove the process on low-risk apps first, then scale — the whole craft of wave planning.
Boiling the ocean
☺ Like you’re 10: Trying to do everything everywhere this quarter means nothing actually gets finished.
Gizmo’s pitch 👺: “Let’s migrate the entire estate this quarter. Go big or go home.”
Symptom: scope keeps expanding, deadlines keep slipping, and no single workload is ever fully “done” and closed out.
Why it hurts: scope explodes, teams burn out, nothing finishes, momentum dies, and the project gets cancelled.
The fix 🐢: slice into achievable waves with visible wins. Ship something, learn, repeat — small proven progress beats a heroic plan.
Skipping the pilot
☺ Like you’re 10: Do a practice run on something small before you touch the important stuff.
Gizmo’s pitch 👺: “The revenue app is the whole point — let’s migrate that one first and prove the value fast.”
Symptom: the very first thing scheduled to move is a crown-jewel, business-critical system.
Why it hurts: you learn your process is broken on your most important system, in front of your most important users.
The fix 🐢: run a pilot on a small, real-but-low-risk app to shake out the process safely first — the job of Wave 1.
Foundation & architecture traps — building on sand
☺ Like you’re 10: These are about the shape of what you build — a shaky base looks fine until you lean on it.
These traps are baked into what you build the migration on: the account structure, the guardrails, and the shape of the services themselves. They are dangerous precisely because a shaky foundation looks perfectly fine until you try to scale it or audit it. The antidotes live in best practices and provisions.
No landing zone or governance
☺ Like you’re 10: Set up the new house with proper wiring and locks before you carry the furniture in.
Gizmo’s pitch 👺: “We’ll spin up cloud accounts by hand as we need them — governance can catch up later.”
Symptom: accounts and networks are hand-built one at a time; naming, permissions, and network layout differ from account to account.
Why it hurts: inconsistent networks, naming, and permissions create a snowflake mess that’s impossible to audit or scale.
The fix 🐢: build a landing zone — a pre-governed, repeatable cloud foundation — before migrating any workloads onto it.
Security as an afterthought
☺ Like you’re 10: Lock the doors while you build, not after the burglars have already visited.
Gizmo’s pitch 👺: “Get it working first — we’ll lock it all down in phase two.”
Symptom: storage left open “just to test,” broad admin permissions handed out for convenience, secrets pasted straight into code.
Why it hurts: open storage buckets, over-broad permissions, and secrets in code become breaches. Later never comes.
The fix 🐢: bake in identity, encryption, and least-privilege from the start. Security is a design input, not a cleanup task.
The distributed monolith
☺ Like you’re 10: If two “separate” toys must always be played with together, they aren’t really separate.
Gizmo’s pitch 👺: “Chop the old monolith into microservices — instant modern architecture!”
Symptom: your shiny new “microservices” always have to be deployed together, and a change in one forces changes in the others.
Why it hurts: you get all the pain of distributed systems (network calls, versioning) with none of the independence — worse than the monolith.
The fix 🐢: split along real business boundaries. If two services must always deploy together, they are one service, not two.
Premature microservices
☺ Like you’re 10: Don’t build a twenty-room mansion when you only have furniture for one room.
Gizmo’s pitch 👺: “Everything should be a microservice from day one — that’s how the big companies do it.”
Symptom: a small system is carved into many services before anyone understands the domain or has felt any real scaling pressure.
Why it hurts: huge operational overhead for a system that would run fine as one deployable. You optimize a problem you don’t have yet.
The fix 🐢: start with a well-structured monolith or modular design; extract services only where proven pressure actually exists.
Execution & cutover traps — the switch itself goes wrong
☺ Like you’re 10: Careful movers and reckless ones look the same right up until they flip the switch.
Now the move itself. These traps strike during replication and cutover — the exact moment where a careful team and a reckless one are indistinguishable, until the switch is flipped and only one of them has a way back.
No rollback / backout plan
☺ Like you’re 10: Never make a move you can’t undo — always keep a way back to the old place.
Gizmo’s pitch 👺: “The cutover will be fine — why waste time planning for failure?”
Symptom: nobody can answer “what exactly do we do if this goes wrong?”, and there is no explicit go/no-go checkpoint in the runbook.
Why it hurts: when something breaks at 2 a.m., there is no way back. Downtime stretches for hours while you improvise a fix live.
The fix 🐢: every cutover needs a tested backout plan and a clear go/no-go decision point — the non-negotiable of every wave.
Inadequate testing & validation
☺ Like you’re 10: Check the new place actually works before you tell everyone to move in.
Gizmo’s pitch 👺: “It moved without errors — ship it. We’ll find out if it really works in production.”
Symptom: validation is a quick smoke test; nobody ran it under load or compared the data row-for-row against the source.
Why it hurts: performance, data integrity, and edge cases fail in production, where customers are the ones who discover them.
The fix 🐢: test functionally, at load, and validate data before cutover. Compare old vs. new side by side until they match.
Underestimating data gravity & egress
☺ Like you’re 10: A huge pile of data is heavy and expensive to drag around — it doesn’t teleport.
Gizmo’s pitch 👺: “It’s just a database — copy it over the night before, easy.”
Symptom: the plan treats terabytes like a quick file copy — no replication window scheduled, no egress line in the budget.
Why it hurts: huge datasets take days to move and cost real money to pull out (egress fees). The app can’t leave its data behind.
The fix 🐢: plan replication windows, use bulk-transfer options, and budget egress. Respect data migration timing from the start.
Cost & lock-in traps — the bills you can’t see
☺ Like you’re 10: The sneakiest traps don’t bite on moving day — they show up on next month’s bill.
This last family is the sneakiest, because the invoice arrives long after the decision that caused it. You won’t catch these on cutover night — they surface on next month’s bill or next year’s contract renewal, when the cheap fix is already out of reach.
Ignoring cost (no FinOps) → bill shock
☺ Like you’re 10: Someone has to watch the money meter, or the bill quietly grows while nobody’s looking.
Gizmo’s pitch 👺: “Provision generously so nothing’s ever slow — cost is finance’s problem, not ours.”
Symptom: instances sized “to be safe,” test resources left running for weeks, and no single person who owns the monthly number.
Why it hurts: bill shock — over-provisioned instances and forgotten resources balloon the invoice, and nobody owns the number.
The fix 🐢: right-size, set budgets and alerts, and give someone the FinOps job on day one. Model TCO up front.
Lift-and-shift and forget
☺ Like you’re 10: Moving your old habits to a fancy new place, then never using the new features you’re paying for.
Gizmo’s pitch 👺: “Rehost it exactly as-is and call it done — we’re on the cloud now!”
Symptom: months after the move, apps still run on fixed-size VMs with no autoscaling and no managed services, and the modernization ticket has no date on it.
Why it hurts: you pay cloud prices for on-prem habits — idle VMs, no autoscaling, no managed services. The “temporary” state becomes permanent.
The fix 🐢: rehost as a first step, then schedule real modernization. Put a date on it, not a “someday” — see the 7 R’s.
Unmanaged vendor lock-in
☺ Like you’re 10: It’s fine to use a special tool — just know how hard it’d be to switch away later.
Gizmo’s pitch 👺: “Wire straight into every proprietary service — don’t overthink portability.”
Symptom: proprietary services are woven all through the code with no boundaries, and nobody ever asked “how would we leave?”
Why it hurts: switching later becomes prohibitively expensive; you lose all your negotiating leverage with the vendor.
The fix 🐢: lock-in is often a fine trade — just make it a conscious choice. Isolate the proprietary bits behind clear boundaries.
The trap table: fifteen pitfalls at a glance
☺ Like you’re 10: Here is Gizmo’s whole bag of tricks in one place — the sneaky idea, why it bites you, and what to do instead.
Everything above, condensed into one recap you can scan later. Read it slowly. If you only remember one thing from the page, remember that every fix is some form of “slow down and do the boring step first.”
| 👺 The Trap | Why it hurts | 🐢 The Fix |
|---|---|---|
| Big-bang everything — move all apps in one weekend, no phasing. | One failure takes down everything at once, with no safe place to stand. Rollback is enormous and rehearsal is impossible. | Move in small waves (groups of related apps). Prove the process on low-risk apps first, then scale. |
| Lift-and-shift and forget — rehost, then never modernize. | You pay cloud prices for on-prem habits: idle VMs, no autoscaling, no managed services. The “temporary” state becomes permanent. | Rehost as a first step, then schedule real modernization. Put a date on it, not a “someday.” |
| Migrate the junk — no rationalization or retirement. | You spend money and effort moving apps nobody uses. Complexity and cost travel with you. | Run portfolio rationalization first: retire and retain candidates before you move anything. See the 7 R’s. |
| Skip discovery — no inventory or dependency map. | You cut over an app and discover it secretly depended on a database you left behind. Hidden links break in production. | Do full discovery: inventory every server and map dependencies before grouping into waves. |
| Ignore cost / no FinOps — provision generously, watch the bill later. | Bill shock: over-provisioned instances and forgotten resources balloon the invoice. Nobody owns the number. | Right-size, set budgets and alerts, and give someone the FinOps job on day one. Model TCO up front. |
| Distributed monolith — split into microservices that are still tightly coupled. | You get all the pain of distributed systems (network calls, versioning) with none of the independence. Worse than the monolith. | Split along real business boundaries. If two services must always deploy together, they are one service. |
| Premature microservices — chop everything up before you understand the domain. | Huge operational overhead for a system that would run fine as one deployable. You optimize a problem you don’t have yet. | Start with a well-structured monolith or modular design; extract services only where proven pressure exists. |
| No rollback plan — assume the cutover just works. | When something breaks at 2 a.m., there is no way back. Downtime stretches for hours while you improvise. | Every cutover needs a tested backout plan and a clear go/no-go decision point. |
| Inadequate testing — validate lightly, ship on faith. | Performance, data integrity, and edge cases fail in production where customers see them. | Test functionally, at load, and validate data before cutover. Compare old vs. new side by side. |
| Underestimating data gravity & egress — treat terabytes like a quick copy. | Huge datasets take days to move and cost real money to pull out (egress fees). The app can’t leave its data behind. | Plan replication windows, use bulk-transfer options, and budget egress. Respect data migration timing. |
| Security as an afterthought — “we’ll lock it down later.” | Open storage buckets, over-broad permissions, and secrets in code become breaches. Later never comes. | Bake in identity, encryption, and least-privilege from the start. Security is a design input, not a cleanup task. |
| No landing zone / governance — hand-build accounts as you go. | Inconsistent networks, naming, and permissions create a snowflake mess that’s impossible to audit or scale. | Build a landing zone — a pre-governed, repeatable cloud foundation — before migrating workloads. |
| Skip the pilot — go straight to the crown-jewel app. | You learn your process is broken on your most important system, in front of your most important users. | Run a pilot on a small, real-but-low-risk app to shake out the process safely. |
| Boiling the ocean — everything, everywhere, this quarter. | Scope explodes, teams burn out, nothing finishes, momentum dies and the project gets cancelled. | Slice into achievable waves with visible wins. Ship something, learn, repeat. |
| Unmanaged vendor lock-in — wire deeply into proprietary services with no awareness. | Switching later becomes prohibitively expensive; you lose all negotiating leverage. | Lock-in is often a fine trade — just make it a conscious choice. Isolate proprietary bits behind clear boundaries. |
Almost every anti-pattern is a “skip the boring step” trap. Discovery, planning, testing, rollback, cost modeling, and governance all feel like delays — but they are the exact steps that turn a scary big move into a series of calm small ones.
Why the traps are so tempting
☺ Like you’re 10: The bad shortcuts feel good right now, and the price only shows up later — that is exactly why they fool smart people.
The reward is now; the bill is later
Notice a pattern across the whole table: the reward for each anti-pattern is immediate (less work today), and the punishment is delayed (an outage, an invoice, a rewrite next year). Humans are wired to grab immediate rewards, which is why even experienced teams fall for Gizmo’s ideas.
Traps hunt in packs
The traps also tend to cluster: skip discovery and you will almost certainly migrate junk, miss dependencies, and have no idea how to plan waves — one shortcut pulls three others along with it. That is why fixing the first boring step often disarms several traps at once.
The most expensive traps are invisible
The two most expensive traps in practice are usually the invisible ones: ignoring cost (because the bill arrives a month after the damage is done) and underestimating data gravity (because a spreadsheet says “copy the database” as if it were a single small file). Both hide their true size until it is too late to plan around them.
Spotting a trap before you fall in
☺ Like you’re 10: If a plan skips the boring safety step to “save time,” a trap is probably hiding inside it.
You do not need to memorize all fifteen traps to stay safe. Instead, learn the warning phrases that signal one is nearby. When you hear any of these in a planning meeting, slow down and ask a Timmy question:
- “Let’s just move everything at once” → big-bang. Ask: what’s our rollback if wave one fails?
- “We’ll modernize it later” → lift-and-forget. Ask: later means what date, owned by whom?
- “We don’t have time for discovery” → skipped inventory. Ask: what does this app depend on that we haven’t mapped?
- “Cost is finance’s problem” → no FinOps. Ask: who owns the monthly bill and the budget alert?
- “Security review can wait for phase two” → afterthought. Ask: who can read this data on day one?
These questions are not obstacles — they are the cheapest insurance you will ever buy. Each one costs a minute in a meeting and can save a weekend of firefighting. This is exactly the mindset the migration journey is built to enforce, stage by stage.
Gizmo: Team! Big idea: move all of Fort Rusty to Cloudville this Saturday night. One truck, one trip, no list. Efficient!
Timmy: One trip, one crash. If anything breaks, everything breaks — and we can’t move back. We go in waves, low-risk apps first.
Gizmo: Fine, fine. But we skip the boring counting. And we’ll “clean up” the old junk apps after we move them.
Nutty: If we don’t count first, we’ll haul three apps nobody’s opened since 2019 — and miss the database they secretly lean on.
Gizmo: Okay but security we bolt on later, right? And who cares about the bill?
Timmy: “Later” is how buckets leak and invoices explode. Security and cost are design inputs, not clean-up chores. Nice try, Gizmo.
The most dangerous anti-pattern is the one wearing a deadline. “There’s no time to plan” is never a reason to skip discovery, testing, or a rollback plan — it is the exact reason you need them. Pressure is when traps do their best work.
Pick any real app you use (a game, a school portal, a shop). On paper, list three things it secretly depends on — a login service, a database, a payment provider. Now imagine moving only the app and leaving those behind. Which one breaks it first? You just did dependency mapping, the antidote to the “skip discovery” trap. For the correct discovery-first order, revisit provisions and best practices.
From traps to a safe path
☺ Like you’re 10: Flip every trap around and you get a checklist of good habits — that is your safety net.
Here is the reassuring part: you do not have to invent good migration habits. They already exist, and every one of them is simply the mirror image of a trap on this page. Boil the ocean → slice into waves. Skip discovery → inventory first. No rollback → rehearse the backout. Ignore cost → assign FinOps. Security later → security by design. When you turn all fifteen fixes into a running checklist, you have essentially rebuilt the discipline described in best practices and enforced by the migration journey.
So the goal of studying anti-patterns is not to feel scared — it is to feel prepared. Every trap you can name in advance is a trap that can no longer surprise you. That is the whole point: Gizmo only wins when nobody in the room knows his tricks.
1. Why is “big-bang everything” riskier than moving in waves? 2. What does “lift-and-shift and forget” cost you over time? 3. Name the trap where microservices are split but still tightly coupled — and why it’s worse than a monolith. 4. What single habit is the fix hiding behind almost every anti-pattern?
Check your answers
- In a big-bang move, one failure takes down everything at once and rollback is enormous and un-rehearsable; waves isolate failures to a small group and let you prove the process on low-risk apps first.
- You keep paying cloud prices for on-prem habits — idle, over-provisioned VMs, no autoscaling, no managed services — because the “temporary” rehosted state quietly becomes permanent when nobody schedules the real modernization.
- The distributed monolith: services are split but must still deploy and change together, so you get all the pain of distributed systems with none of the independence — worse than leaving it as one monolith.
- Doing the boring step first — discovery, planning, testing, rollback, cost modeling, and governance — instead of skipping it to “save time” today.