Capstone Part 4 — The Data Move & the Cutover Runbook
Parts 1 to 3 were decisions on paper. This is the part where something actually has to happen on a specific Sunday at a specific hour, and 22 clinics open on Monday whether you finished or not. You’ll do the arithmetic that decides how 50.2 terabytes physically travel — in the open, with every unit conversion shown — then write the minute-by-minute runbook for the single hardest cutover in the estate, and finally the rollback plan that answers the only question that matters at four in the morning: what happens to the clinical notes that were written twelve minutes ago and exist in exactly one place?
You’re moving house on Sunday night, and the family has to be able to live normally on Monday morning. Two questions decide everything. First: forty-one thousand boxes won’t fit through the letterbox, so do you post them one at a time for a month, or hire a lorry? Second: once you’ve handed the old keys back, what exactly do you do if the new house’s lights don’t come on — and what about the homework someone already did on the new kitchen table, which exists nowhere else in the world?
Starting: a disposition matrix from Part 1, a landing-zone design from Part 2, and a wave plan from Part 3 that puts ImageVault’s bulk seed in month 2 and PIMS-Core’s cutover in Wave 4. Leaving this page: three finished documents — a data-movement plan covering every dataset in the estate with a named validation step and a named signer; a cutover runbook for PIMS-Core, minute by minute, that fits inside a four-hour Sunday window with an hour of slack; and a rollback plan with an explicit point of no return, a wall-clock deadline, and a named person allowed to call it. Part 5 picks up the morning after and asks what all of this costs.
You need a spreadsheet and a text editor. Nothing else. No cloud account, no card, no infrastructure. Real tools are named throughout as “this is what you’d reach for” — none of them is required to finish this page.
What this part assumes, and what it produces
☺ Like you’re 10: Three earlier pages made the decisions. This page turns three of those decisions into things you could hand to someone on a Sunday night and they’d know what to do.
This part is written to follow Part 3, but it is deliberately self-contained: every fact about the estate that this page needs is restated below, so you can work it cold. If you have done the earlier parts, use your own answers where they differ from the ones here — the method is what’s being practised, not the specific R you chose.
The three things Parts 1–3 were supposed to leave behind
| From | The decision this part depends on | If you skipped it, assume this |
|---|---|---|
| Part 1 | Which datasets travel at all — because the cheapest terabyte to move is the one you already decided to retire. | FileShare’s cold 40% and 31 of BI-Reports’ 40 reports are Retire. Everything else in the table below travels. |
| Part 2 | A destination that exists, with non-overlapping CIDRs, hybrid connectivity, identity, and a static egress address for LabBridge. | Landing zone live from month 1; site-to-site VPN up; DNS for brambleside.internal served from the cloud with on-prem forwarders. |
| Part 3 | When each thing moves — and specifically that ImageVault seeds in month 2 even though PIMS-Core doesn’t cut over until Wave 4, month 8. | Wave 0 = foundation (month 1). Wave 4 = PIMS-Core + ImageVault path flip, a Sunday in month 8 (February). |
What you will produce
- Artifact A — the data-movement plan. One row per dataset: size, file count, the path it travels by, why that path, who validates it on arrival, and who signs the reconciliation report.
- Artifact B — the PIMS-Core cutover runbook. A prep block from T-14 days, then a minute-by-minute table for the night with two go/no-go gates, a smoke test, and a comms plan.
- Artifact C — the rollback plan. An explicit point of no return, one plan for each side of it, a named decision owner, and the latest wall-clock minute the revert may be called.
These three artifacts are one document in three parts, and they are written in this order for a reason. The data-movement plan decides how long the bulk takes, which decides what is already in place on the night, which decides how short the cutover can be, which decides how much you might have to hand-carry back. Reverse the order and you end up designing a four-hour window around a copy job that needs thirty-four days.
The estate, restated — only the parts that move bytes
☺ Like you’re 10: Here’s the full list of boxes, how big each one is, and the rules about when you’re allowed to be carrying them.
Brambleside Veterinary Group runs 22 small-animal clinics plus one 24-hour emergency hospital, around 600 staff, all in one country. Everything currently lives at Fort Rusty: VMware vSphere 7 across a converted server room at the flagship clinic and eight racks in a colo 40 km away. The colo contract ends 31 March — month 9 of a nine-month programme, and there is no renewal beyond a three-month extension at 2.4× the rate.
The stated data footprint — 50.2 TB
| System | Data | Shape | The fact that decides how it travels |
|---|---|---|---|
| ImageVault — X-ray/ultrasound archive since 2004 | 41 TB 1,502,384 studies (~28 MB each) +900 GB/month | Aging NAS in the colo, SMB | PIMS-Core references every study by UNC path. 78% of studies untouched in 24 months. Reads must never break. |
| FileShare — staff file server | 6.2 TB 1,100,000 files across ~140,000 folders mean 5.6 MB, median 340 KB | Windows file server, NTFS ACLs | 40% of the bytes untouched in 5 years. A full enumeration pass with ACLs takes 3.5 hours — file count, not size, is the constraint. |
| PIMS-Core — appointments, clinical notes, billing | 1.9 TB | 4 × Win Server 2016 + SQL Server 2016 Enterprise cluster | Used every minute in every clinic. Downtime tolerance ≤ 4 h, Sunday 02:00–06:00 only, never a Monday. |
| BI-Reports — SSRS, 40 scheduled reports | 400 GB | 1 VM | The audit log proves 31 of the 40 haven’t been opened in 18 months. Only the 9 survivors’ history needs to travel — roughly 60 GB. |
| ClaimsFeed — nightly insurance claims via SFTP | 280 GB | Oracle Database 12c SE | May miss one night. Licence renewal due month 7 — which is the whole reason it replatforms rather than rehosts. |
| VetLearn — internal CPD portal | 220 GB | 1 VM | Repurchased to the vendor’s SaaS. The export goes to the vendor’s importer, not into your landing zone — but it still crosses the same link. |
| StockCtrl — consumables + controlled-drug register | 140 GB | Vendor app on SQL Server | Controlled-drug register carries a 7-year retention obligation that survives the migration. |
| BramblesideOnline — site, booking, repeat scripts | 90 GB | 2 VMs + MySQL 5.7 | MySQL 5.7 is out of support — the version jump is the work, not the bytes. Downtime tolerance ≤ 2 h. |
| RotaMaster — staff rota | ~15 GB export (not part of the 50.2 TB) | Classic ASP, Win Server 2012 R2 | Repurchased. Only a CSV bundle travels; the application is retired in place. |
| LabBridge · AD-DC01/02 · PrintSrv · BackupVault · DevTest | no material data of their own | VMs, tape library | LabBridge needs a fixed public egress IP. PrintSrv and AD are Retained on-prem for now. The tape library holds the 7-year finance retention. |
The four constraints that decide this whole part
| Constraint | The number | What it forbids |
|---|---|---|
| The link | Colo circuit is 500 Mbps but contractually shared. Brambleside can sustain at most 150 Mbps without burst charges. | Any plan that assumes 500 Mbps. Any plan that saturates 150 Mbps for weeks while 22 clinics are also using it. |
| The window | PIMS-Core: ≤ 4 hours, Sunday 02:00–06:00 only, never a Monday. BramblesideOnline ≤ 2 h. ClaimsFeed may miss one night. ImageVault reads must never break. | Any cutover whose happy path uses more than about three hours. You need slack, and slack has to be designed in, not hoped for. |
| The blackouts | No cutovers during the two-week spring vaccination campaign (mid-March) or 20 Dec – 3 Jan emergency-cover period. | December and March. Which is why Wave 4 lands in February — month 8: after Christmas, before the campaign, six weeks clear of the 31 March hard stop. |
| The clock | Colo contract ends 31 March. Extension only at 2.4× the rate. | Any bulk transfer that isn’t finished with months to spare. A 34-day copy that starts late has no second attempt. |
Every figure on this page — sizes, transfer rates, shipping durations, row counts — is invented for the exercise, and Brambleside Veterinary Group is a fictional company. Real link goodput, real appliance logistics and real cloud pricing all change constantly. The skill being practised is the method: convert units explicitly, compare paths on both wall-clock and link cost, and write the answer down where someone else can check it. Never carry a number from this page into a real business case.
Artifact A — the data-movement plan
☺ Like you’re 10: Sort every box into “goes on the lorry”, “goes through the letterbox”, and “doesn’t go at all” — and write down how you’ll know it arrived.
Start with the arithmetic, because the arithmetic is the only part of a migration that gives an unambiguous answer. Everything else is judgement; this is a division problem, and a division problem that nobody does in the open is a division problem that gets guessed.
Step 1 — do the 41 TB sum, showing every conversion
The single question this part exists to answer: can ImageVault go over the wire? Do not reach for a rule of thumb. Do it properly, one line at a time, so that anyone reading your plan can find the step they disagree with.
ImageVault over the wire — the full working
1. 41 TB the archive, as it stands today
2. 41 × 1,000 = 41,000 GB TB → GB (decimal, as storage is sold)
3. 41,000 × 1,000 = 41,000,000 MB GB → MB
4. 41,000,000 × 8 = 328,000,000 Mb BYTES → BITS ← this is the ×8 everyone forgets
5. 328,000,000 ÷ 150 = 2,186,667 s at the 150 Mbps we are allowed to sustain
6. 2,186,667 ÷ 3,600 = 607.4 h
7. 607.4 ÷ 24 = 25.3 days at a PERFECT, uninterrupted 150 Mbps
8. 25.3 ÷ 0.75 = 33.7 days at 75% goodput (TCP overhead, retries,
the sync tool's own chatter, checksums)
ANSWER: ~34 days of continuously saturating a link that 22 clinics also need,
during which the archive grows by another ~1 TB.Line 4 is where most people’s estimate silently breaks. Storage is sold in bytes; links are sold in bits per second. If your answer is eight times too optimistic, that is the line you skipped. Line 8 is the second trap: nobody ever gets the sticker rate. Pick a goodput assumption, write it down as an assumption, and be ready to defend it — 75% is a reasonable planning figure for a WAN sync with verification enabled, and if your organisation has measured its own, use that instead.
Thirty-four days is not the problem. Thirty-four days of a shared circuit is the problem. Brambleside is allowed 150 Mbps of a 500 Mbps contractually shared link; above that, burst charges land every month. So the honest reading of line 8 is not “the copy takes five weeks” — it is “for five weeks, nothing else can move, and clinic traffic competes with a bulk job the whole time.” Wall-clock is only half the cost of a transfer. Link occupancy is the other half, and it is the half that gets people shouted at.
Step 2 — cost the appliance round trip honestly
An offline appliance — AWS Snowball, Azure Data Box, Google Transfer Appliance, and each cloud’s equivalents — is a rugged encrypted box the provider ships you. You copy onto it over your own LAN, ship it back, and they ingest it. Its wall clock is dominated by logistics, not by data size, which is exactly why it wins at scale. But it is not free of time, and a plan that says “ship an appliance” without a day count is not a plan.
| Stage | Days | Uses the colo link? | Needs Brambleside staff? |
|---|---|---|---|
| Order placed → appliance delivered to the colo | 7 | No | No |
| On-site copy — ImageVault 41 TB at ~200 MB/s over 10 GbE | 2.4 | No | Yes |
| On-site copy — FileShare hot 3.7 TB at ~40 MB/s (small files, ACLs preserved) | 1.1 | No | Yes |
| Return shipping | 2 | No | No |
| Provider ingest + checksum verification | 5 | No | No |
| Total, door to door | ~18 days | Zero | 4 days |
Look hard at rows two and three. FileShare’s hot subset is eleven times smaller than ImageVault and takes 45% as long to copy. That is the file-count trap appearing for the first time — and it appears on your own LAN, before a single byte has gone anywhere near the WAN. If you sized the appliance window on total terabytes, you just under-booked it by a day.
Step 3 — find the crossover, and then distrust it slightly
The crossover is the dataset size at which the appliance stops being slower and starts being faster. It is worth deriving once, for your own link, because after that you can answer the question in your head for every dataset in the estate.
Where does the appliance start winning on wall-clock?
Over the wire, per TB: 8,000,000 Mb ÷ (150 Mbps × 0.75) ÷ 86,400 s/day
= 0.823 days per TB
By appliance: 14 days fixed (ship out, ship back, ingest)
+ 0.058 days per TB of local copy (at 200 MB/s)
Set them equal: 0.823 × S = 14 + 0.058 × S
0.765 × S = 14
S = 18.3 TB
CROSSOVER: just over 18 TB on THIS link with THIS logistics chain.Now distrust it slightly, in two directions. Downward: at 10 TB the wire technically “wins” at 8.2 days — but that is 8.2 days of a circuit the clinics are sharing, and the appliance would have cost zero of it. Upward: the crossover collapses if you can buy more bandwidth, and it climbs if delivery is slow or your country’s customs are involved. 18.3 TB is a property of Brambleside’s situation, not a fact about the universe. The transferable skill is the derivation, not the number — that is precisely what the Size the Data Move drill exists to give you reps on.
Step 4 — the number that makes the whole plan work
Here is the part people miss. Once the bulk seed has landed, keeping the cloud copy current until Wave 4 does not need 150 Mbps. It needs almost nothing:
The standing sync, month 2 → month 8
Archive growth: 900 GB/month
900,000 MB × 8 = 7,200,000 Mb per month
30 days × 86,400 = 2,592,000 seconds per month
7,200,000 ÷ 2,592,000 = 2.78 Mbps average
÷ 0.75 goodput = 3.7 Mbps of budget
ANSWER: under 4 Mbps of your 150 keeps the cloud copy current
for the six months between the seed landing and the flip.That is the argument in one line: the appliance converts a 34-day link-saturating problem into an 18-day logistics problem plus a permanent 4 Mbps trickle. And it explains why Part 3 insists the seed happens in month 2 even though the cutover is in month 8. Seed early and you buy six months of cheap, boring, unattended sync. Seed late and either PIMS-Core reads 41 TB back over the VPN for months, or your entire nine-month schedule is hostage to one copy job with no second attempt before 31 March.
Seed-then-sync is the shape of almost every large data move: one enormous one-off transfer by whatever means is fastest, then a small continuous one that keeps the copy warm until you’re ready to switch. The on-prem NAS stays authoritative the whole time — a strictly one-way sync, never bidirectional — and only at cutover does the path flip. Two-way sync between an old and a new home is not a safety net; it is two sources of truth, which is one more than you can afford.
Step 5 — the FileShare problem, which bandwidth math will lie to you about
FileShare’s hot subset is 3.7 TB. By line 8 of the arithmetic above that is 3.0 days over the wire — comfortably under the crossover, so the wire should win. It doesn’t, and the reason has nothing to do with bandwidth.
- Enumeration dominates. A full walk of 1.1 million files across 140,000 folders, reading NTFS ACLs and timestamps, takes 3.5 hours against this NAS. That cost is paid before a single byte moves, and it is paid again on every incremental pass, because a timestamp-based sync has to re-walk the whole tree just to discover the three thousand files that changed.
- The median file is 340 KB, not 5.6 MB. The mean is dragged up by a few thousand large scans; 2% of the files hold about 74% of the bytes. So the long tail is hundreds of thousands of tiny files, each paying a fixed per-file cost in round trips, and per-file cost does not shrink when you buy more bandwidth.
- The window arithmetic is brutal. If your final sync is a timestamp walk and your cutover window is four hours, you have spent the entire window enumerating before you copy anything.
So FileShare gets three answers, not one: the hot 3.7 TB rides the same appliance as ImageVault (it is already going, and the box has room); the final delta uses a change-journal-based mechanism — the NTFS USN journal, or a DFS-R-style replication group — so the last sync reads a list of changes rather than re-deriving one; and the cold 2.5 TB never travels at all, because Part 1 marked it Retire.
Before you read the model ledger, fill in three rows yourself on paper. For ClaimsFeed (280 GB), BramblesideOnline (90 GB) and PIMS-Core (1.9 TB), write: how it travels, how many hours or nights that takes at 40 Mbps (a third of your budget — leaving room for everything else), and one validation check that would catch a silent failure. Then check yourself: does any of those three justify a second appliance? (It doesn’t — and knowing why is the point.)
Step 6 — write the ledger
Now put it all in one table. This is Artifact A. Every dataset in the estate appears exactly once, including the ones that don’t travel, because “we consciously decided not to move this” is a line a steering committee will ask you for and you will not want to reconstruct it from memory.
Artifact A — data-movement plan. One row per dataset. Columns:
Dataset | Size | File count | Travels? | Path | Why this path
| Scheduled | Validation on arrival | Signed off by
Rules for filling it in:
• Every row's "Why this path" must cite a number, not an adjective.
• Every row that travels must name a validation step that would
catch a SILENT failure — not just "the job said success".
• Every row must name a human who signs the reconciliation report.
• Rows that don't travel still need a "Signed off by" — someone
has to own the decision not to move something.Reveal the worked data-movement plan (Artifact A)
Two paths carry everything: one appliance takes 44.7 TB, and the wire takes 2.7 TB spread across seven months. That is 94% of everything that travels going by road and 6% going by wire — and the 6% is what people instinctively worry about.
| Dataset | Size / count | Path | Why — with the number | Validation on arrival | Signed by |
|---|---|---|---|---|---|
| ImageVault — bulk, frozen at seed | 41 TB 1,502,384 studies | Appliance, month 2 | 34 days over the wire at 75% goodput vs 18 days door-to-door using zero link. Above the 18.3 TB crossover by a factor of two. | Study count matched to the DICOM index; SHA-256 manifest generated at freeze, re-verified after ingest; byte-for-byte compare of 500 randomly sampled studies; 20 named studies opened in the PIMS-Core viewer by a clinician. | Migration lead + Head of Diagnostic Imaging |
| ImageVault — delta, seed → cutover | ~30 GB/day ~32,000 studies/month | One-way sync over the link, months 2–8 | 3.7 Mbps of a 150 Mbps budget. NAS stays authoritative until the path flips. | Daily automated reconciliation: studies written on-prem vs studies present in cloud, difference must be zero at 06:00 each day. Three consecutive non-zero days escalates. | Migration lead |
| FileShare — hot 60% | 3.7 TB 660,000 files | Same appliance, then change-journal sync | 3.0 days by bandwidth — but 3.5 h per enumeration pass makes a timestamp walk impossible inside any window. USN journal for the delta. | File count and total bytes per top-level share; ACL comparison on 50 sampled paths including three known-restricted folders; a list-only (robocopy /L) pass returning zero differences. | IT manager |
| FileShare — cold 40% | 2.5 TB 440,000 files | Does not travel | Untouched in 5 years. Retired per Part 1 — one verified offline archive copy retained, restore-tested once, then the live share is deleted. | Archive copy restore-tested end to end before the source is deleted. Deletion evidence captured (file list + hashes) before wipe. | IT manager + Finance Director |
| PIMS-Core SQL | 1.9 TB → ~550 GB compressed | Wire. Compressed full backup seed at T-14d, then log shipping to cutover | Uncompressed, 1.9 TB at 40 Mbps is 5.9 days. With SQL Server backup compression at ~3.5×, the seed is 550 GB ≈ 41 hours — under two nights. | LSN match source vs target; DBCC CHECKDB clean; the 12 reconciliation queries (below), each against a value recorded at 02:00 from the frozen source. | Database engineer + Practice Systems Manager |
| ClaimsFeed Oracle 12c → managed PostgreSQL | 280 GB | Wire. Schema conversion, then CDC | 21 hours at 40 Mbps — one night. Heterogeneous, so the schema is the work, not the bytes. A managed migration service (AWS DMS / Azure DMS / Database Migration Service) does the conversion assessment first. | Row counts per table; SUM() of every money column matched to source; a parallel run — one night’s claims batch generated on both systems and the two output files diffed byte for byte. | Database engineer + Finance Director |
| VetLearn export | 220 GB | Wire, to the SaaS vendor’s importer | 17 hours at 40 Mbps. Repurchased — it never enters your landing zone, but it does cross your link, so it gets a scheduled slot like everything else. | Course count and learner-record count reported by the vendor’s import log; 25 sampled learner records checked for completion dates and certificates. | L&D Manager |
| StockCtrl | 140 GB | Wire. Backup/restore | 9 hours at 40 Mbps. Vendor supports cloud hosting, so a straight rehost. | Row counts; controlled-drug register reconciled row for row against the 7-year retention requirement — this one is a legal record, so a sampled check is not enough. | Head of Clinical Operations |
| BramblesideOnline MySQL 5.7 → managed MySQL 8 | 90 GB | Wire. Dump + CDC | 6 hours at 40 Mbps. The 5.7 → 8 version jump is the work; ≤ 2 h downtime tolerance means CDC, not a dump-and-restore on the night. | Row counts and a per-table checksum comparison; functional tests of the booking and repeat-prescription flows against a known client record. | Application engineer |
| BI-Reports — 9 surviving reports | 60 GB | Wire. Export | 4 hours at 40 Mbps. Only the survivors’ snapshot history travels. | Each of the 9 reports executed on both old and new, outputs diffed. Any report that can’t be diffed clean is not a survivor — it is a rebuild. | Finance Director |
| BI-Reports — 31 dead reports | 340 GB | Does not travel | 18 months with no opens, proven by the audit log. Retired per Part 1. | Audit-log evidence exported and retained as the justification before anything is deleted. | Finance Director |
| RotaMaster export | ~15 GB CSV | Wire, into the SaaS rota product | Under an hour. The ASP application itself is retired in place — no source control, no tests, nothing worth carrying. | Staff count matched; the next 8 weeks of published rota compared line by line by the HR manager before the old system is switched off. | HR Manager |
| BackupVault + tape library | tapes | Does not travel — Retained, then re-homed in Part 5 | Holds the 7-year finance retention. The obligation outlives the data centre, so it needs a new home before 31 March, not a migration. | Retention inventory produced and matched against the 7-year obligation; a restore tested from the oldest tape still in scope. | Finance Director |
Totals. Appliance: 41 + 3.7 = 44.7 TB. Wire: 1.9 + 0.28 + 0.22 + 0.14 + 0.09 + 0.06 TB + a 15 GB rota export ≈ 2.7 TB, which is 2.2 days of continuous link at 150 Mbps — spread across seven months, it is close to invisible. Does not travel: 2.5 + 0.34 = 2.84 TB. Sum: 50.2 TB, which is the whole estate, accounted for.
The one-sentence version for the steering committee: “We ship 94% of the data on one appliance in month 2, keep it current on under 4 Mbps for six months, and move the remaining 2.7 TB over the existing link in scheduled overnight slots — so the colo circuit is never the thing standing between us and 31 March.”
Step 7 — validation, and the difference between “the job said success” and “it arrived”
☺ Like you’re 10: The lorry driver saying “all delivered” is not the same as you counting the boxes and opening a few.
A copy tool reporting success means the tool did not crash. It does not mean the data is right. Every dataset in Artifact A therefore names a check that would catch a silent failure — the kind that reports green and is wrong. Four techniques cover almost everything, and Data Migration & Data Gravity covers the theory behind each:
| Technique | Catches | Misses | Use it for |
|---|---|---|---|
| Row / file / object counts | Missing or duplicated records — a truncated copy, a re-run that double-loaded | Corruption. A row that arrived with the wrong contents still counts as one row. | Every dataset, every time. It is cheap and it is the first thing that ever goes wrong. |
| Checksums / hash manifests | Silent corruption — a flipped bit, a truncated file, a character-set mangling | Structural problems. A perfectly-hashed file in the wrong folder still hashes fine. | ImageVault’s 1.5 million studies; anything that goes on physical media and travels by road. |
Aggregate reconciliation — SUM(), MAX(), per-day totals | Off-by-a-day loads, timezone shifts, decimal precision loss, encoding damage in money columns | Compensating errors — two mistakes that happen to cancel out | Anything financial. ClaimsFeed, InvoiceLine, the controlled-drug register. |
| Parallel run — do the real work on both, diff the output | Everything the other three miss, because it exercises the actual business process end to end | Nothing much — but it is the most expensive check, so reserve it for the highest-stakes dataset | ClaimsFeed’s nightly batch. Run one night on both, diff the two output files. |
And then the step that is not technical at all: somebody signs. Each reconciliation report gets a named human who has read it and accepts the data is correct. Not the person who ran the copy — the person who owns the consequence if it is wrong. That is why the ledger’s last column pairs a technical signer with a business one for anything with a legal or financial obligation attached.
Artifact B — the PIMS-Core cutover runbook
☺ Like you’re 10: The exact list of what happens, minute by minute, on the one night that matters — written weeks earlier, in daylight, by people who slept the night before.
PIMS-Core is the hardest single cutover in the estate, and it is worth being precise about why: it is used every minute in every clinic; it has a four-hour window that can only ever be a Sunday and never a Monday; it depends on Active Directory, which is Retained on-prem; it depends on StockCtrl and on PrintSrv, which is also Retained on-prem and latency-sensitive; and it reads 1.5 million imaging studies by UNC path, which means the imaging archive and the practice system have to flip in the same hour or not at all.
A note on which R you chose
This runbook is written for Rehost — the four-node SQL Server cluster and the application tier lifted onto cloud VMs inside your own landing zone, because the vendor supports this product on IaaS only and their hosted SaaS edition is a clinical-data conversion plus a 22-clinic retraining programme that will not fit before 31 March. Repurchasing to that hosted edition is deliberately deferred to year two, which is exactly the kind of two-step a hard deadline forces and Part 5 picks up as a modernization candidate. If Part 1 got the vendor to confirm an in-country hosted tenant with a slot before month 7 and you chose Repurchase, that is the better answer and you do not need to redo this page: every row of the runbook still applies. Three things change and nothing else. The restore is run by the vendor’s DBA rather than yours, so a third party sits on your bridge call and owns a step in your critical path. The go/no-go deadline gets earlier, because the vendor’s change window is theirs and not yours. And the UNC-path answer below becomes something you negotiate rather than engineer — which turns it into a lead-time item, and lead-time items get asked about in week 1, not month 7. Note those three deltas at the top of your runbook and carry on.
The UNC path — the one design decision that makes this cutover short
PIMS-Core stores every study as a path like \\NAS-COLO-01\imaging\2019\04\1145882.dcm, in a table with 1,502,384 rows. When PIMS-Core moves, that string has to keep resolving. There are three ways to arrange that, and only one of them is a four-hour cutover:
| Option | What you change | Cutover cost | Rollback cost | Verdict |
|---|---|---|---|---|
| Rewrite the stored paths | 1.5 million rows in the clinical database | A large, slow, transactional data change in the middle of your window — and a schema you now have to keep consistent with the vendor’s next upgrade | Another 1.5 million-row update, under pressure, at 04:12 | No. You are changing clinical data to solve a naming problem. |
| Leave PIMS-Core reading the on-prem NAS | Nothing | Zero on the night — and every imaging read afterwards crosses the VPN, and Fort Rusty stays alive past 31 March | N/A | No. It defeats the entire programme to save one hour. |
| Keep the string, move what it points at | One DNS record: NAS-COLO-01 resolves to the cloud SMB endpoint instead of the colo NAS | Seconds. TTL lowered to 60 s at T-24h. | Seconds. Change the record back. | Yes. The flip is a name resolution change, and so is the way back. |
This is worth internalising well beyond this exercise: the cheapest thing to move on the night is a pointer; the most expensive thing to move on the night is data. Every hour you spend in the weeks beforehand converting a data change into a pointer change buys you back ten minutes of the window and an entire rollback path. Read Architecture Patterns on what actually flips the traffic — DNS, load balancer, feature flag — and notice that every mechanism it lists is a pointer.
The prep block — everything that happens in daylight
A runbook that starts at 02:00 is a runbook that will fail at 02:40. Most of the work is before the night, done by people who are awake:
| When | What | Who | Why it can’t wait until the night |
|---|---|---|---|
| T-14d | Full dress rehearsal against the DevTest copy: restore, catch up to zero lag, flip a test DNS zone, run every validation query, run the smoke test, then roll the whole thing back. Record the actual minutes for every step. | Whole team | If the rehearsal doesn’t fit in three hours, your plan is wrong — and you have two weeks to fix a plan, or forty minutes to fix a night. |
| T-14d | Compressed full backup seed of the 1.9 TB SQL cluster shipped over the link (550 GB compressed, ~41 h at 40 Mbps), then log shipping enabled and left running. | Database engineer | The whole point of the four-hour window is that only the tail log moves on the night. |
| T-7d | Change freeze on PIMS-Core: no vendor patches, no schema changes, no new scheduled reports, no new integrations. | Practice Systems Manager | Every change after the rehearsal is a change you did not rehearse. |
| T-7d | ImageVault read verification: 500 sampled studies opened from the cloud SMB endpoint; sync lag confirmed under 15 minutes; study-count difference confirmed zero. | Migration lead | Discovering the archive doesn’t read at 02:50 is discovering it four hours too late. |
| T-5d | Comms wave 1 to all 22 clinic managers, the emergency hospital, and the out-of-hours triage provider: date, window, what will be unavailable, what the fallback is, the number to call. | Comms lead | People plan their Sunday around this. Five days is the minimum notice that gets read. |
| T-3d | The paper fallback pack, couriered to every site: blank consult forms, blank dispensing labels, a printed list of Sunday and Monday appointments per clinic, and — for the emergency hospital — a printed 72-hour medication schedule for every in-patient. | Practice Systems Manager | This is the actual disaster plan. A veterinary practice can run on paper for a day; it cannot run on a promise that the system will be back shortly. |
| T-2d | Go/no-go pre-check. Nine entry criteria, all must be green in writing: rehearsal passed, seed complete, log shipping healthy, ImageVault read test passed, comms sent, paper packs delivered, on-call roster confirmed, rollback rehearsed, decision owner available. | Decision owner | Cancelling two days out costs a rescheduled Sunday. Cancelling at 02:00 costs the team’s confidence. |
| T-24h | DNS TTL lowered to 60 seconds on pims.brambleside.internal and NAS-COLO-01. Verified from a clinic workstation, not just from the server room. | Network engineer | A 24-hour TTL turns a 60-second rollback into a day-long one. This single step is the difference between a revert and an outage. |
| T-12h | Final full backup of the source cluster, verified restorable — actually restored somewhere, not merely taken. | Database engineer | An untested backup is a rumour. |
| T-12h | On-call roster published: seven named people, mobile numbers, escalation tree, bridge details. | Cutover lead | At 03:40 you need a name, not a rota. |
The seven people, and why one of them isn’t from IT
| Role | Owns | From |
|---|---|---|
| Cutover lead | The runbook and the clock. Calls the clean revert. Declares done. | Migration team |
| Database engineer | The tail-log ship, the LSN gate, the restore, the delta export if it comes to that. | Migration team |
| Network / platform engineer | DNS, the VPN, the SMB endpoint, LabBridge’s static egress address. | Migration team |
| Application engineer | The app tier; keeps the vendor’s support line open on a second bridge. | Migration team |
| Comms lead | The comms plan. The only person who talks to clinics. | Migration team |
| Clinical validator | Runs the smoke test on a real clinic workstation. The only person who can fail it. | A senior veterinary nurse |
| Decision owner | Go/no-go #1 and #2, and the mitigate-forward call. On the bridge from 03:30. | Head of Clinical Operations |
Two of those seven are not from IT, and that is deliberate. The clinical validator exists because “the service returned HTTP 200” and “a vet can do a consultation” are different claims, and only one of them matters on Monday. The decision owner exists because the person who spent nine months building this is the worst possible person to ask whether to abandon it at 03:55 — you want the decision owned by whoever carries the consequence, not whoever carries the sunk cost.
Note also what this costs: five of the seven come from a migration team that Part 3 established is six people, and one of them left at month 3. The entire remaining migration team is on this bridge. Nothing else happens that weekend, and your wave plan has to say so.
The night — minute by minute
This is the table. Every row has a clock time, an owner, an expected result, and a failure branch — because a runbook that only describes the happy path is a description, not a runbook.
| Clock | Step | Who | Expected result | If it fails |
|---|---|---|---|---|
| 01:30 | Bridge opens. Roll call of all seven roles. Rollback runbook open on a second screen. | Cutover lead | Seven voices. | Any role absent → no-go. Stand down, reschedule. Nothing has been touched. |
| 01:45 | Pre-flight: log-shipping lag < 60 s; target instance healthy; ImageVault sync lag < 15 min; DNS TTLs confirmed at 60 s from a clinic workstation. | DBA + Network | Four greens, read aloud. | Any red → no-go. |
| 02:00 | GO/NO-GO #1. Proceed, or stand down with nothing changed. | Decision owner | A spoken “go”, logged with the time. | Stand down. Reschedule to the next non-Monday Sunday outside the blackouts. |
| 02:00 | Freeze. Stop the application service on all 4 nodes; set the database READ_ONLY; disable the ClaimsFeed and LabBridge scheduled jobs; publish the maintenance page and login banner. | App + DBA | Zero active sessions within 3 minutes. | Kill lingering sessions; log which clinic each came from — you will want that for next time. |
| 02:05 | Verify zero sessions and zero open transactions. | DBA | Only the DBA’s own session remains. | An open transaction means someone is still writing. Do not proceed until it is gone. |
| 02:10 | Final log ship. Tail-log backup → transfer → restore on target → bring target online. | DBA | Budget 15 min. Rehearsed at 11. | Over 25 min → clean revert. Do not “just wait a bit longer”; that is how windows are eaten. |
| 02:25 | Zero-lag gate. Compare last LSN, source vs target. | DBA | Exact match. Hard gate. | No match → clean revert immediately. There is no version of this where you proceed with a gap. |
| 02:30 | Validation A — data. Run all 12 reconciliation queries against the values recorded from the frozen source at 02:00. | DBA + Practice Systems Manager | 12 of 12 exact. | Any mismatch → clean revert. A count that is “nearly right” is a count that is wrong. |
| 02:50 | Validation B — the ImageVault path. From the new app tier, open five named studies by their stored UNC path: one from 2004, one from 2011, one from 2019, one from last month, one from yesterday. | App + Clinical validator | All five render. | Clean revert — and find out why the T-7d read test passed when this doesn’t. This is the step everyone forgets and it is the one that ends careers. |
| 03:00 | The flip. Change the DNS record for pims.brambleside.internal to the new app tier. Stored UNC strings are not touched. | Network | Propagated within 60 s, verified from three clinics. | Revert the record. It is one record. |
| 03:05 | Bring the application tier up. | App | All 4 nodes healthy within 4 min. | One node down → continue on three, note it. Two or more → clean revert. |
| 03:10 | Smoke test A — the clinic script (nine steps, below), on a real workstation at the flagship clinic. | Clinical validator | Nine of nine pass. 20 min. | Any step fails → clean revert. The validator’s call is final and is not overruled by the migration lead. |
| 03:30 | Smoke test B — the same nine steps, from a clinic on the far side of the country over the clinic VPN. | Clinical validator | Nine of nine. 10 min. | Passing A but failing B means it works when you’re in the building — which is not a pass. |
| 03:40 | GO/NO-GO #2 — the point-of-no-return gate. Everything so far is reversible; everything after 04:00 is not. | Decision owner | A decision, logged. | Decision must be made by 03:55. If it is not made by 03:55, the answer is automatically no-go and the clean revert runs. The default is safe. |
| 03:45 | Re-enable the ClaimsFeed and LabBridge jobs. Confirm LabBridge egresses from the allow-listed static IP — check with the reference lab’s connection log, not with your own. | Network | The lab’s log shows the expected source address. | Leave the jobs disabled. ClaimsFeed may miss one night; that is a stated tolerance. Do not revert the whole cutover for it. |
| 04:00 | ⛔ POINT OF NO RETURN — writes open. Database set READ_WRITE. From this minute, new clinical notes exist only in the new system. | DBA, on the decision owner’s instruction | Timestamped in the bridge log, out loud, by name. | See Artifact C. There is no “fail” branch here — only a different plan. |
| 04:05 | Comms wave 2 — live. To 22 clinic managers, the emergency hospital, the out-of-hours triage provider, the reference lab, and the claims processor. | Comms lead | Sent, with the “report anything odd to this number” line. | — |
| 04:10–05:00 | Hypercare watch. Session count against a normal Sunday, error rate, ImageVault read latency (95th percentile), dispensing-label print success, and DR replication of the new system started and healthy. | All | Nothing anomalous for 50 minutes. | Anything anomalous → Artifact C’s mitigate-forward table. |
| 05:00 | Declared done — with a full hour of the four-hour window unspent. | Cutover lead | Announced on the bridge. | — |
| 05:00–08:00 | Bridge stays open, unattended but reachable. Everyone sleeps with a phone on. | All | Silence. | — |
| 08:00 Sun | First live consult of the day at the emergency hospital is watched end to end by the clinical validator. | Clinical validator | Uneventful. | — |
| 07:00 Mon | Hypercare peak. All seven back on the bridge before the busiest day of the week begins. | All | The real test. Sunday was the rehearsal that happened to be live. | — |
The twelve reconciliation queries
Every one of these has an expected value recorded at 02:00 from the frozen source — that is the entire trick. A query that returns a number nobody can compare against has told you nothing.
-- Three of the twelve, written out in full. Run against the frozen SOURCE at
-- 02:02, record the results on the bridge; run against the TARGET at 02:30
-- and compare. Every one is an exact match or the cutover does not proceed.
-- (3) Total clinical notes — the record that matters most and is never deleted.
SELECT COUNT_BIG(*) AS note_rows, MAX(NoteId) AS max_id, MAX(CreatedUtc) AS newest
FROM dbo.ClinicalNote;
-- expected: 4,912,663 | 4,912,663 | (the freeze instant, to the second)
-- (6) Money. Row count AND sum, because a count alone misses a mangled decimal.
SELECT COUNT_BIG(*) AS line_rows, SUM(AmountGross) AS gross
FROM dbo.InvoiceLine
WHERE FinancialYear = @currentFY;
-- expected: 1,204,559 | 18,442,915.60
-- (11) The ImageVault join. This number IS the archive's study count --
-- if these two ever disagree, a study exists that nothing can find.
SELECT COUNT_BIG(*) AS linked_studies
FROM dbo.StudyLink
WHERE UncPath IS NOT NULL;
-- expected: 1,502,384 -- matches the DICOM index exactly| # | Check | What a mismatch would mean |
|---|---|---|
| 1–2 | Row counts: Client (61,418) and Patient (88,204) | A truncated or partially-restored load. The cheapest check there is. |
| 3 | ClinicalNote count, max id, max timestamp (4,912,663) | Lost clinical records. This is a legal document set; there is no acceptable variance. |
| 4 | ClinicalNote written in the last 24 h (3,180) | A timezone or watermark bug that silently drops the most recent day — the classic one. |
| 5 | Max NoteId and max CreatedUtc match source exactly | Replication stopped before the freeze. Should be impossible after the LSN gate; check anyway. |
| 6 | InvoiceLine count + SUM(AmountGross) for the current FY (1,204,559 / 18,442,915.60) | Decimal precision loss or an encoding problem in a money column. |
| 7 | Open (unpaid) invoices (9,341) | A state column that didn’t survive a type conversion. |
| 8 | ControlledDrugRegister count + max entry timestamp (214,880) | A 7-year statutory retention obligation with a hole in it. |
| 9 | Appointments booked for the next 14 days (27,905) | Monday morning arrives and 22 waiting rooms have no schedule. |
| 10 | Distinct active user accounts (611) | Staff who cannot log in on Monday — the most visible possible failure. |
| 11 | StudyLink rows with a non-null UNC path (1,502,384) | Imaging history that exists on disk but that nothing can find. |
| 12 | DBCC CHECKDB — 0 allocation errors, 0 consistency errors | Corruption you would otherwise discover in three weeks, after the source is gone. |
The nine-step clinic script
☺ Like you’re 10: Don’t ask “is the computer on?” Ask a real vet nurse to do a real appointment, start to finish, and watch.
A smoke test that checks endpoints tests the thing you built. A smoke test that walks a working day tests the thing they need. The clinical validator runs all nine, in order, on a real clinic workstation — twice, once at the flagship and once from a remote clinic over the VPN:
- Log in with a normal clinic account — proving the on-prem Active Directory that is Retained at Fort Rusty still authenticates against a system that now lives in the cloud.
- Find a client by surname, with a deliberately awkward one — an apostrophe, an accent, a hyphen. Character-set damage in a migration hides in exactly these names.
- Open the pet’s history and read a note written more than five years ago.
- View an X-ray from ImageVault — the UNC path, the SMB endpoint, the DNS change and the appliance seed, all proven in one click.
- Add a clinical note and save it. (During the smoke test the database is still read-only, so this step is run against a designated test patient after 04:00, and rerun if the revert is called.)
- Dispense an item from StockCtrl, including a controlled drug, and confirm the register entry appears.
- Print a dispensing label on the clinic’s own printer — PrintSrv is Retained on-prem and latency-sensitive, so this is the step that proves the hybrid path actually works rather than merely existing on a diagram.
- Take a payment via the processor’s hosted redirect, confirming no cardholder data touches Brambleside systems — the arrangement that keeps the compliance scope small stays intact after the move.
- Book a follow-up appointment and confirm it appears in the clinic diary.
Steps 1, 6, 7 and 8 all cross a boundary — to on-prem AD, to StockCtrl, to a Retained print server, to an external payment processor. Those four are where migrated systems break, and they are precisely the steps a technical smoke test skips because they are “not part of PIMS-Core.” They are part of the working day, which is the only unit of testing that matters at 03:10 on a Sunday.
The comms plan
| When | Who is told | Channel | The message | Sent by |
|---|---|---|---|---|
| T-14d | All staff | PIMS-Core is moving on Sunday DD. Here is what changes for you (nothing) and what to expect. | Comms lead | |
| T-5d | 22 clinic managers · emergency hospital · out-of-hours triage provider | Email + the practice group chat | The window, what will be unavailable, the fallback, the number to call. | Comms lead |
| T-3d | Every site | Physical courier | The paper fallback pack. | Practice Systems Manager |
| T-12h | The seven on-call | Bridge invite + SMS | Join link, roles, escalation tree, the rollback runbook. | Cutover lead |
| 02:00 | All staff | Status page + login banner | PIMS-Core is unavailable until 06:00. | Automated |
| 04:05 | 22 clinics · emergency hospital · out-of-hours · the reference lab · the claims processor | Email, plus SMS to the 22 managers | Live. Report anything odd to this number. | Comms lead |
| Within 10 min of a revert | The same full list | Email + SMS | The move did not go ahead. Nothing has changed for you. Monday is normal. | Comms lead |
| 07:00 Mon | 22 clinic managers | SMS | We are on the bridge all day. Here is the number. | Cutover lead |
The two rows that separate an experienced plan from a first one are the reference lab and the claims processor. They are external organisations with their own on-call, their own change freezes and their own opinions about a partner’s system going quiet at 02:00 on a Sunday. Telling them is not courtesy; it is how you avoid an automated integration being disabled at the other end because it looked like a fault.
Reveal the runbook’s time budget, checked against the window (Artifact B)
| Block | Budget | Rehearsed at T-14d | Running total from 02:00 |
|---|---|---|---|
| Freeze and confirm zero sessions | 10 min | 6 min | 02:10 |
| Final log ship and restore | 15 min | 11 min | 02:25 |
| Zero-lag gate | 5 min | 2 min | 02:30 |
| Validation A — 12 queries | 20 min | 14 min | 02:50 |
| Validation B — ImageVault paths | 10 min | 4 min | 03:00 |
| DNS flip + app tier up | 10 min | 7 min | 03:10 |
| Smoke test A (flagship) | 20 min | 18 min | 03:30 |
| Smoke test B (remote clinic) | 10 min | 9 min | 03:40 |
| Go/no-go #2 — decide by 03:55 | 15 min | — | 03:55 |
| Re-enable ClaimsFeed + LabBridge | 5 min | 3 min | 04:00 |
| Writes open | — | — | 04:00 |
| Hypercare watch before declaring | 60 min | — | 05:00 — done |
| Window closes 06:00 — slack remaining | 60 minutes | ||
Read the rehearsed column, not the budget column. Every block came in under budget at rehearsal, which is how you know the budget is honest rather than optimistic. The 74 minutes of accumulated headroom between budget and rehearsal is what absorbs the one thing that always goes differently on the night — and the 60 minutes at the end is what absorbs the second one. A plan whose happy path lands at 05:55 is a plan with no plan.
Two design choices did most of the work. The seed and log shipping ran for fourteen days beforehand, so only a tail log moves on the night — the 1.9 TB copy happened in October, quietly. And the ImageVault flip is a DNS record rather than 1.5 million row updates, which is the difference between a 60-second step and a step that does not fit in the window at all. Almost all cutover time is won in the weeks before the cutover.
Artifact C — the rollback plan
☺ Like you’re 10: Decide now, in daylight, the exact moment after which “let’s just put it back” stops being a thing you’re allowed to say — and write down what you do instead.
Everything above was preparation for this. A rollback plan is not a paragraph saying “we will roll back if necessary”; that is a wish. A rollback plan names a moment, names a person, names a deadline, and describes two completely different procedures either side of that moment.
Define the point of no return, precisely
The point of no return is the first moment at which data exists in the new system and nowhere else. For PIMS-Core that is not the DNS flip, not the app tier coming up, and not the go/no-go — it is 04:00, the minute the database is set READ_WRITE and the first clinical note is written. Before that instant the source has been frozen read-only since 02:00 and the target has taken no user traffic, so there is literally nothing to reconcile. After it, “roll back” stops meaning “undo” and starts meaning “decide what happens to real records.”
This is why the freeze at 02:00 is not an inconvenience to be minimised — it is the mechanism that keeps the whole night reversible. Every minute the source is read-only is a minute in which a mistake costs nothing but time. That is a trade worth making deliberately: you are buying reversibility with downtime, and four hours of Sunday downtime buys you two full hours of it.
Before 04:00 — the clean revert
Rehearsed at T-14d, timed at 12 minutes. Who may call it: the cutover lead, and only the cutover lead. Latest permitted minute: 03:55 — and if go/no-go #2 has not produced a decision by 03:55, the revert runs automatically. The default is safe.
CLEAN REVERT — before 04:00. Rehearsed: 12 minutes.
1. Cutover lead calls it, out loud, on the bridge, with the time. Logged.
2. DNS: pims.brambleside.internal -> on-prem VIP (TTL 60s)
3. DNS: NAS-COLO-01 -> colo NAS (TTL 60s)
4. Source database: READ_ONLY -> READ_WRITE
5. Restart the application service on all 4 on-prem nodes
6. Re-enable ClaimsFeed and LabBridge jobs against the on-prem instance
7. Clinical validator reruns all NINE smoke-test steps -- against the OLD system.
A revert is a change too, and an unverified revert is just a second outage.
8. Comms wave 3-A within 10 minutes, to the full list:
"The move did not go ahead. Nothing has changed for you. Monday is normal."
9. Take down the maintenance page.
DATA STATE AT THIS MOMENT: zero new writes exist anywhere.
The source has been read-only since 02:00; the target took no user traffic.
Nothing to reconcile. This is the entire reason the freeze exists.Step 7 is the one people leave out. A revert puts you back on a system that has been read-only for two hours, with services restarted and DNS changed — three things that can each fail. Verify it with the same nine steps you would have used to accept the new system. Anything less and you have swapped a suspected problem for an unmeasured one.
After 04:00 — there is no rollback, only mitigate-forward
At 04:12 — twelve minutes past the point of no return — the new system holds roughly 40 clinical notes, 6 dispensing records including one controlled drug, and 3 card payments. They came from the emergency hospital, which never closes, and from the out-of-hours triage line. Every one of those clinical notes is a legal record with a seven-year retention obligation attached, and none of them exists anywhere else in the world.
So the plan changes shape entirely:
AFTER THE POINT OF NO RETURN — the order is fixed. Do not improvise it.
STEP 1 — CAPTURE, ALWAYS, BEFORE ANYTHING ELSE.
Run the pre-written delta export. Written and tested at the T-14d
rehearsal -- NOT composed at 04:12 by someone who has been awake
for twenty-two hours. Output to a file, checksummed, held by the DBA.
STEP 2 — CHOOSE, and the choice is the decision owner's, not IT's:
(a) FIX FORWARD -- stay live, vendor on the bridge. Default for
anything that is merely slow or ugly.
(b) DEGRADED MODE -- set the new system READ_ONLY, clinics fall
back to the paper pack delivered at T-3d. Buys unlimited time
with NO new writes accumulating. Default for anything that is
wrong rather than slow.
(c) REVERSE MIGRATION -- only if (a) and (b) have both failed.
This is a project, not a night: transform the delta file,
load it into the old system, and have a clinician verify
every record with a second clinician countersigning.
NEVER: flip DNS back before STEP 1 has completed. Ever. Not once.-- The delta export. Written at the T-14d rehearsal. Tested at the rehearsal.
-- Its existence is a milestone, not an afterthought.
DECLARE @cutover datetime2 = '<< the exact UTC instant writes were opened >>';
SELECT * INTO dbo.delta_ClinicalNote
FROM dbo.ClinicalNote WHERE CreatedUtc >= @cutover;
SELECT * INTO dbo.delta_ControlledDrug
FROM dbo.ControlledDrugRegister WHERE EntryUtc >= @cutover;
SELECT * INTO dbo.delta_InvoiceLine
FROM dbo.InvoiceLine WHERE CreatedUtc >= @cutover;
SELECT * INTO dbo.delta_Appointment
FROM dbo.Appointment WHERE BookedUtc >= @cutover;
-- Then, immediately, the count that tells the decision owner how big
-- the problem is -- BEFORE they are asked to choose (a), (b) or (c):
SELECT 'notes' AS t, COUNT_BIG(*) FROM dbo.delta_ClinicalNote
UNION ALL SELECT 'drugs', COUNT_BIG(*) FROM dbo.delta_ControlledDrug
UNION ALL SELECT 'invoices', COUNT_BIG(*) FROM dbo.delta_InvoiceLine
UNION ALL SELECT 'appts', COUNT_BIG(*) FROM dbo.delta_Appointment;That last query is the most important thing on this page. The decision owner cannot choose between fix-forward and a reverse migration without knowing the size of the delta, and at 04:12 nobody has time to write a query. Forty records is an evening’s careful work for two clinicians. Four thousand is not recoverable by hand at all, and knowing which of those two you are in changes the answer.
The trigger table — what each failure actually means, on each side of 04:00
| What has gone wrong | Before 04:00 | After 04:00 |
|---|---|---|
| Replication lag won’t reach zero | Clean revert. This is exactly why the LSN gate sits at 02:25 and not at 03:40. | Cannot happen — you never opened writes without passing a zero-lag gate. If it somehow has, you have a bug in the gate, not in the cutover. |
| The app tier won’t come up healthy | Clean revert. | Fix forward on the vendor bridge. If not resolved within 30 minutes, degrade to paper. |
| ImageVault studies won’t render | Clean revert — then go and find out why the T-7d read test passed. | Degrade imaging only. Clinics can consult; they just can’t view history. PIMS-Core itself stays live. Do not take down a working practice system to fix a viewer. |
| A reconciliation query is off by rows | Hard stop. Do not proceed under any circumstances. | Correctness fault. Read-only immediately, paper pack, delta export, DBA and vendor on the bridge. This is the one that goes straight to (b). |
| It works, but it’s slow | Clean revert if you are not confident by 03:55. | Fix forward. Slow is survivable for a day and you have a week of hypercare; abandoning a correct system because it is sluggish costs more than it saves. |
| The dispensing-label printers won’t print | Clean revert — a clinic that cannot label a controlled drug cannot dispense one. | Local problem, local fallback: hand-written labels per the paper pack, per the practice’s existing procedure. Do not roll back an entire practice management system for a print queue. |
| A clinician reports a note filed against the wrong patient | Hard stop, clean revert, and the cutover does not get rescheduled until the cause is found. | Immediate degraded mode. A slow system is an inconvenience; a system that mis-files clinical records is a patient-safety incident, and the two are not on the same scale. |
Notice the pattern down the right-hand column: speed problems get fixed forward; correctness problems go to paper immediately. That single distinction is the whole of after-hours decision-making, and it is worth writing at the top of your rollback plan in one line, because at 04:12 nobody is going to read a table. Gizmo’s entire pitch — “we’re nearly there, just push through” — is only ever correct on the speed side of that line, and he will offer it just as loudly on the other side.
Reveal the worked rollback plan (Artifact C)
| Field | The answer |
|---|---|
| Point of no return | 04:00 — the minute the PIMS-Core database is set READ_WRITE and the first clinical note can be written. Timestamped out loud, by name, in the bridge log. |
| Who may call the clean revert | The cutover lead. One person. Not a committee, not the migration lead, not whoever is loudest at 03:50. |
| Latest minute it may be called | 03:55. With a rehearsed 12-minute revert, the old system is verified and live by 04:07 — inside the window with 113 minutes to spare. |
| What happens if nobody decides by 03:55 | The revert runs. Indecision resolves to the safe option, by design, so that “we didn’t want to be the one to say it” cannot become a decision. |
| Who owns the mitigate-forward call | The Head of Clinical Operations, on the bridge from 03:30. Deliberately not from IT: the choice between fix-forward and paper is a clinical-risk judgement wearing a technical costume. |
| Data state before 04:00 | Zero new writes exist anywhere. Source read-only since 02:00, target has taken no user traffic. Nothing to reconcile — this is what the freeze bought. |
| Data state at 04:12 | ~40 clinical notes, 6 dispensing records (one controlled drug), 3 card payments — from the emergency hospital and the out-of-hours line. All legal records. All existing in exactly one place. |
| What happens to those 40 notes | Step 1 is always capture — the pre-written delta export runs before any other action, output checksummed and held by the DBA. Then the decision owner chooses fix-forward, degraded mode, or reverse migration, having been shown the row counts first. If it comes to a reverse migration, each record is re-keyed by a clinician and countersigned by a second one. |
| The forbidden action | Flipping DNS back before the delta export has completed. There is no scenario in which that is the right first move, and it is the move a tired team will reach for. |
| Why 02:00, and not 22:00 on Saturday | Because the size of the delta you might have to hand-carry is a function of the hour you chose. 04:00 on a Sunday is the quietest hour Brambleside has — an emergency hospital and a triage line, and nothing else. The same cutover finishing at 08:00 would leave hundreds of records on the wrong side of the line instead of forty. |
The one line to put at the top of the plan: “Before 04:00 we go back and nobody outside this room ever knows. After 04:00 we capture first, then choose — and correctness problems go to paper immediately, speed problems get fixed forward.”
Take the second-hardest cutover in the estate — BramblesideOnline, with a ≤ 2 hour tolerance, 90 GB of MySQL, and a version jump from 5.7 to 8 — and write just three lines: its point of no return, who may call the revert, and the latest wall-clock minute. Then notice how different the answer is. A public booking site has no freeze that stops the world; customers arrive whenever they like, so the point of no return arrives the moment the first booking is taken on the new stack. Which means the entire rollback strategy has to be something else — a parallel run, or a dual-write, or an accepted tolerance for reconciling a handful of bookings by hand. The point of no return is a property of the system, not of the runbook.
Foxy: Forty-one terabytes and nine months. Why can’t we just start the upload tonight and forget about it?
Pip: I did the sums. Thirty-four days at the fastest we’re allowed to push — and only if the link is ours alone, which it never is. Every one of those days, twenty-two clinics are sharing it with us.
Gizmo: So push harder! It’s a five-hundred megabit circuit, isn’t it? Use the circuit.
Sol: It’s five hundred we’re allowed to be billed for. Above one-fifty it’s burst charges — every month, for a month nobody budgeted. Slowly, now: that’s not more bandwidth, that’s a bigger invoice.
Ellie: So the archive goes by road. One appliance, eighteen days door to door, and not one bit of it touches the link. Then I keep a one-way sync running at under four megabits until the night we flip. The old NAS stays the truth the whole time.
Timmy: And on the night, nothing goes live until five named studies open, twelve queries return the exact numbers I wrote down at two a.m., and a vet nurse has printed a real label on a real printer in a real clinic. Not one of those is optional.
Foxy: And if it’s still not right at four?
Timmy: At three fifty-five we go back and nobody outside the room ever knows. At four twelve it’s a completely different question — forty clinical notes exist in one place on earth, and what you do about them is something you write down in October, not something you invent at four twelve.
Gizmo: …we’re nearly there though. Just push through?
Ellie: That’s the sentence, Foxy. That exact sentence is why we wrote the deadline down two weeks ago and gave it to somebody who isn’t us.
Milestones
☺ Like you’re 10: Tick a box only when the thing actually exists on your page — not because you’ve read about it and it sounds sensible.
Work these in order; each builds on the one before. Progress saves in this browser.
What “done” looks like for Part 4
☺ Like you’re 10: Four things you can check yourself, without anyone marking it.
- Your arithmetic shows why the appliance beats the wire — with every unit conversion visible, a stated goodput assumption, and a crossover you derived rather than remembered. Someone who disagrees with your answer can point at the exact line they disagree with.
- Every dataset has a named validation step and a named signer — including the ones that don’t travel. No row says “the job reported success”, and nothing financial or clinical is signed by one person alone.
- The runbook fits inside four hours with slack — your happy path finishes with at least 45 minutes unspent, every row names an owner and an expected result, and every row has an “if it fails” branch.
- Your rollback plan says what happens to the notes written at 04:12 — an explicit point of no return, a named person allowed to call the revert, a wall-clock deadline with a safe default if nobody decides, and a capture-before-anything-else rule for the other side of the line.
If any of those four is a paragraph of intent rather than a table of specifics, it isn’t done yet. The test is simple and unforgiving: could someone who was not in any of these conversations run this night from your document alone?
Where this goes next
| Page | What it does with Part 4’s artifacts |
|---|---|
| Part 5 — Operate, Optimize & Modernize | Picks up the morning after and asks what all of this costs — including the two things you must refuse to optimize, one of which is the parallel-run capacity that made this cutover survivable. |
| Drill — Size the Data Move | Three harder scenarios of the same arithmetic, including one rigged so an online transfer never converges at all. |
| Drill — Write a Rollback Plan | Three cutovers that have already gone wrong, at three different moments — including one where the rollback itself is what breaks. |
| Move Brambleside — Start Here | The hub: the full estate fact sheet, the five parts, and the afternoon fast path. |
1. Walk the 41 TB conversion out loud — which step is the one people skip, and how wrong does skipping it make you? 2. The appliance takes 18 days and the wire takes 34. Name the second reason the appliance wins, the one that has nothing to do with wall-clock. 3. FileShare’s hot subset is 3.7 TB — three days by bandwidth. Why isn’t bandwidth the constraint, and what does that change about the final sync? 4. What exactly is the point of no return for PIMS-Core, and why is it 04:00 rather than the 03:00 DNS flip? 5. Something goes wrong at 04:12. What is the first action, in every case, before anyone decides anything?
Check your answers
- 41 TB → 41,000 GB → 41,000,000 MB → ×8 = 328,000,000 megabits → ÷150 Mbps = 2,186,667 s → 607.4 h → 25.3 days at a perfect link, or ~34 days at 75% goodput. The skipped step is the ×8: storage is sold in bytes, links in bits per second. Skip it and your estimate is eight times too optimistic — you plan a four-day copy and get a month.
- Link occupancy. The appliance uses zero of the colo circuit; the wire would saturate Brambleside’s entire 150 Mbps allowance for five weeks, competing with 22 clinics the whole time and risking burst charges above the contracted rate. Even below the 18.3 TB crossover, where the wire wins on days, it still spends days of a circuit somebody else needs. Wall-clock is only half the cost of a transfer.
- Because the binding constraint is enumeration, not transfer: a full walk of 1.1 million files with NTFS ACLs takes 3.5 hours, and a timestamp-based sync pays that cost on every pass, just to discover the handful of files that changed. Four hours of window cannot contain a 3.5-hour scan. So the final delta must come from a change journal (the NTFS USN journal, or a DFS-R-style replication group) that reads a list of changes rather than re-deriving one — and the bulk rides the appliance regardless of what the bandwidth math says.
- The point of no return is 04:00, the minute the database goes
READ_WRITEand the first clinical note can be written — it is the first moment data exists in the new system and nowhere else. The 03:00 DNS flip is not it, because DNS is a pointer: changing it back takes 60 seconds and nothing has been written in the meantime. The source has been frozen read-only since 02:00 precisely so that everything up to 04:00 stays reversible with nothing to reconcile. You are buying reversibility with downtime, deliberately. - Capture. Run the pre-written, pre-tested delta export — every row created since 04:00, to a checksummed file held by the DBA — and produce the row counts, before the decision owner is asked to choose between fixing forward, degrading to paper, or a reverse migration. Nobody can weigh those options without knowing whether the delta is 40 records or 4,000. And under no circumstances does DNS get flipped back before that export has completed.
Part 4 turned three decisions into three documents: an arithmetic-backed plan for moving 50.2 terabytes, a runbook a stranger could execute on a Sunday night, and a rollback plan that names the minute after which “put it back” stops being a sentence anyone is allowed to say. Continue to Capstone Part 5 — Operate, Optimize & Modernize, where the bill arrives and you find out what the lift-and-shift instinct really costs. Step back to Part 3 — The Wave Plan if the month-2 seed still feels arbitrary, or to Move Brambleside — Start Here for the whole track. And for the theory behind everything on this page, revisit Data Migration & Data Gravity, Architecture Patterns, Best Practices and Security, Cost & Resilience.