If the criteria above apply to your upgrade (see Summary at the top), the upgrade resets part of the Monitor database schema, and two kinds of history are affected:
The upgrade clears the data in the enhanced resource-utilization columns and the newer raw resource-utilization and session-metrics tables; both start collecting fresh afterward.
The Session Score table SessionPerformanceSummary is recreated empty during the upgrade and starts collecting fresh afterward.
Run this toolkit only if those criteria apply and you want to retain that historical data (for example, the historical/trend resource charts and the Session Score history charts in Director) across the upgrade.
If the criteria don't apply, or you don't need that history, you can skip the toolkit entirely — the upgrade works fine without it.
This is optional. It is not a replacement for a full database backup. Always take a normal full SQL Server backup before any upgrade.
| Data | What it is | How impotant | Preserved? |
| Resource-utilization summary history | The aggregated, long-retention data behind Director's historical resource-utilization trend charts | High — not automatically rebuilt after the upgrade | Yes |
| Session Score summary history | The Session Score for each session, one value per 30-minute interval, plus its component sub-scores (CPU, RAM, Disk I/O, logon duration, protocol latency, input delay), behind Director's Session Score history charts | High — not automatically rebuilt after the upgrade | Yes |
| Recent raw resource-utilization detail | The most recent days of raw machine resource samples | Low — re-collected automatically; short retention | Yes (see note below) |
| Recent raw session metrics | The most recent days of raw session network/protocol samples | Low — re-collected automatically; short retention | Yes (see note below) |
Other Monitor data that the upgrade may clear is not backed up because it is either never populated, recomputed automatically, or refreshed within minutes of the service restarting.
Note on the raw detail tables: raw resource/session data is groomed (deleted) after roughly 3 days by design. Restoring it only gives you continuity for the most recent day or two immediately after the upgrade; grooming then removes it normally. The summary histories are the durable benefit. If you only care about long-term history, you can back up the summaries alone (see -Dataset RUS, SPS below).
Note on Session Score retention: SessionPerformanceSummary holds up to ~7 days of history, so older rows are groomed out as they age. Restoring it re-establishes the pre-upgrade history that still falls within the ~7-day window
Backup copies the selected data into a separate database on the same SQL Server (CitrixMonitorUpgradeBackup). Because it's a separate database, the upgrade never touches it.
Restore puts the data back additively — it only fills values that are missing and only inserts rows that aren't already there. It never overwrites or deletes anything collected after the upgrade.
Verify reports whether everything came back. It makes no changes to your Monitor data — it writes only a status row to the toolkit's own log table in the side database (use -DryRun for a fully read-only verify).
Everything is processed in small batches with checkpoints, so it is resumable (safe to stop and re-run) and online-safe (no table locks, no index rebuilds, no downtime required).
The toolkit reads from four MonitorData tables in your Monitor database, copies them to the side database, and writes them back on restore. It touches no other tables and makes no schema changes.
| Dataset | Source table | Restore operation | Match key |
| RUS | MonitorData.ResourceUtilizationSummary |
UPDATE (fill 13 NULL columns) | PK (MachineId, Granularity, SummaryDate) |
| RUV2 | MonitorData.ResourceUtilizationV2 |
INSERT missing rows | unique (MachineId, CollectedDate) |
| SMV3 | MonitorData.SessionMetricsV3 |
INSERT missing rows | (SessionId, CollectedDate) |
| SPS | MonitorData.SessionPerformanceSummary |
INSERT missing rows | PK (SessionKey, SummaryDate, CollectedDay) |
Columns:
RUS — only these 13 columns are backed up and restored (the row already exists; the upgrade only NULLs these columns):
P95PercentCpu, P95UsedMemory, AvgDiskLatency, AvgDiskIops,
AvgCPURelativeFrequencyPercent, AvgIdlenessPercent, AvgRAMUsagePercent,
AvgNetUtilizationPercent, AvgPagefileUsagePercent, AvgPercentGPU,
AvgDiskUsagePercent, AvgProfileDiskUsagePercent, AvgLoadIndexPercent
RUV2 — full row (the table is emptied by the upgrade, so all columns are restored):
CollectedDate, PercentCpu, UsedMemory, TotalMemory, SessionCount, CreatedDate,
ModifiedDate, MachineId, DesktopGroupId, AvgIcaRttInMs, DiskLatency, DiskIops,
CPURelativeFrequencyPercent, IdlenessPercent, RAMUsagePercent, NetUtilizationPercent,
PagefileUsagePercent, PercentGPU, DiskUsagePercent, ProfileDiskUsagePercent,
LoadIndexPercent, CollectedDay
SMV3 — full row except the identity Id (a fresh Id is assigned on insert; Id is an internal surrogate, not a key):
SessionId, CollectedDate, IcaRttMS, IcaLatency, ClientL7Latency, ServerL7Latency,
ConnectionState, InputBandwidthUsed, InputBandwidthAvailable, OutputBandwidthUsed,
OutputBandwidthAvailable, Fps, InputFps, OutputFps, ClientPacketRetransmit,
ServerPacketRetransmit, WanLatency, DcLatency, ClientSideFastRTO, ServerSideFastRTO,
ClientZeroWinSize, ServerZeroWinSize, CreatedDate, ModifiedDate, CollectedDay
SPS — full row (the table is recreated empty by the upgrade, so all columns are restored):
SessionKey, SummaryDate, CreatedDate, CollectedDay, SessionScore,
CPUUsageScore, RAMScore, DiskIOScore, LogonDurationScore,
ProtocolLatencyScore, InputDelayScore
COALESCE(live_value, backup_value) only where the live value is still NULL and the backup has a value. A non-NULL live value is never changed.(MachineId, CollectedDate) is not already present; within each batch the source is de-duplicated first, so a single statement never attempts two rows for the same unique key.(SessionId, CollectedDate) is not already present; Id is left to the table's identity. Because (SessionId, CollectedDate) is not a unique key, if two genuinely distinct rows share that pair, only one is restored. This does not affect the trend charts, and Verify reports both the total backup-row count and the distinct-key count, so any such collapse is visible.(SessionKey, SummaryDate, CollectedDay) is not already present; the source is de-duplicated per batch first.Foreign-key note: The three tables the toolkit inserts rows into each reference a parent row: SessionPerformanceSummary and SessionMetricsV3 reference a Session, and ResourceUtilizationV2 references a Machine. On restore, the toolkit inserts a row only if its parent still exists in the live database. If the parent machine or session was removed or groomed after the upgrade, that row is skipped instead of failing the whole batch. (For ResourceUtilizationV2, a row whose delivery group was removed is still restored, just with its delivery-group reference left blank.) Verify accounts for these skips: for Session Score it reports them separately as a missingNoParentSession count, and for ResourceUtilizationV2 and SessionMetricsV3 it includes them in the reported missing total.
No DELETE, TRUNCATE, DROP, or schema change on any Monitor table.
No overwrite of a non-NULL live value (RUS) and no duplicate rows (RUV2/SMV3/SPS).
No index disabling/rebuilding and no table locks. The only optional storage work happens when you pass -CompressColumnstore: an online row-group compaction of the three columnstore tables (RUV2, SMV3, SPS), plus an UPDATE STATISTICS refresh on all four tables.
Touches only the four tables above plus the dedicated side database it creates.
This toolkit uses the same separation-of-duties model as Citrix's scripted database setup: a database administrator (DBA) performs the one-time, privileged database creation, and routine use needs only normal read/write rights. Choose whichever model fits your organization.
Option 1 — the DBA performs every step.
The DBA (or any login holding the rights in the table below) runs all operations: create the side database, back up before the upgrade, restore after it, and verify. Nothing is delegated to the Citrix administrator. Best for sites where all database operations are exclusively DBA-controlled.
Option 2 — the DBA sets up once; the Citrix administrator runs the rest (recommended).
The DBA runs only the one-time privileged step: create the side database and grant the Citrix administrator's login the rights below. The Citrix administrator then runs backup / restore / verify.
| Operation | Required SQL role |
Create the side database (01_Create-BackupDatabase.sql) |
server dbcreator (or sysadmin); becomes db_owner of the new database |
| Grant the Citrix administrator's login (Option 2, one-time) | securityadmin/sysadmin + db_owner on both databases |
Pre-flight check (00_Validate-Source.ps1) |
Monitor DB db_datareader + VIEW DATABASE STATE (for the row-count estimate; without it the table/column checks still work and the estimate is skipped) |
| Backup | side DB db_owner; Monitor DB db_datareader |
| Restore | side DB db_datareader + db_datawriter; Monitor DB db_datareader + db_datawriter |
Restore with -CompressColumnstore |
the above plus Monitor DB db_ddladmin |
| Verify | Monitor DB db_datareader; side DB db_datareader + db_datawriter (Verify writes a run-log row to bak.Log; use -DryRun for a fully read-only verify) |
| Drop the side database (cleanup) | side DB db_owner (typically the DBA who created it), or dbcreator/sysadmin |
In Option 1 the DBA holds all of these. In Option 2 the DBA holds the create/grant/cleanup rows; the Citrix administrator's login holds the rest.
Create the side database (run on the SQL Server, via sqlcmd or SSMS — no SQLCMD mode required):
sqlcmd -S YOURSQLHOST\INSTANCE -i .\01_Create-BackupDatabase.sqlOption 2 only: grant the Citrix administrator's login the database roles listed above — db_owner on the side database, and db_datareader + db_datawriter (plus db_ddladmin if -CompressColumnstore will be used) on the Monitor database.
DBA tuning (optional): the side database is created with default file locations and the SIMPLE recovery model. To control file placement, initial size, or collation, edit the CREATE DATABASE / ALTER DATABASE block in 01_Create-BackupDatabase.sql — for example, pre-size the data file to ~1.2x the expected backup size to avoid autogrowth during a large load. The toolkit never joins on text columns, so a side-database collation that differs from the Monitor database cannot affect any of its joins.
The .sql runs on the database server (or any host with sqlcmd/SSMS that can reach it), run by the DBA — exactly where you run Citrix's Studio-generated setup scripts.
The PowerShell connects over the normal SQL client protocol and can be launched from the database server or any administrator workstation that can reach the instance. It is not a Delivery Controller operation and does not run as a Controller service. (All data movement is server-side INSERT … SELECT.)
Authentication — use Windows Integrated Authentication (Integrated Security=SSPI), the same Windows-auth model the Delivery Controller uses to reach its databases. SQL authentication is supported only as a fallback where Windows auth is unavailable.
Transport security: the examples use TrustServerCertificate=True for convenience. For full transport security, replace it with Encrypt=True and a trusted server certificate.
Tools — nothing to install on a standard SQL Server host:
| Tool | Needed? | Notes |
| Windows PowerShell 5.1 | Yes | Built into Windows Server. No modules required. Run the scripts with powershell.exe (5.1); PowerShell 7 (pwsh.exe) is not required and may not load the SQL client on all systems. |
sqlcmd or SQL Server Management Studio (SSMS) |
Yes | To run the one-time setup script. Either works; both are standard on a SQL host. |
No other downloads, modules, or third-party tools are required.
SQL Server version / edition:
Works on the same SQL Server version your Monitor database already runs on.
The optional columnstore-compaction switch (-CompressColumnstore) requires SQL Server 2016 or newer; on older versions the toolkit falls back to a plain online REORGANIZE automatically.
On SQL Server Express (10 GB per-database limit), the raw detail tables (RUV2/SMV3) may be too large to back up — in that case back up the summaries only (-Dataset RUS,SPS) or use a higher edition. The summary and Session Score data are small and very unlikely to hit the limit on their own.
Permissions: see #5 (Who runs it). In short — creating the side database needs a database administrator once; the pre-flight/backup/restore/verify need only a read/write login. You can run the optional read-only pre-flight check 00_Validate-Source.ps1 first (see §7) to confirm the source database is compatible.
Disk: the backup database needs free space roughly proportional to the data you choose to preserve. The summaries and Session Score are small; the raw tables can be several GB on large sites. Use the dry-run (below) to size it first.
PowerShell execution policy: if scripts are blocked on your machine, run with powershell.exe -ExecutionPolicy Bypass -File <script> or Unblock-File <script> once.
C:\MonitorUpgradeToolkit), open Windows PowerShell 5.1 there (cd C:\MonitorUpgradeToolkit), and unblock them once: Get-ChildItem *.ps1 | Unblock-File. Run every command below from that folder so the .\ paths resolve.Use a connection string pointing at your Monitor database. Windows Integrated Authentication is recommended (the same model the Delivery Controller uses):
$cs = 'Server=YOURSQLHOST\INSTANCE;Database=<MonitorDatabase>;Integrated Security=SSPI;TrustServerCertificate=True'
(SQL authentication fallback: ...;User ID=<user>;Password=<password>;TrustServerCertificate=True. For full transport security use Encrypt=True with a trusted certificate instead of TrustServerCertificate=True.)
Use HOST\INSTANCE for a named instance; for a default instance use just HOST (and for a non-standard port, HOST,PORT).
Finding your Monitor database: the Monitor (Director) database is separate from the Site/Configuration database. To get its server and name: in Citrix Studio open Configuration and read the Monitoring database entry; or on a Delivery Controller run Get-MonitorDBConnection (the connection string it returns contains the Server and Initial Catalog to use).
00_Validate-Source.ps1Before creating the side database, run this read-only probe to confirm you are pointed at the right database and that it is structurally ready. It makes no changes (SELECT/metadata queries only). It checks: connectivity; SQL Server version and edition; that the four source tables exist; that ResourceUtilizationSummary has all 13 metric columns and SessionPerformanceSummary has all 7 score columns; the expected structure (RUV2 unique key, RUS primary key, SMV3 identity/no unique key, SPS primary key + columnstore); approximate row counts; and whether the data is actually populated.
.\00_Validate-Source.ps1 -ConnectionString $cs
Read the final READINESS VERDICT line: green ("toolkit can run here") means the source tables and all expected columns are present — proceed. Red ("MISSING target objects") means you are either pointed at the wrong database or on an upgrade path this toolkit does not apply to — do not run the backup. The green verdict confirms only table/column presence, so also review any yellow WARNING lines (structure differences or empty tables) and the row-count / data-presence sections yourself.
Before the upgrade
# 0) (Recommended) Pre-flight check - read-only, changes nothing
.\00_Validate-Source.ps1 -ConnectionString $cs
# 1) Create the backup database (DBA; once)
sqlcmd -S YOURSQLHOST\INSTANCE -i .\01_Create-BackupDatabase.sql
# (or open 01_Create-BackupDatabase.sql in SSMS and Execute)
# 2) (Optional) Preview sizes - makes no changes
.\Invoke-MonitorDataRetention.ps1 -ConnectionString $cs -Mode Backup -DryRun
# 3) Back up
.\Invoke-MonitorDataRetention.ps1 -ConnectionString $cs -Mode Backup
# 4) Confirm the backup is complete
.\Invoke-MonitorDataRetention.ps1 -ConnectionString $cs -Mode Verify
Perform your normal Citrix upgrade
After the upgrade
# 5) (Optional) Preview the restore - makes no changes
.\Invoke-MonitorDataRetention.ps1 -ConnectionString $cs -Mode Restore -DryRun
# 6) Restore
.\Invoke-MonitorDataRetention.ps1 -ConnectionString $cs -Mode Restore -CompressColumnstore
# 7) Confirm
.\Invoke-MonitorDataRetention.ps1 -ConnectionString $cs -Mode Verify
Clean up (after you've confirmed the Director charts look right)
USE master;
GO
DROP DATABASE CitrixMonitorUpgradeBackup;
Run this from a session whose current database is master (not the backup database) and with no other open connections to it, otherwise SQL Server returns "cannot drop database … currently in use." In Option 2, cleanup is typically done by the DBA who created the side database.
Preserve only the durable summary histories (skip the short-lived raw tables RUV2/SMV3):
.\Invoke-MonitorDataRetention.ps1 -ConnectionString $cs -Mode Backup -Dataset RUS,SPS
.\Invoke-MonitorDataRetention.ps1 -ConnectionString $cs -Mode Restore -Dataset RUS,SPS
| Option | Default | Meaning |
| -Mode | — | Backup, Restore, or Verify. |
| -Dataset | all | Limit scope. Values: RUS (resource-utilization summary), RUV2 (raw resource-utilization), SMV3 (raw session metrics), SPS (Session Score summary). Combine with commas, e.g. -Dataset RUS,SPS for the durable summaries only. |
| -DryRun | off | Preview what would happen; writes nothing. |
| -BatchSize | 50000 | Rows per batch. Lower it on a busy or smaller server. |
| -SleepMs | 0 | Pause between batches to reduce load on a live server. |
| -MaxRunSeconds | 0 | Stop cleanly after N seconds; re-run later to resume. |
| -CompressColumnstore | off | Restore only. Compacts columnstore storage on the three columnstore tables (RUV2/SMV3/SPS), then refreshes statistics on all four tables. Requires SQL Server 2016 or newer; older versions automatically fall back to a plain online REORGANIZE. |
| -Reset | off | Start a dataset over from scratch. In Backup mode, it empties the backup table (TRUNCATE) and clears its checkpoint; your live Monitor data is never touched. In Restore mode, it clears the restore checkpoint only. Use only if Citrix support tells you to. |
| -BackupDatabase | CitrixMonitorUpgradeBackup | Name of the side/backup database (must be on the same instance). |
| -CommandTimeout | 600 | Per-batch SQL command timeout, in seconds. |
Re-running is always safe. Restore never creates duplicates and never overwrites or deletes data collected after the upgrade. Backup never double-copies.
Resumable. If a run is interrupted (including a dropped connection), just run the same command again — it continues from where it stopped.
Online. No table locks, no index disabling, no downtime; it can run while the Monitor service is up (a quiet window is still preferable for speed).
Read-only verification. Verify makes no changes to your Monitor data (it writes only a status row to the toolkit's log in the side database); use -DryRun for a fully read-only verify.
Not a substitute for a full backup. Always take a normal full SQL Server backup before upgrading.
The bulk of the time is spent on the raw resource-utilization data; the summaries and Session Score data are small by comparison.
In performance testing on a large dataset (tens of thousands of machines, ~100 million rows across the resource-utilization data sets), throughput was roughly 50,000–85,000 rows/second per data set, single-threaded and online. A ~100-million-row Monitor database backs up in about 20–35 minutes; restore is similar.
The Session Score table SessionPerformanceSummary holds one row per session per 30-minute interval (up to ~7 days) and is small — on typical sites the Session Score portion completes in a few minutes.
The backup database uses disk on the order of the data volume you preserve (the summaries and Session Score are small; raw tables scale with machine count). Use -Mode Backup -DryRun to size it.
Long runs tolerate brief network interruptions — the tool resumes automatically.
Do I need database-administrator rights to run this? Only to create the side database once. After that, backup / restore / verify need only a normal read/write login — see §5 for the two operating models.
Where do I run it — on the Delivery Controller or the database server? The .sql runs on the SQL Server (via sqlcmd/SSMS); the PowerShell runs from the database server or any administrator workstation that can reach SQL. It is not a Delivery Controller operation.
Windows or SQL authentication? Windows Integrated Authentication is recommended — the same model the Controller uses. SQL authentication is a fallback.
Error "Unable to find type [System.Data.SqlClient.SqlConnection]"? Run the scripts in Windows PowerShell 5.1 (Start > Windows PowerShell, or powershell.exe), not PowerShell 7.
A run stopped partway — did I lose progress? No. Re-run the same command; it resumes.
Can I run backup or restore more than once? Yes — it's idempotent and additive.
Verify reports some rows "missing". Usually normal, and by design. Two things cause it:
Grooming. The recent raw tables (RUV2/SMV3) are groomed (deleted) after ~3 days and SessionPerformanceSummary after ~7 days, so rows that age out between backup and verify are gone.
A missing parent row. On restore, the toolkit skips any row whose parent machine or session no longer exists (removed or groomed after the upgrade), so a restore never breaks a foreign key. Session Score reports these skips separately as a missingNoParentSession count; for RUV2/SMV3 they are included in the missing total.
A small missing count is therefore expected, not a failure. The resource-utilization summary history (RUS) should report no gaps.
Which database did it use? The first line of output prints the Monitor database it connected to and the backup database name.
Where can I see status/history? In the console output, and in the bak.Log table inside the backup database.
Can I run it while users are active? Yes (it's online). A maintenance window is faster.
My maintenance window is short. Use -MaxRunSeconds <n> to stop cleanly and resume later.
A single set of three scripts covers all of the data preserved by this guide (resource-utilization, session metrics, and Session Score).
| File | Purpose |
| 01_Create-BackupDatabase.sql | Creates the CitrixMonitorUpgradeBackup database (run once, before backup). Safe to re-run. |
| Invoke-MonitorDataRetention.ps1 | Runs Backup / Restore / Verify for all datasets (RUS / RUV2 / SMV3 / SPS). Takes a connection string. |
| 00_Validate-Source.ps1 | Optional read-only pre-flight check (confirms tables/columns/data are present). |
"The above mentioned sample code is provided to you as is with no representations, warranties or conditions of any kind. You may use, modify and distribute it at your own risk. CITRIX DISCLAIMS ALL WARRANTIES WHATSOEVER, EXPRESS, IMPLIED, WRITTEN, ORAL OR STATUTORY, INCLUDING WITHOUT LIMITATION WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NONINFRINGEMENT. Without limiting the generality of the foregoing, you acknowledge and agree that (a) the sample code may exhibit errors, design flaws or other problems, possibly resulting in loss of data or damage to property; (b) it may not be possible to make the sample code fully functional; and (c) Citrix may, without notice or liability to you, cease to make available the current version and/or any future versions of the sample code. In no event should the code be used to support ultra-hazardous activities, including but not limited to life support or blasting activities. NEITHER CITRIX NOR ITS AFFILIATES OR AGENTS WILL BE LIABLE, UNDER BREACH OF CONTRACT OR ANY OTHER THEORY OF LIABILITY, FOR ANY DAMAGES WHATSOEVER ARISING FROM USE OF THE SAMPLE CODE, INCLUDING WITHOUT LIMITATION DIRECT, SPECIAL, INCIDENTAL, PUNITIVE, CONSEQUENTIAL OR OTHER DAMAGES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. Although the copyright in the code belongs to Citrix, any distribution of the sample code should include only your own standard copyright attribution, and not that of Citrix. You agree to indemnify and defend Citrix against any and all claims arising from your use, modification or distribution of the sample code."
The uberAgent lite feature, introduced in 2507 CU2, stores new performance metrics — resource-utilization, session metrics, and Session Score history — in the Monitor database.
When you upgrade from CU2 or any other CU in 2507 to a release that also includes this feature, the upgrade resets that part of the Monitor schema and does not carry the previously collected data across. Therefore, the data collected before the upgrade is lost and collection starts fresh afterward. Once you are on 2603 or later, the feature is part of the base release and later upgrades preserve the data — this no longer applies.
This article applies if all of the following conditions are met:
It does NOT apply if:
Note that the feature itself is not impacted during such upgrades (except for the upgrade to 2511 as mentioned above) — data collection resumes automatically after the upgrade; only the history collected before the upgrade is affected. If none of the above matches your upgrade, or you don't need this history, you do not need this toolkit — the upgrade works fine on its own.
This is an optional toolkit to back up and restore the resource-utilization and session Score/metrics data that can otherwise be cleared when you upgrade, as described in the criteria above.
It is safe, additive, and re-runnable. It changes no product code — you run it by hand (or from your upgrade runbook) against your Monitor database.
Scripts: a single set of three scripts (01_Create-BackupDatabase.sql, Invoke-MonitorDataRetention.ps1, and the optional 00_Validate-Source.ps1) covers all of the data preserved here — resource-utilization, session metrics, and Session Score.
Download them from this article before you start.
Optional tool. Online-safe, idempotent, resumable. Always take a full SQL Server backup before any upgrade.