In my previous post, I focused on Coach views and static assets, and how their loading behavior can significantly affect perceived and actual performance in a Case Details Custom CSHS.
In this post, I’ll shift attention to another major contributor to runtime behavior: Service Flows, and what really happens when they’re invoked from a CSHS diagram.
While Service Flows are a powerful way to encapsulate server‑side logic, they aren’t free. Each call has costs in terms of network requests, data processing, and security validation. Understanding those costs helps you decide when a Service Flow call is justified and when it’s better to keep work on the server or consolidate logic.
Server Requests
A CSHS diagram runs entirely in the browser. Every Service Flow activity in that diagram requires a request to the server to execute it.
At a high level, the cost difference between making one request versus three sequential requests is already well understood. What’s less obvious is the additional overhead introduced specifically by invoking Service Flows from a CSHS, compared to executing the same logic entirely on the server.
That overhead shows up even before your business logic runs, and it becomes increasingly important as Service Flow calls are chained together before or between coaches.
Data Handling Costs
Moving JSON data between client and server is routine, but invoking Service Flows from a CSHS introduces a couple of extra costs that are easy to overlook:
- Data type handling
- Shared business objects and content objects
Strongly Typed Data
Service Flows operate on strongly typed Java implementations of JavaScript objects. This means the server does more than a simple JSON.parse when handling incoming data. Object construction, type validation, and error handling all add to processing time.
Because the client side of a CSHS is loosely typed, every Service Flow call is also a potential failure point if the object structure isn’t exactly what the server expects. To defend against that, it’s tempting to add more validation and error handling in the CSHS, making the diagram more complex.
Shared and Content Objects
When a CSHS implements a user task any shared business objects or content objects, commonly associated with case properties, have a lifecycle independent of that task. To manage this, special metadata is included with these variables.
The CSHS only ever sees this metadata in encrypted form to prevent it from being manipulated directly. Each time the variable is sent to the server:
- The metadata is decrypted
- Value changes are merged into the server‑side lifecycle
- Updated metadata is encrypted again for the response
That work happens every time the variable crosses the client‑server boundary, and it can add measurable overhead if Service Flows are invoked frequently.
One subtle point to be aware of: if the connection leading to a Service Flow has Save enabled, the save operation is included with the Service Flow request. This avoids a second round trip, which is good, but if you’re measuring request times in the network profile, the numbers will include both save and Service Flow execution which can skew timing comparisons.
In some designs, saving task progress is the reason Service Flows are called individually from a CSHS. Since saves are only supported on connections in the CSHS diagram, any requirement to save between Service Flows means those Service Flows must be invoked from the CSHS with saving enabled between them.
Security Overhead
Calling a Service Flow from a CSHS also triggers additional security checks.
Any Service Flow can be called from a CSHS, regardless of the Ajax access settings on the Service Flow itself. Access is governed instead by the user’s authorization for the CSHS.
At runtime, the server validates the request by checking that the Service Flow being invoked actually exists in the CSHS model that the request claims it belongs to. To do that, the server loads the CSHS model, and if the Service Flow resides in a nested CSHS, the entire chain of CSHS models is verified before execution. This verification is then combined with a check of the user’s authorization for the CSHS.
None of this validation work is required when one Service Flow calls another Service Flow on the server. In that case, the invocation occurs entirely within the trusted server context, avoiding the cost of loading and validating CSHS models and performing CSHS‑level authorization checks.
There’s also a data‑exposure concern to keep in mind. When the outputs of one Service Flow are only needed as inputs to the next Service Flow, they’re still sent back to the browser in between calls if those calls originate from a CSHS. If the CSHS doesn’t actually need to read or manipulate those values, they’re being sent to the client, and potentially exposed to manipulation, for no benefit.
In those situations, keeping intermediate values entirely on the server is both more efficient and more secure.
Wrapping Up