Skip to main content
NewNMC’s advertising guidelines for doctors are in force from 6 Oct 2026. See what to change, and get a free compliance auditNew NMC advertising rules for doctors: what to change
Website

ISR for Doctor Rosters: Daily Schedule Changes Without Full Rebuilds

Keep doctor timetables accurate without full rebuilds. Map HIS roster changes to cache tags, choose stale-while-revalidate or immediate expiry, and avoid multi-instance ISR pitfalls.

ISR for Doctor Rosters: Daily Schedule Changes Without Full Rebuilds

This post is for the web team or marketing technologist at a hospital whose doctor pages show OPD days and timings, and whose rosters change every day. A consultant is on leave on Thursday, a clinic moves from the second floor to the annexe, a visiting specialist adds a Saturday slot. The hospital information system (HIS) knows within minutes. The website often learns days later, or never, because updating it means a developer, a deployment or an editor remembering.

It answers a specific engineering question: how do you keep statically generated doctor pages accurate when the schedule changes daily, without rebuilding the whole site for each change? The method is on-demand revalidation in Next.js, driven by roster events from the HIS, with cache tags that map a change to exactly the pages it affects. The examples describe our approach to revalidation on Next.js builds in general terms; they contain no client data, and the numbers used are hypothetical.

It assumes you already use, or are considering, a Next.js App Router front end. The content model behind doctors and placements is a separate subject; see our headless CMS and provider bio pages services for that side.

Roster is not availability

Separate two things that are often confused.

Roster is the planned pattern: Dr A consults at Location 2 on Monday, Wednesday and Friday from 10:00 to 13:00 in room 214. It changes a few times a month per doctor, occasionally daily across a large staff.

Availability is the live state of bookable slots on a given date. It changes every few minutes as patients book.

The first suits static generation with on-demand updates. The second does not. Do not try to bake availability into a cached page; fetch it on the client or at request time from the scheduling system, and keep the roster page as the stable frame around it. A page can say "Mon, Wed, Fri, 10:00 to 13:00" statically and load "next available: Friday" from an API. If the API is slow or down, the static roster still shows. This split is also kinder to your Core Web Vitals, since the static HTML paints quickly.

Our appointment scheduling build follows the same split.

How Next.js revalidation works, as of the current docs

The Next.js ISR guide describes the cycle. A page is prerendered and cached. After invalidation, the next request still receives the cached (stale) page while a fresh version generates in the background; once ready, later requests receive the new version. Time-based revalidation (export const revalidate = 3600) invalidates after an interval. On-demand revalidation invalidates when you call a function.

Two functions matter:

  • revalidatePath invalidates specific paths or layouts.
  • revalidateTag invalidates all cached data carrying a tag, across every page that uses it.

The `revalidateTag` reference gives the current signature: a tag and a second argument. The recommended max profile marks data stale and serves stale content while revalidation runs in the background. The single-argument form is deprecated. { expire: 0 } means stale content is never served and the next request is a blocking revalidation, the right choice where the caller needs the data gone immediately and updateTag is not available, which is the case for webhooks and calls from other services. Tags are case-sensitive and limited to 256 characters.

An important point from the documentation: a revalidation is triggered by a request, not by the revalidateTag call. Pages refresh as they are visited. A rarely visited doctor page will stay stale in cache until someone requests it, then refresh. That is fine for most pages, because the first visitor after the change may still see the old version under max, which is a trade-off to consider for rosters.

Choosing stale-while-revalidate or immediate expiry

The profile you choose encodes a business rule about how wrong a page is allowed to be.

ChangeRisk if shown staleSuggested handling
Added consultation dayPatient does not see a new option; low harmmax (stale while revalidating)
Time shifted by an hourPatient arrives at the wrong time{ expire: 0 }
Doctor on leave or clinic cancelledPatient travels for nothing{ expire: 0 } and a visible notice
Room or floor changedPatient goes to wrong place{ expire: 0 }
Bio or photo editCosmeticmax

For schedule reductions and changes, prefer immediate expiry. The cost is that the next visitor waits for a fresh render rather than being served stale content. For a doctor page that renders in a fraction of a second, this is acceptable. If roster-critical pages are heavy, trim them rather than accept stale clinic times.

Tag design

Tags make the HIS event map to pages with no knowledge of URLs. Define at the data-fetching layer, not in the page:

  • roster:doctor:{doctorId} on any fetch that reads that doctor's schedule
  • roster:location:{locationId} on any fetch that lists doctors at a location
  • roster:department:{departmentId} on department listings that show "available this week"
  • roster:all on the rare global components, such as a "doctors on duty today" widget

A fetch is tagged with next: { tags: [...] }, and functions using 'use cache' call cacheTag. The reference page shows both forms. One roster change event for Dr A at Location 2 triggers roster:doctor:A and roster:location:2. The doctor profile, the location page, and any department listing that includes her are all invalidated. No other page is touched.

Keep tags coarse enough to maintain. Tagging every field separately creates a map nobody can reason about. One tag per entity per concern is usually enough.

The pipeline from HIS to page

A typical flow:

  1. Event source. The HIS or the scheduling module emits a change, or you poll for changes.
  2. Normaliser. A small service converts the vendor format into your own event: { type: "roster.changed", doctorId, locationId, effectiveFrom, changeKind }. It also strips anything that is not roster data. The event must not contain patient information, and nothing patient-related should ever reach the website layer.
  3. Queue or buffer. Events are queued, so a burst of changes (a department-wide rota update at 6 pm) does not flood the site.
  4. Revalidation endpoint. A Route Handler receives the event over HTTPS, checks a shared secret, validates the payload shape, maps changeKind to a profile, and calls revalidateTag.
  5. Verification. Optionally, request the affected URLs and check the response.

Many hospital HIS products do not offer webhooks. If yours does not, run a poller that reads the roster export every few minutes, hashes each doctor's schedule, compares with the last hash, and emits an event only for those that changed. This is simple and reliable. The cost is latency equal to the polling interval, so choose the interval according to the kinds of change in the table above.

Document who owns the integration. When a vendor changes an export field, the poller breaks silently unless something is watching for it. Add an alert when the poller has produced no events for an unusually long time, since a quiet day and a broken feed look alike.

Want this applied to your practice? Get a free website audit.

Book my free audit

Debouncing and idempotency

Two properties keep the pipeline sane.

Idempotency: the same event processed twice should have the same effect. revalidateTag is naturally idempotent, but your logging and any downstream notifications may not be. Give events an ID and ignore repeats.

Debounce or batch: if the HIS sends thirty updates for the same doctor within a minute while a rota is edited, collapse them into one revalidation for that tag. Otherwise you cause repeated background renders for no gain.

Pitfalls specific to ISR

The ISR guide lists caveats that matter here.

  • Multiple instances: with the default file-system cache, on-demand revalidation only invalidates the instance that receives the call. If your site runs on several containers, use a shared cache handler, or the page may be fresh on one server and stale on another. Test by changing a roster and requesting the page repeatedly through the load balancer.
  • Proxy rewrites: Proxy does not run for on-demand ISR requests, so revalidate the exact path (/doctors/x) and not a rewritten one. If you use tags, this does not apply, but if you use revalidatePath as a fallback it does.
  • Errors: if a revalidation throws, the last successful data keeps being served and Next.js retries on the next request. A broken API therefore shows as stale pages, not errors. Monitor for it.
  • Dynamic params: pages not prerendered are generated on first request unless dynamicParams is changed. A newly added doctor appears when first visited or when you revalidate the relevant listing tag.

The docs also note the x-nextjs-cache response header, with values HIT, STALE, MISS and REVALIDATED. Use it in tests and in a synthetic check after a roster change.

Always show when the roster was last confirmed

Whatever the technology, a patient should not have to trust a static page blindly. Add a "timetable last updated" date taken from the HIS event time, and a line such as "Please confirm before travelling" with the hospital's appointment number. This is a content decision for the hospital, but it limits the harm from a missed update and costs little. Keep the wording factual and avoid any promise about waiting times or availability.

Testing the setup

Build a repeatable test:

  1. In a staging environment, change a doctor's roster in the HIS test instance or send a synthetic event.
  2. Record the time the event was sent.
  3. Request the doctor page, location page and one department listing; check content and x-nextjs-cache.
  4. Repeat for max and { expire: 0 } changes and for a doctor leave event.
  5. Kill the integration for a while, restore it, and confirm that the missed changes appear on the next poll.

Record the time from event to visible change. With a poller you will see the polling interval plus a render. Set that as an internal service level and tell reception what it is, so they know when to expect the web page to reflect a change.

Implementation checklist

ItemDecision
Roster versus availabilityRoster static, availability fetched live
TagsPer doctor, per location, per department, one global
Profilesmax for additions, { expire: 0 } for reductions and changes
Event sourceWebhook if available, otherwise hash-based poller
EndpointSecret, payload validation, debouncing
HostingShared cache for multiple instances, tested
MonitoringAlert on silent feed, errors in revalidation
Patient-facing"Last updated" date and confirmation line
ReviewReception tests a real change each quarter

If you want the wider performance context, our Core Web Vitals service explains how static rendering supports fast pages, and the practice management integration page covers connecting these systems.

Filed underISR doctor schedule updatesNext.js revalidateTagdoctor roster websiteon-demand revalidationHIS website integration

About the author

Co-Founder & CTO · Gurugram, India

Arush builds the systems the rest of the company runs on — the patient-acquisition pipelines, the AI chatbots, the analytics that tie a single click to a booked appointment. If a campaign reports a number, it's because something his team built is tracking it.

Free guide · 15 pages

WhatsApp AI Chatbot for Hospitals (14-Day Deploy)

The 14-day WhatsApp booking-bot implementation playbook.

The Pioneers Brief — one essay, three benchmarks, one teardown, every Thursday. Subscribe free →

Free website audit

Your next chapter starts with a conversation.

Three quick questions. We come prepared with a plan for your specialty and city.

  • A 30-minute call with a healthcare specialist
  • Your top three growth opportunities, in writing
  • Honest advice — even if that means not hiring us
  • No obligation and no hard sell
You’ll speak with a senior strategist
Consultations are hosted by Arush Thapar’s team.
Step 1 of 3Takes 30 seconds

What do you want to improve first?

Details stay privateNo obligationReply within 1 working day

Client portfolio · Healthcare websites

Work relevant to isr for doctor rosters daily schedule changes without full.

Explore client work →