The data
4 questions
Where does all of this come from?
Measured
Four sources, joined into one file. Nothing on the page is typed by hand.
| What | Source |
| VIPs and applications | NetScaler configuration parse |
| Traffic, up/down state, stale flag | Nitro API script run against the ADCs |
| Owners, directors, VPs | ServiceNow, via SnowQL |
| Change requests | The change request database |
Those merge into a single CSV that this page reads. There is no database behind the figures
on screen. The only thing the dashboard creates is the answers people give it, which are kept
separately.
945applications
4,086VIPs
835have a named VP
2,988have to migrate
Every source, and what it gives
Measured
Five inputs. Each one contributes specific columns, and nothing on the page
comes from anywhere else.
| Source | File | From | Dated | What it contributes |
| NetScaler configuration parse |
output_20260729_v7.csv SharePoint |
Ben |
Jul 29 |
One row per vserver: VIP address, port, protocol, backend members, reverse DNS, the
requested application short name, and the change number. This is what defines the
estate. 6,272 distinct addresses. |
| ADC VIP usage report |
adc_vip_usage_report.xlsx |
Daniel |
Aug 18 |
Per-VIP request counters read off 98 devices, up/down state, and the “possibly
stale” flag that becomes the idle-day count. The traffic thresholds are his
too. 6,254 distinct addresses. |
| ServiceNow, queried via SnowQL |
snowql_enriched_changes.csv |
System |
— |
The manager, director and VP chain attached to each change record. Two batches: one
keyed from change numbers, one from the application list. |
| CMDB backend server lookup |
cmdb_backend_owners_full.csv |
System |
— |
Business owner for the servers sitting behind a VIP. Used because VIPs
themselves are not CMDB records — 0 of 16 matched when that was tested. |
| Change request database |
change_actual_dates.csv |
Jason |
— |
Change numbers per application, and the real completion dates used to tell a planned
change from an executed one. |
Neither source export is committed anywhere. Both carry internal hostnames,
vserver names and VIP addresses, so they stay local and only the derived CSV is published.
Two sources, kept separate on purpose
Ben’s exports and Daniel’s exports live in different directories and are never
mixed, so the provenance of any row can always be traced back to one of them.
How it is put together
Measured
Five stages, run in order. Each writes a file the next one reads, so any
figure can be traced back a stage at a time.
| # | Stage | What happens |
| 1 | Enrich the changes |
Change numbers from the change database are looked up in ServiceNow, pulling the
manager, director and VP chain, plus the real completion date for each. |
| 2 | Group VIPs into applications |
Ben’s per-VIP rows are grouped into applications and the owner is attached from
the change record. This is where an application can pick up more than one
VP — see the questions below. |
| 3 | Add the CMDB-owned applications |
Applications with no usable change record get an owner from the business owner of the
servers behind their VIPs. Roughly half the estate arrives this way. |
| 4 | Apply corrections |
Review spreadsheets that owners have marked up are applied, so a corrected name or
owner survives the next rebuild instead of being overwritten. |
| 5 | Add traffic and scope |
Daniel’s report adds the traffic tiers and, separately, the migration scope
columns. These are different questions and are computed independently. |
The result is copied to the dashboard as a single CSV. The page does no joining and
no lookups of its own; it reads that one file and renders it.
Traffic and scope are computed separately, on purpose
Traffic grades a VIP by how many requests it served. Scope asks whether it has to migrate,
which depends on state: up, or standing by for something that is up.
Conflating them was a real error on an earlier version of this page. 51% of the
VIPs in the lowest traffic tier are actually up, so reading the traffic chart as
scope overstates what can be dropped by about half of its own largest segment.
Is any of it live?
Measured
No. Every figure is a snapshot, and the page says which day.
Configurations and owners were compiled September 4. The traffic counters
were read August 3. Those are shown separately on purpose, because they are
different ages and the traffic reading is the older of the two.
Answers people give are the exception. Those save the moment they are clicked.
The traffic numbers
5 questions
How is “no requests in X days” worked out?
DecidedAsked by Jason · Sep 9
From the request counters on each load balancer, which reset when the device
reboots. So it means “in the window we can see”, never “ever”.
Per-VIP request counters are read through the Nitro API. Those counters start from zero at
the last reboot or counter reset, so the figure is bounded by however long that device has been
up. Across the estate those windows run from 26 to 398 days.
That is why the page says 40+ days rather than 40 days. The plus is
load-bearing.
Decided September 9
Show the number, and state what it is measured from. Removing it was explicitly
rejected on the grounds that less data is not a better decision.
The wording agreed: this is what we know, these times are based on the last reboot, please
do your own research, but here is what we have.
So the day count can be wrong?
DecidedAsked by Jason · Sep 9
It can mislead, and the dangerous direction is a VIP that looks dead and is
actually up.
A VIP that has served no requests in the visible window can still be up and in
service. Low traffic is not the same fact as down, and the migration rule keys off
state, not traffic. Someone reading a long idle count and decommissioning on that basis alone
would be making a mistake the page used to invite.
What the row used to show: the idle-day count with no up or down state
beside it. State only appeared once the VIP list was opened, so a row could read
4 with no requests in 264+ days while all four were up and in service.
The decision, and what changed. The state now travels with the count in the
same sentence, so the two cannot be read apart: 50 with no requests in 264+ days, 30 still
up. Where none are up the row says so outright rather than staying silent, because silence
there reads as unknown when it is actually the reassuring answer.
This was not a rare case. Of the 2,532 VIPs with no requests in the visible window,
1,325, or 52%, are up, across 415 applications. The misleading reading was the
common one.
The chart subtitle now also states what the totals are measured from: each counter restarts
when its load balancer reboots, so they cover the last 26 to 398 days depending on the device,
and it says it is worth checking before acting. The position agreed was to disclose the limit
rather than remove the number.
On responsibility, the position agreed was that the dashboard gives a starting point, the
manager delegates the detail to engineers who know the application, and the call is theirs.
What if the data is wrong and mine is in use?
Still openAsked by Jason · Sep 9
There is no way to tell us yet. This one is genuinely not built.
It is a different question from answering no. “I can show it is up” is feedback on
the evidence rather than a migration decision, so it cannot be recorded as either. Answering no
would put the wrong thing on the record: the application is not being declined, the figure
behind it is being disputed.
The position agreed was that if the page says something has not been used and the owner can
show otherwise, they correct us and we act on the correction. That needs somewhere for the
correction to go, which is why it waits on the database being hosted rather than sitting in one
person’s local copy.
Are two VIPs both showing 100k+ comparable?
Measured
No, and this is the honest weakness in the traffic bands.
The figure is a cumulative total since that device’s counter last reset. One VIP may
have served 100,000 requests in three weeks and another over thirteen months, and they look
identical on the page.
Requests per day would make them comparable. It barely moves the headline but it
reduces migration scope by 128 VIPs, so it needs a decision rather than a
quiet change.
What is a request? Can we see the URLs?
MeasuredAsked by Kyla and Claudine · Sep 2
A hit counted by the load balancer. Each VIP shows its DNS name, which is not
the same as the URL an application team would quote.
This was measured before being promised: all 4,086 VIPs have reverse DNS, and 3,890
of them, 95%, are real names such as rdc5085mhe.homedepot.com. The other
196 are auto-generated load balancer interface names, so those fall back to showing the
address.
It is called a name rather than a URL deliberately. This is reverse DNS on the VIP. The URL
that was originally requested lives in a different field on the change record, with roughly 64%
coverage.
Scope
4 questions
Where does 2,988 come from?
MeasuredAsked by Claudine · Sep 2
It counts VIPs that are up or on standby. It is a state rule, not a traffic
rule.
73% of the estate. This corrected an earlier version of the page that graded VIPs by traffic
and implied the quiet ones could be dropped. Around 2,200 VIPs with almost no traffic
are nonetheless up, and anything up migrates.
Traffic is on the page to help owners decide what to decommission. It does not decide
scope.
Is this production, or QA too?
Asked by Brad · Sep 9
Measured
Both. Every figure on the dashboard includes QA, so it cannot be compared
against a production-only number without splitting it first.
| Population | Applications | VIPs |
| Everything, which is what the page shows | 945 | 4,086 |
| Production only | 470 | 1,758 |
| QA only | 398 | 1,335 |
| Both environments | 72 | 987 |
| Touching production at all | 542 | 2,745 |
If you are comparing against a production-only figure, the number to use is 542
applications and 2,745 VIPs, not 945 and 4,086. The 398 QA-only applications disappear
entirely from a production count, which is large enough to look like a discrepancy on its own.
Daniel’s wider estate splits about the same way: of 6,254 addressable VIPs across 98
devices, 3,436 are production and 2,817 are QA.
Why doesn’t this match another count of the estate?
Asked by Brad · Sep 9
Measured
Three reasons, and they stack: this page counts IP addresses rather than
vserver rows, it includes QA, and it only covers VIPs that could be tied to an application.
1. A VIP here means one distinct IP address. Elsewhere it often means one
vserver:port row, and there are several of those per address. Comparing the two directly
overstates the gap by roughly four times.
2. This includes QA. See the question above.
3. Coverage. This is the real gap and it is measurable:
| Distinct VIP addresses | Count |
| In the NetScaler configuration parse | 6,272 |
| In the ADC usage report | 6,254 |
| On this dashboard | 4,086 |
| In the configuration but not on this page | 2,186 |
Those 2,186 are not missing from the source data. They are dropped here, because
building an application row needs an application short name and none of them has
one.
They are not recoverable, and this was tried
An earlier version of this answer said most of them could be recovered. That was wrong, and
it is worth saying why rather than quietly deleting it.
1,916 of the 2,186 do have backend servers listed, and attributing an
application from its backend servers is a route that already works: it is how 477 of the 945
applications on this page got their owner. So the expectation was that most of the 1,916 would
follow.
They do not. All 1,850 distinct backend addresses behind them were looked
up in CMDB. 39 came back with an owner, 2.1%, which attributes
16 VIPs. Not the sixteen hundred the earlier wording implied.
The mistake was assuming that having a backend server meant that server is in CMDB. Only the
first half had been measured. The gap is CMDB coverage of these particular servers,
not anything this page is doing wrong, and no amount of re-running the lookup changes it.
Of the rest, 249 have nothing to attribute them with and 21 carry only a change number. Just
188 of the 1,916 carry a change number either, so the change-request route does not close this
gap.
There is no third route. Application and service names were never recorded
against load balancer requests, so there is no source to go and ask for them. The only place an
application is tied to its VIPs is the service named on the change record, and most of these do
not have one. These addresses can be listed, but they cannot be attributed.
Why is there no migration progress bar?
Measured
Because migration has not started, and a progress figure implying otherwise was
already wrong once.
An earlier chart read 42.8% migrated. It was counting completed change requests, most of
them years old and unrelated to this programme. There is essentially nothing on the F5 yet, so
the honest number is zero and the chart was removed rather than relabelled.
“Shared with other teams”
4 questions
What does “493 shared with other teams” mean?
MeasuredAsked by Ben and Kyla · Sep 9
It was the total VIP count of the 15 applications on that card which have
more than one VP named against them. The wording was wrong, and the card now says
“15 of these applications are also listed under another VP” instead.
It does not mean two applications share a VIP. That happens zero times out
of 4,086. What happens is that one application appears on more than one VP’s card, so the
same VIPs get counted on each of them.
73applications with more than one VP
914VIPs on them, counted once
2,439what you get adding up every card
0VIPs in two applications
Sixty of the 73 have two VPs, eight have three, three have four, and two have five.
Where the wording came from
The card flags any application with more than one VP named and adds its whole VIP
count to each of those VPs. So 493 is not 493 shared VIPs, it is the full size of 15
applications that appear in more than one place.
The word “shared” assumed those applications were jointly owned. It is being
replaced, because it also hides the distinction in the next question: two
genuine business owners and a change-assignment artifact currently read identically. Better
wording is along the lines of 15 applications here are also listed under another
VP, with the reason shown on the row.
Why is one application under two VPs?
MeasuredAsked by Brad · Sep 9
Two different mechanisms, and which one applies decides whether the second VP
is meaningful.
| How the owner was found | Apps | Of the 73 | A second VP means |
| CMDB, via backend servers | 477 | 53 | Usually real |
| Change request | 468 | 20 | Usually an artifact |
The CMDB path, 53 of the 73. VIPs are not tracked in CMDB at all, which was
tested: 0 of 16 matched. So the lookup goes to the backend server IPs behind each VIP and finds
a server record with a business owner. Those backend servers can genuinely belong to two
different organisations, and when they do, two VPs is the correct answer.
The change-request path, 20 of the 73. The VP comes from the change record,
and the application collects every VP across every change that touched any of its VIPs. Two
changes assigned to two groups produces two VPs. Nothing picks a winner.
Is it what is on the change request, or the CMDB object?
MeasuredAsked by Brad · Sep 9
Both, split almost evenly. 468 applications get their owner from change
requests, 477 from CMDB.
For the change-request half, the field used is assigned_vp: the VP over the
group the change was assigned to. Who raised it,
requested_by_vp, is only the fallback when there is no assignment.
Why that distinction matters
Those two fields disagree on 55% of changes, 2,316 of 4,180. So which one
is used materially changes who owns what across half the estate.
It also explains a pattern worth knowing about. Load balancer work is assigned to the
network team, so that team’s VP accumulates applications they do not own.
Being assigned a change is not ownership.
There is also at least one VP who appears on the multi-VP list far more often than the
assignment data explains, arriving instead through the requested_by_vp fallback.
That is worth a closer look before anyone relies on those rows.
Shouldn’t there only be one VP?
Still openAsked by Brad · Sep 9
Yes for the change-request cases. No for the CMDB ones, where two owners is the
true answer.
Collapsing the 20 change-request cases to a single VP is right, because being assigned a
change is not ownership. But the 53 CMDB cases reflect backend servers that really do have
different business owners, and forcing those to one would be inventing an answer.
Two further findings on this:
- Abandoned changes still confer ownership. Nothing filters on change
state. One application takes both its VPs from two changes that were both abandoned, so
neither was ever executed and it still produced two owners.
- The path should be visible on the row. “From the change
request” and “from the server behind the VIP” deserve different amounts of
trust, and today they look identical.
Answering, and what happens next
8 questions
Does it save, or does it just change the page?
DecidedAsked by Grant · Sep 9
It saves to a real database as you click. Today that database is running
locally, not centrally.
Answers are written immediately to an append-only store. There is no submit button on
purpose; every click is recorded when it happens.
The code already runs against Cloud SQL for Postgres using the same schema, so moving it to
GCP is a configuration change rather than a rewrite. That move is waiting on project access.
Where does it live afterwards?
DecidedAsked by Brad and Grant · Sep 9
The record is kept indefinitely. The running database is not.
Settled on September 9: retire the running instance once migration is done, since keeping it
up is not worth the cost, but keep an accessible copy of the record. The reason is that someone
will eventually ask why a VIP was not moved, and the answer should be a record rather than a
recollection.
The store is append-only, which serves this exactly. Nothing is ever
updated or deleted, and changing your mind adds a row. So the history of who said what, and
when, is the evidence.
What happens when two people disagree?
Still openAsked by Ben · Sep 9
Both answers are kept and the row is flagged. Nothing and nobody resolves it
yet.
Keeping both is the whole reason for a database rather than collected spreadsheets. A
spreadsheet merge takes whichever file was processed last and drops the other answer without
telling anyone, and a silently discarded “do not migrate” is the expensive
direction of that mistake.
So disagreement is reported rather than decided, and that part works. What is
missing is who resolves it. A flag is not a process.
A useful shortcut
For the change-request cases above, the likeliest explanation for a disagreement is not a
real dispute. It is that one of the two does not own the application and is
only listed because their team worked a change.
So resolution should start with “who actually owns this” rather than
adjudicating migrate against do not migrate. The “not mine” button already
collects that answer. Nothing reads it yet.
Who is allowed to answer?
Decided
Today anyone, because the name is typed in. Identity-Aware Proxy fixes that on
deployment.
The reviewer name is currently self-declared, which makes it a claim rather than a fact.
This page and the dashboard both say so.
IAP federates against the existing homedepot.com Google identity, which is itself federated
to Azure AD, so it introduces no new identity provider. The name then comes from the login
rather than from a text box.
That also removes a real problem: a name typed three different ways currently counts as
three different reviewers, so one person can appear to disagree with themselves.
Does answering yes mean it migrates tomorrow?
DecidedAsked by Brad · Sep 9
No. Yes means ready. Answers are batched so configuration can be staged.
Once someone has been through every VIP, a ready to migrate link will hand
them to the Galaxy self-service portal, possibly pre-filled with the application ID. Completing
the list is what unlocks it.
That link is deliberately not shipped yet. If someone answers everything and there is
nothing to click, they will not come back.
What is “not mine” for?
DecidedAsked by Kyla · Sep 2
For when an application is against your name and it is not yours. It answers
ownership, not migration.
That is why it sits under the application name rather than among All, Some and None. It is a
different question. It dims the row and is undoable, because vanishing on click leaves no way
back from a mis-click.
Given what the questions above show about how owners are derived, this matters more than it
first appeared.
I said “some”. What happens when I come back?
DecidedAsked by Grant · Sep 9
Nothing to come back for. An application moves all at once.
If you selected a subset, that subset moves as one batch for that application. There is no
partial-then-partial-again flow, so no per-VIP “already migrated” state is
needed.
The reason the VIP picker exists at all is cleanup: teams can move what they need and leave
the rest behind rather than carrying dead configuration to the F5.
What actually reads the answers?
Still openAsked by Brad · Sep 9
The NetBox modelling work, by API lookup. Specified on September 9, not built
yet.
When configurations are extracted from the Citrix devices and modelled in NetBox, that
process does a cross-reference lookup against this database to see which VIPs are in scope for
the application. If the answer is all, all of them are taken. If it is some, only that subset
is taken.
So the work is a read API: given an application, return all, some or none, plus the VIP
list.
This was the missing piece. Until it exists, someone can review every
application and it produces no report, no batch, and does not move the 2,988. It is also what
would route a “not mine” to whoever chases down the real owner.