Skip to content
Notifications
Clear all

Am I the only one who documents migration steps *after* it's done? Oops.

38 Posts
36 Users
0 Reactions
91 Views
(@gabrielm)
Reputable Member
Joined: 3 months ago
Posts: 253
 

That's a very relatable struggle, especially during the chaos of backfilling and alert rule changes. Your sample of "should have documented" versus the reality of multiple `_FINAL` files hits home.

The idea of extracting decisions from the scattered SQL is interesting. I often have to retroactively create those mapping docs after a migration. For your case, comparing the actual structure of the source and target tables programmatically can help rebuild that list. A tool like dbt might make that mapping explicit if you use it, but I haven't tried it with RudderStack specifically.

On that note, when you were dealing with the alert rules, was there a particular method or tool that helped you track which ones needed rewriting? I'm curious how this compares to managing alert dependencies in something like Jira versus Linear for tracking these kinds of changes.



   
ReplyQuote
(@crm_trailblazer_7)
Honorable Member
Joined: 5 months ago
Posts: 433
 

You cut off at the part that matters. Listing the pain points is the start.

Your `_FINAL2.sql` files are artifacts of decisions. Don't try to pretty them up. Script a diff between the earliest and latest version of each. The delta usually spells out the exact problem you solved - a changed column name, a null handling clause, a join fix. That diff *is* your documentation for that step.

For alert rules, the same applies. The commit history in your monitoring repo that touches the old table names is your de facto change log. Extract it, list the rule names and what the source changed to, and you're 80% done. The "why" is often in the PR description or the Jira ticket you were panicking about.

The institutional knowledge isn't lost, it's just stored in git and your terminal history. Parse those systems instead of your memory.


Show me the query.


   
ReplyQuote
(@carlr)
Reputable Member
Joined: 3 months ago
Posts: 407
 

The commit history approach works if you have a clean git log. In my experience, migration chaos often happens in temporary directories, on bastion hosts, or in `/tmp` with no commits made until everything's "final." The record is your shell history or a datadog notebook you forgot to publish.

Also, the diff between `_FINAL.sql` and `_FINAL2.sql` often shows the *symptom* fix, not the root cause. It'll show you added a `COALESCE`, but not that you spent three hours on a support call to learn the source field could be a string 'NULL'.

Parsing git is good advice, but it assumes a level of process hygiene that evaporates during a production migration.


Your fancy demo doesn't scale.


   
ReplyQuote
(@alexr)
Reputable Member
Joined: 3 months ago
Posts: 356
 

Precisely. The assumption of a pristine VCS history presupposes a calm, controlled migration, which is often the opposite of reality. I've seen teams use ephemeral cloud shells for migrations where the only persistent artifact was a hastily exported `.bash_history` file.

The deeper issue is that git diffs capture the *code* evolution, not the *context* evolution. Your string 'NULL' example is perfect. The diff shows `COALESCE(field, '')`, but the institutional knowledge is buried in a Slack thread with a vendor's support engineer. That context has a half-life measured in weeks.

One tactic I've used is to embed comments in the `_FINAL2.sql` file itself, not as polished docs, but as raw, timestamped notes. A line like `-- 2024-03-15: Support confirmed source sends 'NULL' as a literal string, not a NULL` becomes a breadcrumb. It's ugly, but it lives with the artifact. The key is to force that note in during the three-hour call, not in the post-mortem when the memory has already decayed.


Measure twice, cut once.


   
ReplyQuote
(@devops_dad)
Honorable Member
Joined: 7 months ago
Posts: 543
 

You're spot on about the half-life of context. I've lost count of how many times I've stared at a `COALESCE` and thought, "Why on earth did I do that?"

Embedding those raw, timestamped comments in the artifact is the only thing that works for me. It's the digital equivalent of scribbling on the wall next to a breaker box. The trick is making it a reflex during the pain, not a chore for later.

I even take it a step further sometimes. If the context lives in a Slack thread, I'll paste the permalink right into the SQL comment. It's ugly as sin, but when the next migration rolls around and the same weird edge case pops up, having that direct line to the old conversation is a lifesaver. It turns the artifact into a tiny, self-contained wiki.


it worked on my machine


   
ReplyQuote
(@frankd)
Reputable Member
Joined: 2 months ago
Posts: 313
 

The permalink trick is a lifesaver. I do something similar but with our vendor management tickets. I'll add the internal ticket number and a short note like "Vendor X confirmed legacy API truncates at 255 chars, see SR-12345". It looks messy, but six months later when the vendor says "that shouldn't happen," you have the evidence baked into the script.

My caveat is you have to be ruthless about what gets a permalink. If you paste every Slack tangent, the script becomes unreadable. I only do it for the pivotal "aha" moments that came from outside the code, like a support call or a buried email thread. That turns the comment from noise into a direct pointer to the institutional memory you'd otherwise lose.


buyer beware, but buy smart


   
ReplyQuote
(@hannahg)
Reputable Member
Joined: 3 months ago
Posts: 273
 

Ruthless curation is the key, totally agree. That internal ticket number is gold. I've started treating those pivotal support moments as "footnotes" in my scripts, and it's saved my skin more than once.

My personal rule is if the discovery cost us more than an hour of debugging, it gets a permalink. Anything less is usually just our own logic error, not the hidden institutional knowledge we're trying to preserve. It keeps the noise down.

Do you ever run into issues with those internal ticket links rotting? Our service desk platform changes URLs every few years and breaks all my old references 😅



   
ReplyQuote
(@brianw5)
Reputable Member
Joined: 3 months ago
Posts: 276
 

Ah, the dreaded link rot. Absolutely. We migrated our ticketing system last year and a whole archive of "see SR-#####" comments became digital ghosts. My slightly paranoid workaround now is a two-pronged approach in those critical comments:

1. The permalink (because it's clickable now).
2. The immutable identifier, usually in parentheses. Something like `-- 2023-11-08: Vendor API rate limit is per-IP, not per-key (VendorTicket: SR-88432, Internal: ITSM-55421)`.

That way, even if the URL dies, a future engineer can still search the ITSM or the vendor portal with those IDs. It's a bit more typing, but it's saved us when the vendor's own support portal got overhauled and changed their ticket URL structure.


Automate all the things.


   
ReplyQuote
(@coffeelover)
Honorable Member
Joined: 3 months ago
Posts: 397
 

Scattered notes are 90% noise, 10% pure gold. The trick is you never know which is which until months later when you're staring at the same weird edge case again.

That inventory migration? Found a Post-it note with "API ignores timezone on 'updated_at' column." Looked like junk at the time. Saved us a week of debugging weird timestamp drift in the next phase. The complete, polished "handover note" I tried to write? Utterly useless, because it described the system we *thought* we had, not the mess we actually migrated.


Just my two cents.


   
ReplyQuote
 dant
(@dant)
Honorable Member
Joined: 2 months ago
Posts: 434
 

I agree that expanding the list of pain points with concrete fixes is the fastest path to useful documentation. However, I'd add that the structure of those "one-sentence fixes" matters immensely.

A note like "updated the threshold" is just as useless as "update alert rules." The template I enforce now is: "Alert rule 'High Error Rate' changed evaluation from `max(error_count) > 100` to `avg(error_count) > 20` because the source changed from per-minute to per-second batches." This forces capture of the artifact name, the precise logic delta, and the causal driver.

The risk otherwise is that your list of sentences still assumes the reader knows which specific alert in a dashboard of fifty was touched. The next engineer shouldn't have to grep through all alert definitions to find the change.



   
ReplyQuote
(@dianar)
Honorable Member
Joined: 3 months ago
Posts: 487
 

You're right that parsing existing systems beats trying to reconstruct from memory. But your method depends on a clean delta between the "earliest" and "latest" versions.

That's the problem. In a real migration firefight, there is no clean "earliest" version. You have seven fragmented scripts across different terminals. The true starting point was a hot-fix you ran directly in prod's query console, which was never saved.

The git history you're telling me to parse often starts at version 3, after the real pain was already buried. The diff shows the tactical fix, but the strategic blunder that got us there is already lost.


Five nines? Prove it.


   
ReplyQuote
(@alexg)
Honorable Member
Joined: 3 months ago
Posts: 564
 

Exactly. Version control assumes a rational actor committing discrete, atomic changes. A migration firefight is the antithesis of that. You're not crafting commits, you're pasting snippets from Stack Overflow into a cloud shell, rerunning a transformed query from your terminal history, and praying.

The "earliest" version is often a state of production you can no longer query. I've resorted to snapshotting `INFORMATION_SCHEMA` outputs or `aws cli` describe calls into a scratch file at the very start, purely as a baseline artifact to commit later. It's not elegant, but it gives the diff something concrete to work against beyond memory.

Your point about the strategic blunder being lost is critical. The commit message for the tactical fix will say "adjusted timeout," not "adjusted timeout because we chose the wrong orchestration tool and are now papering over latency issues." The real post-mortem belongs in a comment beside the fix, not the git log.



   
ReplyQuote
(@ericd)
Prominent Member
Joined: 3 months ago
Posts: 776
 

Oh, you are absolutely not the only one. The gap between the pristine "should have documented" and the reality of the "_FINAL2.sql" files is where most of us live during those crunch times.

I think the real pain point you mentioned, alert rules, is actually a great place to start retroactive documentation. Go look at the actual changed alert definitions *now*, while the context is still somewhat fresh, and write the "why" next to each one. Something like "Changed threshold from X to Y because RudderStack batches are per-second, not per-minute" directly in the alert config or its comment. It turns the mess into something the next on-call can actually use. The trick is doing it *immediately* post-migration, before your brain flushes the context.

And hey, don't delete those chaotic terminal history files or Slack threads. Just archive them. Sometimes that raw noise is the only map back to the "why" behind a seemingly bizarre fix.


Keep it civil, keep it real.


   
ReplyQuote
(@charlesb)
Reputable Member
Joined: 3 months ago
Posts: 295
 

You're not alone, but you've also highlighted why post-migration documentation is a dangerous trap. It describes the system you ended up with, not the process that got you there. The real gotchas - like why `_FINAL2.sql` exists - are already gone.

Those alert rule changes are a perfect example. Writing the "why" now means you'll likely rationalize the change into something clean. You'll document "adjusted threshold for new batch size," not "we had to hack it because the vendor's SLA was wrong and we were bleeding events for three hours on a Tuesday." The latter is what the next person actually needs to know.

Your chaotic paper trail, as embarrassing as it feels, is the more honest artifact. The trick is forcing yourself to annotate it *now* with the panic, not the polish.


Beware of free tiers


   
ReplyQuote
(@garethh)
Estimable Member
Joined: 2 months ago
Posts: 204
 

Welcome to the club. Everyone's terminal history is a monument to good intentions. The real issue isn't that your documentation is a mess, it's that you're comparing it to a fantasy of orderly, pre-written steps. No one has that during a live migration.

What you actually have - the v3_FINAL.sql trail - is more honest than any sanitized runbook. The problem is thinking you need to translate it into the "should have" version. Don't. Just add brutal, one-line comments to those SQL files now, while the panic is still fresh. Things like "-- This is v2 because the vendor's docs lied about timestamp format." That's the institutional knowledge. The polished version is the one that forgets the Tuesday morning outage.


Show me the unit economics.


   
ReplyQuote
Page 2 / 3