Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Excerpt

This page describes Catalogue of design guides and best practices for developing Telemetric solutions on top of the eHealth domain services.using the eHealth infrastructure.

The design guides outline rules, standards, and recommendations for designing Telemedicine solutions. The design guides provide a consistent framework for design, ensuring uniformity and coherence across Telemedicine Solutions.

Best practices are general strategies, methods, or techniques that should be used to achieve desired results effectively and efficiently.

Content

Table of Contents
minLevel1
maxLevel7

The best practices and design guidelines are elaborated below.

Best practices

Design guidelines

#1 Develop your own API Gateway (or BFF) to aggregate multiple downstream calls

The “API Gateway” pattern can be a useful pattern for the eHealth architectures where there are a small number of backend services.

BFF is a variation of the API Gateway pattern and defines a separate API gateway optimized for each kind of client.

...

Using an API gateway has the following benefits:

  • Isolate the clients from how the application is partitioned into microservices

  • Isolated the clients from the problem of determining the locations of service instances

  • Simplifies the client by moving logic for calling multiple services from the client to the API gateway

  • Reduces the number of requests/roundtrips. For example,

  • The API gateway enables clients to retrieve data from multiple services with a single round-trip. Fewer requests also mean less overhead and improve the user experience.

  • Translates from a “standard” public web-friendly API protocol to whatever protocols are used internally

Read more on the API Gateway and BFF pattern here:

#2 Minimize the amount of data that the application (or backend-for-frontend) has to calculate on

Try to minimize the amount of data that the telemedicine solution (or backend-for-frontend) has to calculate on, as fetching too much and unnecessary data puts an extra load on the BFF, and complicates the BFF.

Minimize the amount of data can be done by:

  • Target user interface design to microservices (see above Design Guide)

  • Avoid prefetch of data e.g. details view in a master-detail pattern

  • Prefer calling eHealth services directly, only use BFF pattern if needed

#3 Use caching of administrative data in application as a mechanism for achieving better performance

Caching is provided by the eHealth Infrastructure that performs server-side caching but can also be done in solutions or applications.

Guide:

  • Use caching in applications as a mechanism for achieving better performance

  • Enforce “eHealth access control” for access information in the cache

  • Use ”Backend for frontend” or API Gateway patterns to share the cache between clients

Recommendation:

  • Cache ‘static’ data (e.g., administrative data) such as

    • PlanDefinition

    • ActivityDefinitions

    • Organisations

    • etc.

  • Avoid cache ‘live’ data (e.g. clinical information)

  • Use eHealth domain events for cache invalidation.

See Telemedicine Solutions caching of information from the infrastructure for recommendations on caching in telemedicine solutions and applications.

See https://ehealth-dk.atlassian.net/wiki/spaces/EDTW/pages/1034354702/Technical+Interactions+with+Services#Caching-on-Searching on caching provided by the infrastructure.

#4 Retrieve clinical data on-demand (avoid pre-fetching)

Generally, first, retrieve clinical data when needed to avoid the risk of having stale clinical data

If you are lucky, you may know enough about what your users will do next, and thereby be able to prefetch the data they need before it's needed. But really consider if prefetching is needed. Is the BFF response time better than eHealth services?

Prefetching data may result in the prefetch data being stale, and prefetching too many items increases the load on the eHealth Infrastructure.

See https://ehealth-dk.atlassian.net/wiki/spaces/EDTW/pages/1034354702/Technical+Interactions+with+Services#Caching-on-Searching on caching provided by the infrastructure.

See Telemedicine Solutions caching of information from the infrastructure for recommendations on caching in telemedicine solutions and applications.

#5 Take advantage of the eHealth FHIR Service caching

Guide:

  • Make use of eHealth FHIR Service Caching to achieve better response times

  • The caching is based on the principles described in HAPI FHIR Search Result Caching: https://hapifhir.io/hapi-fhir/docs/server_jpa/configuration.html

  • This cache is used when identical searches are performed (same search parameters)

  • Search results will be cached for a limited period (e.g. 1 minute)

Note that clients can selectively disable caching for an individual request using the Cache-Control header:

Cache-Control: no-cache

See https://ehealth-dk.atlassian.net/wiki/spaces/EDTW/pages/1034354702/Technical+Interactions+with+Services#Caching-on-Searching on caching provided by the infrastructure.

#6 Take advantage of the eHealth Infrastructure Event Model

Guide:

  • Telemedicine Solutions should subscribe to events, instead of polling for changes.

  • Telemedicine Solutions can use Infrastructure events to trigger functionality

The eHealth Infrastructure publish simple events at a CRUD resource level e.g.

  • patient created,

  • patient updated,

  • care plan created,

Applications should subscribe to events, instead of polling for changes. Using events is considered more effective than polling for changes.

The events can be used in applications to e.g. update cached information.

image-20240828-060012.pngImage Added

#7 Design the operation and content of the user interfaces to microservice architecture

Guide:

  • Design user interfaces in such a way that there is a minimum need to combine large amounts of data

  • Target user interface and workflows to only require data from one (or a few) microservices.

  • Target the workflows so that data is only retrieved when they are to be used.

Avoid designing a single User Interface that collects data from many of the eHealth microservices into one table or view.

A suggested approach could be to use the same microservices strategy to the user interface itself by e.g. introducing micro-apps or micro frontend patterns.

If the application needs to aggregate information from several FUT Infrastructure services, it should be considered whether the BFF beneficially could cache static or semi-static information.

#8 Design for and recognize other clients may have updated the resources

Guide:

  • Design for and recognize other clients may have updated the resources.

  • A combination of the ETag and If-Match  header can prevent one client update the same resource, and the second overwrites the updates of the first

Avoid requesting (polling) for updates from the user interface, leading to

  • Require unnecessary processing and polling of data.

  • Extra load on the eHealth infrastructure that may reduce response time.

  • Only do an auto-update of the user interface if really needed.

A ‘better’ option is to recognize other clients may have updated the resources.

  • A combination of the ETag  and If-Match  header can prevent one client from updating the same resource, and the second overwrites the updates of the first

If the client wishes to request a version-aware update, it submits the request with an If-Match header that quotes the ETag from the server:

Code Block
PUT /Patient/347 
HTTP/1.1 If-Match: W/"23" 

If the version ID given in the If-Match header does not match, the server returns a “412 Precondition Failed” status code instead of updating the resource.

#9 Make effective use of the user-selected contexts

Make effective use of the end user-selected context and thereby the results returned by the eHealth services

Use the information in context (patient, episode-of-care, care team..) as a parameter in querying the FHIR services to limit the results.

If e.g., the user has set the context (patient, episode-of-care, care team ..) the context can be used to:

  • Provide as parameter in querying the FHIR services to limit the results, the eHealth services will then filter and limit the results returned to the client.

    • E.g., only episodes of care relevant to the selected care team

    • E.g., only tasks relevant to the selected care team

  • Reduce response times from eHealth services

  • Minimize data and thereby work in telemedicine solutions or applications.

  • Reduce the risk of UTH (adverse events, Danish: utilsigtet hændelse)

The context can be considered as three levels of context for Attribute Based Access Control:

  1. Use the care team for searching across resources (avoid Patient and Episode-Of-Care)

  2. Use the patient context for more specific results

  3. The episode-of-care limits the results further. The EOC is often required for updates.

Best practices

Info

NOTICE, example URLs in the following are just examples. Please look at the capability statement in the Implementation Guide for the actual capabilities.

Furthermore, the infrastructure develops and capabilities may change.

#1 Optimize call pattern (call in parallel and do not retrieve data one row at a time)

The eHealth infrastructure effectively supports parallel requests. If an Application or BFF needs to request data from different services, prefer parallel calls instead of sequential calls if possible.

Practice

  • Make use of the eHealth services scaling that allows the infrastructure can handle parallel requests.

  • If an Application (or BFF) needs to request data from different services, prefer parallel calls instead of sequential calls if possible.

Avoid:

  • Do not call one microservice at a time if the call to the “next” service is not dependent on the previous call.

However, when calling with many concurrent threads from BFFs, it may be problematic for the infrastructure (similar to DDoS attacks).

#2 Limit the number of context changes to what is necessary

In regards to the Design Guides “Make effective use of the selected context” do this with care.

Changing context comes with a penalty. Selecting or changing context results in the user ID, access token etc. being refreshed for the specific security context.

Therefore try to limit the number of context changes.

#2 Use the search APIs' counting options to limit the results to the client

The eHealth infrastructure services support count, to keep the load on clients, servers and the network minimized.

Counts are used to limit the number of resources fetched from the database or server.

Example URL to invoke this method:

Code Block
GET [base]/Patient?identifier=urn:foo|123&_count=10

See also: http://www.hl7.org/implement/standards/fhir/search.html#count

#3 Take advantage of the opportunity for paging in the Infrastructure

The Some of the eHealth services provides provide support for paging of results.

That is, eHealth API users only need to request to amount of data that is actually needed, and the limiting of the results can be done at the server or database level.

API users can define a _offset parameter in the request which means that when combined with _count the paging is done on the database level.(The eHealth infrastructure has a default page size (i.e. default _count if not given) and maximum page size (i.e. maximum value for the _count parameter).

Example URL to invoke this method for the first page (assuming page size of 10):http://fhir.example.com

Code Block
GET [base]/Patient?identifier=urn:foo|123&_count=10&_offset=0

Example URL to invoke this method for the second page:http://fhir.example.com

Code Block
GET [base]/Patient?identifier=urn:foo|123&_count=10&_offset=10

Limit the scope of context changes to what is necessary

(warning) Under construction.

The eHealth infrastructure has a default page size (i.e., default _count if not given) and maximum page size (i.e., maximum value for the _count parameter).

#5 Apply filtering to searches

...

to get a smaller and more accurate result

...

(warning) Under construction.

Use the search APIs' counting options (Limiting results (_count))

eHealth infrastructure services supports count, to keep the load on clients, servers and the network minimized.

Count may be used to limit the number of resources fetched from the database or server.

Example URL to invoke this method:

http://fhir.example.com/Patient?identifier=urn:foo|123&_count=10

See also: Search - FHIR v4.0.1 (hl7.org)

...

Searching for resources is fundamental to the mechanics of FHIR.

Generally, FHIR uses “AND” between the parameters in searching.

Best practice

  • Retrieve multiple ids in one call, instead of multiple gets on each id.

  • Use time constraints in searches to get a smaller and more accurate result

...

(warning) Under construction

Optimize call pattern (call in parallel and do not retrieve data one row at a time)

(warning) Under construction

Retrieve data on-demand where possible

(warning) Under construction

Careful using chained resource references

The eHealth services has limited support for chained resource references.

FHIR has the concept of chained resource references. That is, references may also support a "chained" value. For example, you might want to search for DiagnosticReport resources by subject, but use the subject's last name instead of their resource ID. In this example, you are chaining "family" (the last name) to "subject" (the patient).

The net result in the query string would look like:

http://fhir.example.com/DiagnosticReport?subject.family=SMITH

What this query says is "fetch me all of the DiagnosticReport resources where the subject (Patient) of the report has the family (name) of 'SMITH'".

Due to the nature of eHealth microservices resources are split into separate services, and therefore limited support for chained resource references, and therefore be careful using these.

Design guidelines

Take advantage of the opportunity for caching

...

  • A common scenario in searches is to allow searching for resources with values (i.e. timestamps) within a range of dates. Some searches allow for search on multiple IDs, instead of multiple gets on each ID.

  • Use time constraints in searches to get a smaller and more accurate result. Example,

    • A range of &date=gt2022-01-01&date=lt2022-02-01 is any date within January 2022.

Code Block
GET [base]/Appointment?subject.identifier=7000135&start=gt2022-01-01&start=lt2022-02-01
  • The search parameter _lastUpdated can be used to select resources based on the last time they were changed:

Code Block
GET [base]/Appointment?_lastUpdated=gt2022-02-01

This search finds any Appointments changed since 1- February 2022.

See also:

...

...

...

Make the most of context choices (mainly the careteam context)

(warning) Under construction

Avoid unnecessary pre-fetching of data

(warning) Under construction

Make the task overview task / message-centric rather than a patient-centric

(warning) Under construction

Target the operation (and scope) of the user interfaces to the workflows

(warning) Under construction

Avoid unnecessary auto-updates of the user interface

(warning) Under construction

Take advantage of Infrastructure events (mq)

Take advantage of Infrastructure events (mq) for listening to resource changes and perform cache invalidation.

See https://ehealth-dk.atlassian.net/wiki/spaces/EDTW/pages/1177911316/Caching#Cache-invalidation-using-events for events.

Minimize the amount of data that the backend-for-frontend (BFF) has to calculate on

...

#6 Limited support for chained resource references

FHIR allows reference parameters may be "chained"

Practice:

  • Use chained searches to avoid subsequent calls to the same FHIR Services and save a client from performing a series of search operations.

To save a client from performing a series of search operations, FHIR allows reference parameters may be "chained" by appending them with a period (.). Example:

Code Block
GET [base]/CarePlan?subject.name=peter

Return all the care plans that have a subject whose name includes "Peter “.

However, due to the eHealth microservice architecture and resources being handled by individual microservices, the chained parameters are only possible with the same service. That is, limited to resources handled by the same service.