Questions about this dashboard

Everything asked in the September 2 and September 9 reviews, with the answer and where it came from. Written down so the same ground does not get re-covered.

Data compiled September 4, 2026 Traffic counters read August 3, 2026 25 questions

Each answer is marked by what kind of answer it is. Some are measurements, some are decisions that were made, and some are still genuinely open.

Measured Decided Still open

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.

WhatSource
VIPs and applicationsNetScaler configuration parse
Traffic, up/down state, stale flagNitro API script run against the ADCs
Owners, directors, VPsServiceNow, via SnowQL
Change requestsThe 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.

SourceFileFromDatedWhat 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.

#StageWhat happens
1Enrich 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.
2Group 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.
3Add 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.
4Apply corrections Review spreadsheets that owners have marked up are applied, so a corrected name or owner survives the next rebuild instead of being overwritten.
5Add 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.

PopulationApplicationsVIPs
Everything, which is what the page shows9454,086
Production only4701,758
QA only3981,335
Both environments72987
Touching production at all5422,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 addressesCount
In the NetScaler configuration parse6,272
In the ADC usage report6,254
On this dashboard4,086
In the configuration but not on this page2,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 foundAppsOf the 73A second VP means
CMDB, via backend servers47753Usually real
Change request46820Usually 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.