SWS Caching

Advanced Topic - Caching Responses - Read Carefully!

How SWS uses the PeopleTools REST cache

When you set Minutes to Cache Response to a non-zero value on an SWS configuration row, the handler adds a Cache-Control: max-age=<N*60> header to the response. The PeopleTools RESTListeningConnector servlet then stores the full response in memory and replays it for subsequent matching requests until the TTL expires. The cache lives in the PIA web-server JVM, not in PeopleSoft application-server memory β€” restarting PIA empties it; restarting the app server does not.

No code change is required to opt in. Set a non-zero value on the configuration row, save, and the very next request from that endpoint will populate the cache.

What gets cached, and what the cache key actually is

The cache key is the full request URL β€” that is, path and query string β€” combined with the Accept header. Two requests are treated as cache hits only when all three match exactly.

ComponentPart of cache key?Notes
URL path (e.g. /acmecorp/people/PS)yesDifferent path = different cache entry. {emplid} path parameters create one entry per distinct value.
Query string (e.g. ?rowLimit=50)yes?rowLimit=10 and ?rowLimit=20 are independent cache entries. So is the absence of any query string.
Accept headeryesJSON, XML, and CSV responses are cached independently. Three different Accept values populate three cache entries.
Authorization header (basic-auth user)noThis is the central caching gotcha. Two different callers hitting the same URL get the same cached response β€” see below.
Request body (POST endpoints)noThe REST cache is GET-oriented. CHG_SWS_PSOFTQL (a POST endpoint) effectively does not benefit from this cache for variable input.

Choosing a TTL

The right cache duration is the longest interval during which a stale response is still acceptable to the caller. Some patterns we’ve seen work well:

Endpoint patternRecommended TTLWhy
XLAT / setup lookups (subjects, campuses)60 minutes (or 1440 / 24h)These change on a release cadence β€” minutes-old data is fine.
Reference tables editable only by power users5–30 minutesLong enough to absorb burst traffic, short enough that an admin’s edit shows up within the hour.
Reporting / dashboard rollups5–15 minutesDashboards typically refresh on this cadence anyway; caching aligns with the refresh budget.
Real-time-ish data (current term enrollments)1–2 minutesUse only when the source data changes slower than the TTL.
Per-user data (uses %OPERATOR / %EMPLOYEEID)0 (disabled)Caching across users leaks data. See the security alert below.
Cheap queries (<100ms server time)0 (disabled)The cache itself adds overhead. If the query isn’t slow, don’t cache.

There is no upper limit enforced by SWS. Practical ceiling: anything beyond a few hours starts feeling like a static asset, at which point you should consider regenerating the data into a separate table refreshed by a scheduled job rather than caching an unbounded query.

No manual cache invalidation

There is no SWS or PeopleSoft UI to flush the REST cache. Your options when cached data is wrong are:

  1. Wait out the TTL. The cache entry expires naturally and the next request re-runs the SQL.
  2. Bounce PIA. Restarting the PeopleSoft web server tier empties the JVM cache. This is heavy-handed but effective.
  3. Change the URL. Adding a cache-busting query-string parameter (?_v=2) creates a new cache entry rather than replacing the old one β€” works as a per-caller workaround when you can change the integration partner’s URL.

Choose your TTL with the assumption that you cannot intervene mid-window.

Security: the cross-user data-leak risk

The cache key does not include the caller’s OPRID. Two callers hitting the same URL within the TTL window receive the same response, even when:

  • They were authenticated as different OPRIDs.
  • They belong to different permission lists.
  • The underlying SQL uses %OPERATOR or %EMPLOYEEID and would otherwise return different rows per user.

This means that an endpoint where caller A hits /student/grades and gets caller A’s grades will, if cached, return caller A’s grades to caller B’s next call as well.

Safe caching candidates: endpoints whose response depends only on the URL, query string, and database state β€” never on which OPRID is calling.

Detecting whether a response was served from cache

There is no SWS-emitted “cache hit” header. Inspect these signals instead:

  • meta.responseDTTM in JSON/XML responses (or x-requestTime for CSV) is the timestamp the response was originally assembled. On a cache hit it stays at the populate-time value, not the current wall clock. If two calls 30 seconds apart return identical responseDTTM strings, the second was a cache hit.
  • meta.psftTransactionId is also frozen at populate time. Identical transaction IDs across calls = same cached entry.
  • Wall-clock latency drops sharply on a hit β€” typically from hundreds of milliseconds (real SQL execution) to single-digit milliseconds (servlet returning cached bytes).

Combine the three: if responseDTTM and psftTransactionId match across two calls and latency is sub-10ms, you’re seeing a cache hit.

See also