Profile the RDS Journey, Then Scale the VUs

Also published on the product site: profile-rds-journey-then-scale-citratest-vu.aspx

CitraTest VU load testing for Microsoft RDP / RDS / Remote Desktop – encode the on-the-glass journey (mstsc, RD Web, Session Hosts, RemoteApp) with WaitForImage and StartTimer/StopTimer first, then scale concurrent virtual users.

Direct answer: Do not ramp concurrency against a vague Microsoft RDS script. CitraTest VU® load-tests Remote Desktop Services from the glass – but the honest sequence is profile the RDS user journey first, then scale the VUs. Walk the real client path (mstsc, Remote Desktop app, RD Web / Gateway into a Session Host or RemoteApp), encode mouse and keyboard steps, sync with WaitForImage, time moments of truth with StartTimer / StopTimer, prefer static bitmaps, reserve OCR for dynamic text (OCR is not a wait). Only after that definition of success is stable do you raise concurrent virtual users.

Teams that start with "how many RDP sessions can we push?" often skip the harder question: what does a single successful RDS journey look like on screen? If the script stops at "RDP connected," hammers RD Web over HTTP, checks Connection Broker health, or sleeps for five seconds after credentials, concurrency only amplifies the wrong clock. A thousand virtual users with a bad RDS journey is not Session Host capacity planning – it is noise at scale.

This post is the RDP/RDS-specific sequencing method for CitraTest VU load testing: encode the Microsoft Remote Desktop journey on the glass, then scale. It is distinct from the general VU article Profile the User Journey, Then Scale the VUs (Citrix, RDS, and cloud together). It is not a production continuous-watch guide (that is CitraTest APM Publish → Scenario → SLA), not an after-hours APM watch (Overnight Shift Watch), and not a how-to for splitting automated regression scripts into login-storm vs sustained-path builds (Control Plane ≠ Farm for automated testing). For why control-plane / broker green is not farm proof under load, see The Control Plane Is Not the Farm. Same glass contract; this article is the order of operations for Microsoft RDS.

By Jay Labadini, Tevron

Why ramp-first fails on Microsoft RDS

Concurrency is a multiplier. It multiplies whatever your RDS script already treats as "done."

  • RDP connected is not shell ready. The remoting channel can be up while profile attach, GPO, FSLogix (or equivalent), and the desktop or RemoteApp are still painting.
  • RD Web HTTP is the front door, not the farm. Soaking the portal times the website – not Session Host density or in-session click-to-ready.
  • Broker / host counters are not the wait the user feels. Connection Broker health and Session Host CPU can look fine while logon-to-shell and RemoteApp first paint stretch.
  • Fixed sleeps hide variance. A pause that works for one calm mstsc session collapses under a Monday morning rush – or falsely passes when the glass was ready sooner.
  • Unnamed timers cannot guide SKU decisions. If every step dumps into one stopwatch, you cannot tell whether broker spin-up, profile attach, or in-session work broke first.

Profile the RDS journey until a single VU (or a small interactive playback) proves the same moments of truth a real Remote Desktop user would recognize. Then scale.

RD Web and broker can stay green while glass latency rises - profile the RDS journey before scaling VUs

Illustrative / method diagram – not Tevron customer results. Control-plane and broker indices can remain "healthy" while glass-level RDS response climbs with concurrency.

Profile the RDS journey on the glass

Per CitraTest User Guide / Quick Start measurement guidance, an on-the-glass Microsoft RDS journey uses one contract:

  1. Scripts encode the workflow on a Windows desktop – including the real RDP client path.
  2. Playback sees the remoted UI with bitmap images (and OCR when text is dynamic).
  3. Playback acts with real mouse and keyboard into mstsc / Remote Desktop / RD Web launch and the Session Host session.
  4. WaitForImage synchronizes and verifies expected screen state before the next step.
  5. StartTimer / StopTimer capture on-screen response: StartTimer immediately after the initiating action; StopTimer immediately after WaitForImage confirms completion.

Walk the path a shift cannot skip on your farm:

  • Logon-to-shell – credentials (or RD Web / Gateway launch) until a usable desktop or RemoteApp window is ready: shell, icons, no logon animation. Not "the broker returned a session."
  • RemoteApp / published app launch – icon or Start-menu click until first paint of the business app. Not "the process started on the Session Host."
  • In-session transactions – click or key until the ready state: open record, save, print, switch RemoteApps. The wait behind "the desktop is slow" tickets after everyone is already connected.

Name each timer after what the user sees on the glass, not after an RDP round-trip or broker hop label. Pin the Session Host image, collection, client (mstsc / Remote Desktop app), and RD Web or Gateway build. Keep baseline images small and unique; match display properties (resolution, color depth, theme, font smoothing) between capture and playback so "image not found" failures are real application delays, not environment drift.

See Wait Act Measure pipeline with WaitForImage and StartTimer StopTimer for RDS journey profiling

Illustrative method diagram – not customer results. That pipeline is the measurement contract inside the RDS journey you will later scale.

Bitmaps for sync; OCR only for dynamic text

While you profile – and later under VU concurrency on RDP pixels – keep OCR in its lane:

  • Prefer static bitmaps for sync cues that do not change (shell icons, RemoteApp window chrome, toolbar glyphs, confirmation marks).
  • Reserve OCR for values that are unknown ahead of time (IDs, MRNs, order numbers, timestamps on the remoted app).
  • OCR is not a wait/sync. Confirm readiness with image functions first (WaitForImage, ClickOnImage), then OCR. Under VU, OCR calls have no timeout for wait/sync; flaky "OCR problems" on RDS are usually sync problems in disguise.

Related: Advanced OCR for Automated Testing.

Then scale: CitraTest VU concurrency on RDS

Once the RDS journey is honest in interactive playback, scale it with CitraTest VU. Per the CitraTest User Guide (Chapter 11) and Quick Start VU overview:

  1. A dedicated VU load server (Windows Server with Remote Desktop Services) hosts many localhost RDP "CitraTest VU Sessions."
  2. Each session runs the profiled CitraTest script and opens its own client connection to the Microsoft RDS farm under test – mstsc / Remote Desktop / RD Web path into Session Hosts or RemoteApp – just as a group of real users would.
  3. Scripts continue to drive the remoted desktop with real mouse and keyboard, sync with bitmaps, and optionally use OCR for dynamic text.
  4. Separate measurement machines record response timers under load; results land in a results database and VU Results Console.

Nothing invasive is required on the Session Hosts or brokers for the glass path: the load is client-side. You change ramp, concurrency, and think time – not the definition of success. Success remains: the image-confirmed UI state (shell, RemoteApp, in-session ready) appeared within the timer threshold under the load you claim to support.

CitraTest VU architecture flow - load server, VU sessions driving Microsoft RDS, measurement machines

Illustrative architecture based on User Guide Ch 11 / Quick Start VU overview – not a performance result chart.

Profile Microsoft RDS glass journey then ramp CitraTest VU concurrency pipeline

Illustrative method diagram – not customer results. Encode the RDS journey, then raise concurrent VUs against the same WaitForImage timers.

After the RDS journey is honest: storm vs density (brief)

Scaling is not one blunt ramp. Once the glass journey is profiled for Microsoft RDS, Tevron’s 2026 method guidance still separates two load phases – with the same scripts and the same moments of truth:

Phase What you change What you learn
Login storm Steep concurrent logons (broker, profile, Session Host spin-up) Can the farm absorb the rush to first useful glass (logon-to-shell / RemoteApp)?
Density / sustain Hold concurrency; exercise the profiled multi-step RemoteApp / in-session work Sessions-per-host, glass latency, SKU and autoscale truth

Do not invent a second definition of success for each phase. Change how many VUs arrive and how long they stay busy on the Session Hosts. For the deeper control-plane-vs-farm framing under load, see The Control Plane Is Not the Farm and Logon storm vs density. For the broader Microsoft RDS method hub, see Microsoft RDS Load Testing.

Login storm vs density sustain after profiling the Microsoft RDS glass journey for CitraTest VU

Illustrative method diagram – not customer results. Apply the same split after the RDS journey is profiled for Session Hosts and RemoteApp collections.

Sizing note (after the journey, before the big run)

Current User Guide Chapter 1 and Quick Start align on:

8 GB baseline + 8 GB additional RAM per 200 VU sessions, quad CPU minimum, 200 GB disk minimum, RDS configured per Chapter 11.

Also operational: do not minimize VU RDP windows during a run – RDP can blank the display, and scripts need a visible desktop to see. Profile with a visible desktop; scale with a visible desktop. If the generator desktop is pegged, you are measuring the lab, not the Session Host farm.

How this sits next to APM, automated testing, and the general VU post (brief)

One glass definition of success travels across Tevron products without turning this article into those playbooks:

Related: What is CitraTest VU?, Microsoft RDS Load Testing, How to load test Citrix.

Closing: encode the RDS journey, then raise concurrency

Profile the Microsoft RDP / RDS user journey on the glass until WaitForImage and StartTimer/StopTimer name the moments a real Remote Desktop shift would recognize – logon-to-shell, RemoteApp launch, in-session ready. Prefer bitmaps for static sync; reserve OCR for dynamic text; never treat OCR as a wait. Then scale CitraTest VU concurrent sessions against that same definition of success – login storm and density/sustain as ramp shapes, not as new guesses about what "ready" means on a Session Host. Capacity numbers only earn trust when the RDS journey they multiply was honest at one user.

FAQ

Why profile the Microsoft RDS journey before scaling CitraTest VU concurrent users?
Concurrency amplifies whatever the script already measures. If the RDS journey is vague – RDP connected, RD Web HTTP 200, broker green, or fixed sleeps instead of on-screen shell and RemoteApp readiness – a thousand VUs only produce a louder wrong answer. Encode WaitForImage sync and StartTimer/StopTimer for logon-to-shell, RemoteApp launch, and in-session moments of truth first, then ramp.

What does profiling an on-the-glass RDS journey mean in CitraTest VU?
A CitraTest script walks the real Microsoft RDP path – mstsc, Remote Desktop app, RD Web / Gateway launch into a Session Host or RemoteApp – drives the remoted GUI with mouse and keyboard, syncs with WaitForImage on static bitmaps, optionally uses OCR for dynamic text after image sync, and places StartTimer immediately after each initiating action and StopTimer after WaitForImage confirms the screen state users care about.

Can OCR be used as a wait or sync under CitraTest VU for RDS?
No. VU OCR calls have no timeout for wait/sync. Confirm readiness with image functions first (WaitForImage, ClickOnImage), then OCR. Prefer bitmaps for static UI cues; reserve OCR for dynamic text.

How does this post differ from Profile the User Journey, Then Scale the VUs?
That article is the general CitraTest VU sequencing method across Citrix, RDS, and cloud VDI. This article is RDP/RDS-specific: mstsc and RD Web paths, Session Hosts, RemoteApp collections, RDP connected versus shell ready, and the same profile-then-scale order applied to Microsoft Remote Desktop Services.

Do you need agents on Session Hosts for CitraTest VU RDS load testing?
No. For the glass path, load is client-side from VU sessions on a dedicated load server. Each virtual user opens a real Remote Desktop connection to the environment under test. Nothing invasive is required on the Session Hosts or brokers themselves.

When you need that glass path without agents on production session hosts — schedule a demo. Product pages: CitraTest VU, CitraTest APM, and the Tevron.com blog.

Citrix, HDX, ICA, StoreFront, Workspace, Microsoft, Remote Desktop Services, RemoteApp, Azure Virtual Desktop, and related marks are trademarks of their respective owners. Tevron is not affiliated with those vendors. Names are used for identification only.