Skip to main content

Prescribing Frequencies: The FHIR Way

Understanding this is a frequent request 😎, now revealed!​

How It Works​

This document explains how our prescription frequencies should be stored in MedicationRequest and in ServiceRequest FHIR resource. Mona 3 architecture will support the all possibilities FHIR provides to store and process various frequencies. Frequencies have a correlation with how Task-List will be generated hence, Mona 2 will only have limited possibilities to store and process various frequencies.

Self-Sufficient Prescriptions with Full FHIR Frequency Storage​

The primary goal of storing comprehensive frequency information directly within FHIR resources (like MedicationRequest and ServiceRequest) is to make them self-sufficient.

info

âš¡ Performance Boost: By having all frequency-related details readily available, we eliminate the need for time-consuming lookups in external Terminology DB tables such as FrequencyTime and PrescriptionFrequencies.

This offers several key advantages:

  • Faster Processing: When handling FHIR resources or generating Task-List recommendations, all necessary frequency data is immediately accessible. Say goodbye to delays caused by terminology database queries!

  • Improved UI Responsiveness: The user interface can directly display the correct, user-friendly names for various frequencies without making extra calls to terminology endpoints. This results in a smoother and more efficient user experience.

  • Future-Proof External Integration: 🔗 In the future, external services will be able to directly interpret the frequency information within the FHIR resource itself, enhancing interoperability and reducing dependencies.

Benefit

✅ Key Benefit: Making FHIR resources self-contained with complete frequency information streamlines data access, boosts performance, and facilitates easier integration with external systems.

Mona frequencies​

Timing Structure​

The Timing data type in FHIR is used to describe the occurrence of an event that may happen multiple times. It specifies when events are expected or requested to occur and can also summarize past or ongoing events. While the definitions of Timing components often refer to 'future' events for simplicity, they can also describe historic or ongoing events.

A Timing schedule can include:

  • A list of specific events (using event).
  • Criteria for when the event happens, expressed in a structured form (using repeat).
  • A code representing a common timing pattern (using code).
  • When both a list of events and a repeating specification are provided, the event list clarifies the information in the repeat structure.
{
// from BackboneElement: extension, modifierExtension
"event" : ["<dateTime>"], // When the event occurs
"repeat" : { // When the event is to occur
// bounds[x]: Length/Range of lengths, or (Start and/or end) limits. One of these 3:
"boundsDuration" : { Duration },
"boundsRange" : { Range },
"boundsPeriod" : { Period },
"count" : "<positiveInt>", // Number of times to repeat
"countMax" : "<positiveInt>", // Maximum number of times to repeat
"duration" : <decimal>, // How long when it happens
"durationMax" : <decimal>, // How long when it happens (Max)
"durationUnit" : "<code>", // s | min | h | d | wk | mo | a - unit of time (UCUM)
"frequency" : "<positiveInt>", // Event occurs frequency times per period
"frequencyMax" : "<positiveInt>", // Event occurs up to frequencyMax times per period
"period" : <decimal>, // Event occurs frequency times per period
"periodMax" : <decimal>, // Upper limit of period (3-4 hours)
"periodUnit" : "<code>", // s | min | h | d | wk | mo | a - unit of time (UCUM)
"dayOfWeek" : ["<code>"], // mon | tue | wed | thu | fri | sat | sun
"timeOfDay" : ["<time>"], // Time of day for action
"when" : ["<code>"], // Code for time period of occurrence
"offset" : "<unsignedInt>" // Minutes from event (before or after)
},
"code" : { CodeableConcept } // BID | TID | QID | AM | PM | QD | QOD | +
}

Constraints​

The following rules apply to the Timing.repeat element:

  • If duration is present, durationUnit must also be present.
  • If period is present, periodUnit must also be present.
  • duration must be a non-negative value.
  • period must be a non-negative value.
  • If periodMax is present, period must also be present.
  • If durationMax is present, duration must also be present.
  • If countMax is present, count must also be present.
  • If offset is present, when must be present, and when cannot be one of 'C', 'CM', 'CD', or 'CV'.
  • timeOfDay and when cannot both be present.
Storing Timing in ServiceRequest and MedicationRequest

Key Difference: There's a difference in how timing information is stored between MedicationRequest and ServiceRequest, which is important to understand for data consistency.

MedicationRequest: Timing is located within the dosageInstruction field. dosageInstruction is an array. Each element in the dosageInstruction array represents a Dosage, and a Dosage object holds the Timing details. This array structure allows for specifying multiple dosage instructions, each with its own timing.

ServiceRequest: Timing is stored in the occurrenceTiming field. occurrenceTiming is a single object. This single-object structure means that ServiceRequest can only represent one timing schedule. It does not inherently support multiple, distinct timing occurrences.

Mona frequencies and their correlation with Task-List​

There are the below types of frequencies we used in our Mona application:

  1. Minutely
  2. Hourly
  3. Daily
  4. Weekly
  5. Once
  6. Continuous
  7. As-Needed
These frequencies affect Task-list generation

Minutely, Hourly, Daily, Weekly, Once and Custom prescription frequencies generate tasks, while Continuous and As-Needed* do not.

Special Case

Special Case for As-Needed:

Frequency type, As-Needed prescriptions do not generate tasks, even though they also contain frequency information within their Timing object in the FHIR resource.

Essential Fields and rules of Frequency Timing in Task-List generation​

  • boundsDuration
  • count
  • period
  • periodUnit
  • dayOfWeek
  • timeOfDay
Rules for Task-list generation

Important Rules!​

  1. Supported periodUnit for task list generation are: min | h | d | wk
  2. Frequencies like Hourly and Minutely task list recommendation will always start from the boundsPeriod's start time.
  3. For task-list generation frequency and period should be non-negative and non-zero value.
  4. For Daily frequency the number of entries in timeOfDay should match with the frequency value.
  5. For Weekly frequency the number of entries in dayOfWeekshould match with the frequency value.
  6. For Once frequency it is require to have exactly one entry present in timeOfDay its optional to have one entry in dayOfWeek present. If only timeOfDay is present task-list recommendation generated for the next immediate possible time which is in between start and end mentioned in boundsPeriod If both timeOfDay and dayOfWeek present task-list recommendation generated for the next possible day mentioned in the dayOfWeek and time mentioned in the timeOfDay which is also in between the start and end mentioned in boundsPeriod.
  7. Task-list recommendation will not be generated if the count has any other value than the 1.
  8. If count is present frequency, period and periodunit is optional.

Common Fields for Frequency Timing​

For all frequency types, the start and end dates of the prescription are typically stored within the boundsPeriod object under the repeat property of the timing element:

  • The start field within boundsPeriod is required, indicating when the prescription becomes active.
  • The end field within boundsPeriod is optional, specifying when the prescription should cease. If omitted, it implies the prescription continues indefinitely or until otherwise specified.

Minutely Frequency​

For prescriptions with a minutely frequency, the repeat object within the timing element will have the following properties:

  • periodUnit: This will always be set to "min" to denote hours.
  • frequency: This will always be 1, indicating one event per the defined period.
  • period: This numerical value specifies the interval in minutes between administrations. For example, 30.0 indicates a frequency of every 30 minutes.
Example
{
"dosageInstruction": [
{
"timing": {
"repeat": {
"boundsPeriod": {
"start": "2025-04-28T07:10:41.138Z",
"end": "2025-07-01T00:00:00Z"
},
"frequency": 1,
"period": 30.0,
"periodUnit": "min"
}
}
]
}

Hourly Frequency​

For prescriptions with an hourly frequency, the repeat object within the timing element will have the following properties:

  • periodUnit: This will always be set to "h" to denote hours.
  • frequency: This will always be 1, indicating one event per the defined period.
  • period: This numerical value specifies the interval in hours between administrations. For example, 4.0 indicates a frequency of every 4 hours.
Example
{
"dosageInstruction": [
{
"timing": {
"repeat": {
"boundsPeriod": {
"start": "2025-04-28T07:10:41.138Z",
"end": "2025-07-01T00:00:00Z"
},
"frequency": 1,
"period": 4.0,
"periodUnit": "h"
}
}
]
}

Generating Task-List Recommendations:

When generating task-list recommendations for hourly frequencies, the start and end dates from the boundsPeriod are the primary drivers. It's important to note that the start and end date-time values can include minutes and seconds that are not rounded off.

Task list recommendations for hourly frequencies should be generated precisely based on the start time provided in the boundsPeriod. For an hourly frequency with a period of 4 hours and a start time of 2025-04-28T07:10:41.138Z, the subsequent task recommendations will be scheduled by adding the period (in hours) to the initial start time. This results in timestamps like:

2025-04-28T07:10:41.138Z
2025-04-28T11:10:41.138Z
2025-04-28T15:10:41.138Z
... and so on, every four hours.

Daily and/or Custom Frequency​

For prescriptions with a daily or custom frequency, the repeat object within the timing element will have the following properties:

  • periodUnit: This will always be set to "d" to denote days.
  • period: This will always be 1, indicating that the frequency is applied over a one-day period.
  • frequency: This numerical value specifies how many times the event should occur within that single day. For example, a value of 4 signifies four administrations per day.
  • timeOfDay: This is an array of strings, where each string represents a specific time of day when the medication should be administered. The time is stored in "HH:MM:ss" format (e.g., "06:00:00" for 6:00 AM).

Distinction between Daily and Custom Frequencies:

The primary difference between "Daily" and "Custom" frequencies lies in how the timeOfDay array is populated:

  • Daily Frequency: The times listed in timeOfDay are typically fetched from a predefined list will be available as the template or DB table or a map (yet to be defined!)

  • Custom Frequency: The times in timeOfDay are specified directly by the user, allowing for more flexible and individualized dosing schedules.

Local Time

It's important to note that the times stored in the timeOfDay array are in the server's local time.

Example
{
"dosageInstruction": [
{
"timing": {
"repeat": {
"boundsPeriod": {
"start": "2025-04-28T07:10:41.138Z",
"end": "2025-07-01T00:00:00Z"
},
"frequency": 4,
"period": 1,
"periodUnit": "d",
"timeOfDay": [
"06:00:00",
"08:00:00",
"15:00:00",
"20:00:00"
]
}
}
]
}

Generating Task-List Recommendations:

To generate the task list for Daily and Custom frequencies, the system iterates through the timeOfDay array. For each day within the boundsPeriod (from the start date to the end date), a task recommendation is created for each time specified in the timeOfDay array. The date for each recommendation will increment daily, while the time will be taken from the timeOfDay entries.

Weekly Frequency​

For prescriptions with a weekly frequency, the repeat object within the timing element will have the following properties:

  • periodUnit: This will always be set to "wk" to denote days.
  • period: This will always be 1, indicating that the frequency is applied over a one-week period.
  • frequency: This numerical value specifies how many times the event should occur within that single week. For example, a value of 4 signifies four administrations per week.
  • timeOfDay: This is an array of strings, where each string represents a specific time of day when the medication should be administered. The time is stored in "HH:MM:ss" format (e.g., "06:00:00" for 6:00 AM).
  • dayOfWeek: This is an array of strings, where each string represents a specific day of the week when the medication should be administered. The day string should be from one of the following options mon | tue | wed | thu | fri | sat | sun
Local Time

It's important to note that the times stored in the timeOfDay array are in the server's local time.

Example
{
"dosageInstruction": [
{
"timing": {
"repeat": {
"boundsPeriod": {
"start": "2025-04-28T11:53:17.490Z",
"end": "2026-01-01T00:00:00Z"
},
"frequency": 2,
"period": 1.0,
"periodUnit": "wk",
"timeOfDay": [
"14:00:00"
],
"dayOfWeek": [
"mon",
"wed"
]
}
}
]
}

Generating Task-List Recommendations for Weekly Frequencies:

To create the task list for prescriptions with weekly frequencies, the system utilizes both the timeOfDay and dayOfWeek arrays. For each day within the specified boundsPeriod (spanning from the start date to the end date), the system checks if that day matches any of the days listed in the dayOfWeek array. If a match is found, a task list recommendation is generated for each time specified in the timeOfDay array for that particular day. The date of each recommendation will increment daily as the system iterates through the boundsPeriod. The specific day of the week for the recommendation will be determined by the dayOfWeek array, and the time of day will be taken from the timeOfDay array.

Limitation in Mona 2

Important Limitation!

If a prescription requires different administration times on different days of the week (e.g., Monday at 10:00:00 and Wednesday at 14:00:00), this cannot be achieved with a single frequency (Timing object). Task-List will account for it and generate the recommendations accordingly.

To handle such scenarios, it is necessary to create two separate frequency (Timing object), one for each day of the week with its specific time of day.

Note: Only the MedicationRequest FHIR resource supports multiple frequencies via dosageInstruction. This does not apply to the ServiceRequest FHIR resource.

Once frequency (Einmalig)​

For prescriptions with a once frequency, the repeat object within the timing element will have the following properties:

  • timeOfday: This is an array of strings, where each string represents a specific time of day when the medication should be administered. The time is stored in "HH:MM:ss" format (e.g., "06:00:00" for 6:00 AM). It should not have more than one string present in the array, as it should be administered only once.
  • count: It will always be set to 1 indicating only one time to be administered.
Example
{
"dosageInstruction": [
{
"timing": {
"repeat": {
"boundsPeriod": {
"start": "2025-04-28T07:10:41.138Z",
"end": "2026-01-01T00:00:00Z"
},
"timeOfDay": [
"06:00:00"
],
"dayOfWeek": ["mon"],
"count": 1
}
}
}
]
}

Generating Task-List Recommendations for "Once" Frequency:

For prescriptions with a "once" frequency, the system refers to the time specified in the timeOfDay array. A task list recommendation will be generated only once within the entire duration defined by the boundsPeriod. This single recommendation will occur on the start date of the boundsPeriod at the time specified in the timeOfDay array.

As-needed (Bei Bedarf) Frequency​

For prescriptions with an as-needed frequency, the timing object will have a boolean field named asNeededBoolean. For as-needed frequency it will always be true and along with ít repeat object within timing object will have boundsPeriod

Example
{
"dosageInstruction": [
{
"timing": {
"repeat": {
"boundsPeriod": {
"start": "2025-04-28T11:17:03.167Z",
"end": "2026-01-01T00:00:00Z"
}
}
},
"asNeededBoolean": true
}
]
}
Task-List Recommendations

Task-list recommendation for the as-needed frequency will not be generated.

Continuous Frequency​

For prescriptions with a continuous frequency, the repeat object within timing object will only have boundsPeriod.

Example
{
"dosageInstruction": [
{
"timing": {
"repeat": {
"boundsPeriod": {
"start": "2025-04-28T07:10:41.138Z",
"end": "2026-01-01T00:00:00Z"
}
}
}
}
]
}
Task-List Recommendations

Task-list recommendation for the continuous frequency will not be generated.

Bonus: Intermittent Infusion​

Intermittent Infusion is handled similarly as Daily and/or Weekly frequencies. Only difference here is Intermittent Infusion contains duration and durationUnit attributes. They have no direct relation with the task-list. Duration should be interpreted as how much long a medication should be administered.

Example
{
"dosageInstruction": [
{
"timing": {
"repeat": {
"boundsPeriod": {
"start": "2025-04-28T07:10:41.138Z",
"end": "2026-01-01T00:00:00Z"
},
"timeOfDay": [
"06:00:00"
],
"dayOfWeek": ["mon"],
"duration": 30,
"durationUnit": "min"
}
}
}
]
}

Appendix​

Examples of common uses of the Timing Data Type criteria from FHIR documentation​

descriptiondurationdurationUnitfrequencyfrequencyMaxperiodperiodUnitperiodMaxwhenbounds[x]code
Every 8 hours8h
Every 7 days7d
3 times a day31dTID
3-4 times a day341d
Every 4-6 hours4h6
Every 21 days for 1 hour1hr21d
Three times a week for ½ hour0.5hr31wk
With breakfastCM
For 5 minutes, 10 minutes before meals5minAC
1 tablet 3 times daily, 30 minutes before meals31dAC
BID, 30 mins before meal, for next 10 days21dACboundsPeriod.end = +10dBID
Duration = 10 days TID, for 14 days31dboundsPeriod.end = +14dTID
Duration = 14 days BID, start on 7/1/2015 at 1:00 PM21dboundsPeriod.start = 2015-07-01T13:00:00BID
Mon, Wed, Fri Morning1dMORNdayOfWeek = mon, wed, fri
Every day at 10am1dtimeOfDay = 10:00
Take once, at any time1
Take every second day, in the morning, until 20 have been taken2dMORNbounds[x].count = 20
Twice a day, starting 2024-01-15, ending 2024-01-2221dboundsPeriod.start = 2024-01-15, boundsPeriod.end = 2024-01-22BID
Daily at 9am, 1pm, and 5pm31dtimeOfDay = 09:00, 13:00, 17:00
Every other week, on Tuesdays12wkdayOfWeek = tueQOD
Three times a day for ten days31dboundsDuration = 10 dTID