I thought it was just a migration

At the start, I genuinely thought this was going to be straightforward.

Move an Oracle database, build a new environment, connect everything together and that’s it. It sounded clean when we spoke about it. Something you could plan out, follow step by step and just get done.

It didn’t take long to realise it wasn’t going to be like that.

Where I actually started

If I’m honest, I didn’t really know Oracle, not properly anyway.

Most of the team didn’t either and somehow I still ended up in a position where I was helping drive the migration of a Oracle database that sat right in the middle of everything.

That was the first real challenge for me. It wasn’t just about doing the work, it was figuring out where to even start when I didn’t fully understand what I was dealing with.

I remember going through bits of documentation, looking at configs, trying to piece things together and still feeling like I only had part of the picture. It’s a strange feeling, knowing something is important and you’re responsible for it, but not fully understanding how it all fits together yet.

Looking back, that uncertainty definitely influenced a lot of the decisions I made early on.

The assumptions I made

Because I didn’t have the full picture, I filled in the gaps. I told myself I’d figure things out as I went along. That once I got closer to the system, things would start to make more sense. And to be fair, some of it did, but not without a few painful moments along the way.

There were times where something didn’t behave the way I expected and when I dug into it, I realised the issue wasn’t the system, it was my assumption about how it worked.

I should have slowed things down at the start, and spent more time with the people who had been supporting and managing these systems for years. The ones who knew all the quirks, the odd behaviours, the bits that don’t show up anywhere but somehow keep everything running.

Instead, I ended up learning most of that the hard way, usually when something broke and I had no choice but to figure out why.

Trying to do it “properly”

Early on, I had this idea that this was a good opportunity to do things properly. Build a clean environment, use the latest versions, apply the latest patches and improve things while we were at it. It felt like the right thing to do at the time.

Reality has a habit of getting in the way. Time became a factor quite quickly. There was pressure to move things along and that meant I had to rethink how I was approaching it. Instead of improving everything upfront, I had to focus on recreating what already existed.

The same versions, with the same patches, the same setup and quirks.

I wasn’t installing the latest version of Oracle or upgrading anything. I didn't need to do that. I slowly began to realise that my task was to rebuild what was already there, just in a different environment.

There was a moment where this really clicked. I remember trying to introduce a newer version of Oracle APEX, thinking it would best to do it now, only to realise it caused more issues than it solved. That’s when it became clear that, at that stage, stability mattered far more than improvement.

That shift took me a bit of time to accept and if I’m being honest, it cost me time as well. I was trying to fix things that didn’t actually need fixing yet.

The real system

At the beginning, I thought I had a decent understanding of the system. A database, a few applications and some infrastructure to build. It looked fairly straightforward when you broke it down like that.

But that wasn’t the real system. The real system was everything underneath.

I started coming across scripts that were written years ago to run very specific jobs, cron jobs that were running in the background keeping services alive and processes that hadn’t been touched in ages but were still important.

And then there were the script chains. One script calling another, which called another and so on. Trying to trace those sometimes felt like going round in circles.

I remember trying to resolve one issue and ending up several layers deep just to understand where something was actually being triggered. It wasn’t obvious and it definitely wasn’t documented in a way that made it easy to follow.

None of this was visible at the start, but all of it mattered, and once I missed something, things started breaking in ways I didn’t expect.

When things started going wrong

There was a point where everything looked fine on its own. The database had been moved, the infrastructure was up, and applications were starting.

From the outside, it looked like things were going well. I started connecting everything together, and that’s when things started to get...interesting.

I ran into situations where the data looked fine but didn’t behave the same way. Small differences in formatting caused bigger issues further down the line. Some processes just didn’t run properly because the timing wasn’t quite right.

And then there was something else I hadn’t fully thought through. During the scoping phase, I had identified systems and applications that I thought we didn’t need anymore. It felt like a good opportunity to simplify things, but once everything was connected, it became clear those systems were still part of how things worked.

They weren’t obvious, but they were woven into the flow.

Now I had to figure out what to do about it. In some cases, that meant reworking parts of the system. In others, it meant introducing something new to replace what was removed. Either way, it added more work than I had planned for.

These are the things you don’t really account for until you’re already deep into it.

Not 'just a migration'

At some point, I realised something pretty simple: migrations are not easy.

They’re frustrating, messy and at times just draining. You end up trying to fix issues you’re not fully equipped to deal with yet, but you still have to figure it out. I spent a lot of time sitting there thinking, “one more try, this might work” and then realising hours had passed.

There were definitely moments where I looked up and realised how late it had got without even noticing. I just got stuck into it and kept going. It wasn’t structured. It wasn’t clean. It was just constant problem-solving and sometimes trial and error until something finally clicked.

Over time, the way I looked at it changed. I stopped thinking about it as moving systems and started thinking about it as recreating behaviour. That shift made a big difference. It wasn’t enough for the data to be there. It had to behave the same way. Systems had to interact the same way. Everything had to work together, not just individually.

Once I started thinking like that, things started to make more sense.

The cutover

When it came to the cutover, I definitely felt it. Even with all the prep, there’s always that bit of uncertainty. You can test as much as you want, but going live is different. I was watching everything closely, checking logs, making sure nothing unexpected was happening. Then the message came through: cutover was successful.

It’s hard to describe that moment properly.

All the stress, the long hours, the frustration… it just dropped away. It genuinely felt like a weight had been lifted, like I could finally breathe again. Everything just felt lighter, and in that moment, all of it felt worth it.

The learnings

If I had to do it again, I’d approach the start very differently. I’d spend more time understanding the system before jumping into decisions. I’d ask more questions, even the basic ones, and I’d involve the people who knew the system much earlier.

I’d also be more aware of when to improve things and when to just leave them as they are, and I’d assume there are always hidden dependencies, because there usually are.

From the outside, migrations look straightforward. From my experience, they’re anything but. They’re messy, unpredictable and at times exhausting, but when everything finally works the way it should, there’s a level of satisfaction that makes all of it worth it.