FHIR Tooling Extensions IG, published by HL7 International / FHIR Infrastructure. This guide is not an authorized publication; it is the continuous build for version 1.1.2 built by the FHIR (HL7® FHIR® Standard) CI Build. This version is based on the current content of https://github.com/FHIR/fhir-tools-ig/ and changes regularly. See the Directory of published versions
| Page standards status: Informative | Maturity Level: 1 |
<OperationDefinition xmlns="http://hl7.org/fhir">
<id value="cache-control"/>
<language value="en"/>
<text>
<status value="generated"/>
<div xml:lang="en" lang="en"><hr/><p><b>English</b></p><hr/><p class="res-header-id"><b>Generated Narrative: OperationDefinition cache-control</b></p><a name="cache-control"> </a><a name="hccache-control"> </a><p>URL: [base]/$cache-control</p><h3>Parameters</h3><table class="grid"><tr><td><b>Use</b></td><td><b>Name</b></td><td><b>Scope</b></td><td><b>Cardinality</b></td><td><b>Type</b></td><td><b>Binding</b></td><td><b>Documentation</b></td></tr><tr><td>IN</td><td>mode</td><td/><td>1..1</td><td><a href="http://hl7.org/fhir/R5/datatypes.html#code">code</a></td><td/><td><div><p>What to do: 'start' creates a new cache and returns its id; 'end' releases the cache identified by the X-Cache-Id header; 'check' reports whether the cache identified by the X-Cache-Id header is still valid, returns statistics about it, and - because checking is itself use - resets its idle timer, so a client can use 'check' to keep a cache it still needs from timing out.</p>
</div></td></tr><tr><td>IN</td><td>tx-resource</td><td/><td>0..*</td><td><a href="http://hl7.org/fhir/R5/resource.html">Resource</a></td><td/><td><div><p>Optional resources (CodeSystem, ValueSet, ConceptMap) to front-load into the cache when mode=start, so they are immediately in scope for subsequent calls that carry the cache-id. Resources may also be added incrementally on later $validate-code / $expand calls (unless the cache is sealed).</p>
</div></td></tr><tr><td>IN</td><td>sealed</td><td/><td>0..1</td><td><a href="http://hl7.org/fhir/R5/datatypes.html#boolean">boolean</a></td><td/><td><div><p>Used with mode=start: whether the cache is sealed. A sealed cache (the default) contains only the resources front-loaded in this call and does not grow; an unsealed cache (sealed=false) additionally accumulates resources it sees on subsequent calls, and is what makes incremental population and batch front-loading possible. If omitted, the server's default applies (which SHOULD be true); a client that requires a particular behaviour should set this explicitly and check the sealed value returned in the response.</p>
</div></td></tr><tr><td>OUT</td><td>cache-id</td><td/><td>0..1</td><td><a href="http://hl7.org/fhir/R5/datatypes.html#id">id</a></td><td/><td><div><p>The server-issued cache identifier, returned by mode=start. The client sends this value as the X-Cache-Id HTTP header on subsequent requests that should use the cache. Absent if no cache was created.</p>
</div></td></tr><tr><td>OUT</td><td>sealed</td><td/><td>0..1</td><td><a href="http://hl7.org/fhir/R5/datatypes.html#boolean">boolean</a></td><td/><td><div><p>Whether the cache is sealed. A mode=start response always includes it, so the client does not have to assume a default - it states authoritatively whether the cache is fixed at what was front-loaded (sealed=true) or will grow as further resources are seen (sealed=false). A mode=check response includes it for a cache that is still valid, so a client can confirm what it is actually working with. The minimum cardinality is 0 because it is not returned by mode=end, nor by a mode=check that reports valid=false; it is nonetheless mandatory in a mode=start response.</p>
</div></td></tr><tr><td>OUT</td><td>valid</td><td/><td>0..1</td><td><a href="http://hl7.org/fhir/R5/datatypes.html#boolean">boolean</a></td><td/><td><div><p>Returned by mode=check: whether the cache named in the X-Cache-Id header is still held by this server. Mandatory in a mode=check response (the minimum cardinality is 0 only because the parameter is not returned by the other modes). Note that a mode=check that finds nothing is still a successful operation - it returns HTTP 200 with valid=false, not an error - so that a client can distinguish a server that reports the cache is gone from a server it could not reach at all. The two call for opposite responses: the first means start a new cache, the second means retry.</p>
</div></td></tr><tr><td>OUT</td><td>resource-count</td><td/><td>0..1</td><td><a href="http://hl7.org/fhir/R5/datatypes.html#unsignedInt">unsignedInt</a></td><td/><td><div><p>Returned by mode=check for a valid cache: how many resources the cache currently holds. Informational - useful for confirming that incremental population of an unsealed cache is working as the client expects.</p>
</div></td></tr><tr><td>OUT</td><td>idle</td><td/><td>0..1</td><td><a href="http://hl7.org/fhir/R5/datatypes.html#unsignedInt">unsignedInt</a></td><td/><td><div><p>Returned by mode=check for a valid cache: how many seconds it had been since the cache was last used, measured before this check reset the timer. A client can compare this against the <code>timeout</code> to see how close it came to losing the cache, and adjust how often it checks.</p>
</div></td></tr><tr><td>OUT</td><td>timeout</td><td/><td>0..1</td><td><a href="http://hl7.org/fhir/R5/datatypes.html#unsignedInt">unsignedInt</a></td><td/><td><div><p>Returned by mode=check for a valid cache, where the server is willing to say: how many seconds a cache may go unused before this server releases it. This lets a client size its checking interval to the server it is actually talking to, rather than guessing at a value it has no other way to discover. A server that has no idle timeout, or does not wish to state one, omits this - a client that gets no value should choose a conservative interval of its own.</p>
</div></td></tr><tr><td>OUT</td><td>outcome</td><td/><td>0..1</td><td><a href="http://hl7.org/fhir/R5/operationoutcome.html">OperationOutcome</a></td><td/><td><div><p>Returned by mode=check when valid=false: an OperationOutcome explaining why the cache is not available, with an issue carrying the code <code>cache-id-unknown</code> from http://hl7.org/fhir/tools/CodeSystem/tx-issue-type - the same coded issue a request that used the cache-id would have failed with. Servers SHOULD make the diagnostics say which fate the cache met (never issued by this server, released by the client, or timed out after a period of not being used), since those point at quite different problems.</p>
</div></td></tr></table></div>
</text>
<extension
url="http://hl7.org/fhir/StructureDefinition/structuredefinition-fmm">
<valueInteger value="1"/>
</extension>
<extension
url="http://hl7.org/fhir/StructureDefinition/structuredefinition-wg">
<valueCode value="fhir"/>
</extension>
<extension
url="http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status">
<valueCode value="informative">
<extension
url="http://hl7.org/fhir/StructureDefinition/structuredefinition-conformance-derivedFrom">
<valueCanonical
value="http://hl7.org/fhir/tools/ImplementationGuide/hl7.fhir.uv.tools"/>
</extension>
</valueCode>
</extension>
<url value="http://hl7.org/fhir/tools/OperationDefinition/cache-control"/>
<identifier>
<system value="urn:ietf:rfc:3986"/>
<value value="urn:oid:2.16.840.1.113883.4.642.40.1.33.1"/>
</identifier>
<version value="1.1.2"/>
<name value="CacheControl"/>
<title value="Terminology Cache Control"/>
<status value="active"/>
<kind value="operation"/>
<experimental value="false"/>
<date value="2026-08-25T23:44:14+00:00"/>
<publisher value="HL7 International / FHIR Infrastructure"/>
<contact>
<telecom>
<system value="url"/>
<value value="http://www.hl7.org/Special/committees/fiwg"/>
</telecom>
</contact>
<description
value="Manage a terminology client cache on the server. A client that repeatedly validates or expands against the same value sets and code systems can register those resources with the server once, under a server-issued cache-id, and then refer to them by url on subsequent calls instead of re-sending them each time.
The protocol is explicit: the client calls this operation with mode=start to create a cache; the server allocates the cache and returns its identifier in the `cache-id` output parameter. The client then sends that identifier as the `X-Cache-Id` HTTP header on subsequent $validate-code and $expand requests. Resources are populated into the cache by sending them (as `tx-resource`, or as the primary `valueSet`/`codeSystem`) on those requests, or by front-loading them in the mode=start call.
By default a cache is sealed: it holds only the resources front-loaded at mode=start and does not grow. A client that wants the cache to accumulate resources as they are seen (needed for incremental population and batch front-loading) requests an unsealed cache by sending sealed=false at mode=start. The mode=start response always reports, in the `sealed` output parameter, which kind of cache was created. When finished, the client calls mode=end to release the cache (the server will otherwise time it out).
A server releases a cache that has not been used for some time. Because a client's own local caching can absorb its terminology work for long stretches, a client may still depend on a server-side cache it has not touched for a while; mode=check exists for this case. It reports whether the cache is still there, and checking counts as use, so a client that expects to go quiet can keep its cache alive by checking periodically. The response reports the server's idle timeout, so the client can size that interval to the server rather than guessing.
Because the server owns the cache-id, it can authoritatively report when a client refers to a cache it does not have (never created, expired, or released): such requests fail with an OperationOutcome whose issue carries the code `cache-id-unknown` from http://hl7.org/fhir/tools/CodeSystem/tx-issue-type. This is distinct from a value set or code system genuinely not being found, so a client can tell a stale cache from an authoring error.
This operation affects server state and SHOULD be invoked with POST; servers MAY also accept GET for convenience."/>
<jurisdiction>
<coding>
<system value="http://unstats.un.org/unsd/methods/m49/m49.htm"/>
<code value="001"/>
</coding>
</jurisdiction>
<affectsState value="true"/>
<code value="cache-control"/>
<system value="true"/>
<type value="false"/>
<instance value="false"/>
<parameter>
<name value="mode"/>
<use value="in"/>
<min value="1"/>
<max value="1"/>
<documentation
value="What to do: 'start' creates a new cache and returns its id; 'end' releases the cache identified by the X-Cache-Id header; 'check' reports whether the cache identified by the X-Cache-Id header is still valid, returns statistics about it, and - because checking is itself use - resets its idle timer, so a client can use 'check' to keep a cache it still needs from timing out."/>
<type value="code"/>
</parameter>
<parameter>
<name value="tx-resource"/>
<use value="in"/>
<min value="0"/>
<max value="*"/>
<documentation
value="Optional resources (CodeSystem, ValueSet, ConceptMap) to front-load into the cache when mode=start, so they are immediately in scope for subsequent calls that carry the cache-id. Resources may also be added incrementally on later $validate-code / $expand calls (unless the cache is sealed)."/>
<type value="Resource"/>
</parameter>
<parameter>
<name value="sealed"/>
<use value="in"/>
<min value="0"/>
<max value="1"/>
<documentation
value="Used with mode=start: whether the cache is sealed. A sealed cache (the default) contains only the resources front-loaded in this call and does not grow; an unsealed cache (sealed=false) additionally accumulates resources it sees on subsequent calls, and is what makes incremental population and batch front-loading possible. If omitted, the server's default applies (which SHOULD be true); a client that requires a particular behaviour should set this explicitly and check the sealed value returned in the response."/>
<type value="boolean"/>
</parameter>
<parameter>
<name value="cache-id"/>
<use value="out"/>
<min value="0"/>
<max value="1"/>
<documentation
value="The server-issued cache identifier, returned by mode=start. The client sends this value as the X-Cache-Id HTTP header on subsequent requests that should use the cache. Absent if no cache was created."/>
<type value="id"/>
</parameter>
<parameter>
<name value="sealed"/>
<use value="out"/>
<min value="0"/>
<max value="1"/>
<documentation
value="Whether the cache is sealed. A mode=start response always includes it, so the client does not have to assume a default - it states authoritatively whether the cache is fixed at what was front-loaded (sealed=true) or will grow as further resources are seen (sealed=false). A mode=check response includes it for a cache that is still valid, so a client can confirm what it is actually working with. The minimum cardinality is 0 because it is not returned by mode=end, nor by a mode=check that reports valid=false; it is nonetheless mandatory in a mode=start response."/>
<type value="boolean"/>
</parameter>
<parameter>
<name value="valid"/>
<use value="out"/>
<min value="0"/>
<max value="1"/>
<documentation
value="Returned by mode=check: whether the cache named in the X-Cache-Id header is still held by this server. Mandatory in a mode=check response (the minimum cardinality is 0 only because the parameter is not returned by the other modes). Note that a mode=check that finds nothing is still a successful operation - it returns HTTP 200 with valid=false, not an error - so that a client can distinguish a server that reports the cache is gone from a server it could not reach at all. The two call for opposite responses: the first means start a new cache, the second means retry."/>
<type value="boolean"/>
</parameter>
<parameter>
<name value="resource-count"/>
<use value="out"/>
<min value="0"/>
<max value="1"/>
<documentation
value="Returned by mode=check for a valid cache: how many resources the cache currently holds. Informational - useful for confirming that incremental population of an unsealed cache is working as the client expects."/>
<type value="unsignedInt"/>
</parameter>
<parameter>
<name value="idle"/>
<use value="out"/>
<min value="0"/>
<max value="1"/>
<documentation
value="Returned by mode=check for a valid cache: how many seconds it had been since the cache was last used, measured before this check reset the timer. A client can compare this against the `timeout` to see how close it came to losing the cache, and adjust how often it checks."/>
<type value="unsignedInt"/>
</parameter>
<parameter>
<name value="timeout"/>
<use value="out"/>
<min value="0"/>
<max value="1"/>
<documentation
value="Returned by mode=check for a valid cache, where the server is willing to say: how many seconds a cache may go unused before this server releases it. This lets a client size its checking interval to the server it is actually talking to, rather than guessing at a value it has no other way to discover. A server that has no idle timeout, or does not wish to state one, omits this - a client that gets no value should choose a conservative interval of its own."/>
<type value="unsignedInt"/>
</parameter>
<parameter>
<name value="outcome"/>
<use value="out"/>
<min value="0"/>
<max value="1"/>
<documentation
value="Returned by mode=check when valid=false: an OperationOutcome explaining why the cache is not available, with an issue carrying the code `cache-id-unknown` from http://hl7.org/fhir/tools/CodeSystem/tx-issue-type - the same coded issue a request that used the cache-id would have failed with. Servers SHOULD make the diagnostics say which fate the cache met (never issued by this server, released by the client, or timed out after a period of not being used), since those point at quite different problems."/>
<type value="OperationOutcome"/>
</parameter>
</OperationDefinition>