SOFTWARE / SYSTEMS / AIEngineering news. Technical depth.
Architecture / 3 MIN READ

What should a dashboard refresh when the browser restores it from the back-forward cache?

Preserve the user’s place on a bfcache restore, then revalidate live server-backed values instead of treating Back as a full reload.

A dashboard restored from the back-forward cache should keep the user’s local context, then selectively revalidate values that may have changed while the page was frozen. Do not treat Back as a fresh navigation. Preserve scroll, filters, tabs, and in-progress input, but refresh server-derived facts such as balances, job status, counts, and session-sensitive controls. Detect this path with pageshow and event.persisted, which fits how web.dev’s bfcache guide describes a restored page and how the HTML Standard’s session history model describes persisted user state.

Why not reload the whole dashboard?

Because bfcache is specifically designed to restore a prior page quickly from memory. web.dev’s bfcache guide explains that browsers can suspend JavaScript and later make the page visible again, instead of rebuilding it from scratch. If your Back handler discards the restored page and starts over, you lose the main benefit: the user returns to the same reading position and UI state.

The HTML Standard’s session history model also allows persisted user state such as scroll position data and, in some user agents, form control values. For dashboards, that means your default should be continuity, not reset.

What should be refreshed on restore?

Refresh anything that represents the current world outside the browser: balances, inventory, queue depth, unread counts, long-running job progress, lock state, and permission-dependent actions. Those values can become stale while the page is frozen.

Preserve user-owned interface state: selected filters, date range, sort order, expanded sections, scroll position, and draft text. If an open dialog could now be unsafe, keep the draft but re-check the record before enabling a mutating action. The ordering boundary that matters is the server response that returns current state or accepts the write, not a client-side preflight alone.

A practical rule is simple: preserve preferences and reading position; revalidate claims about current server state.

How should you implement the refresh policy?

Use pageshow and branch only for persisted restores.

Prerequisite: your dashboard data layer must support targeted refetches by widget or query key.

window.addEventListener('pageshow', async (event) => {
  if (!event.persisted) return;

  showRefreshingHint();

  const results = await Promise.allSettled([
    refreshSummaryCards(),
    refreshVisibleTablePage(),
    refreshNotifications(),
    refreshSessionSensitiveActions()
  ]);

  if (results.every((result) => result.status === 'fulfilled')) {
    setFreshnessTimestamp(Date.now());
  }
});

Prefer a staged refresh over rerunning every request. Refresh visible and time-sensitive modules first, then lazy sections after interaction or viewport entry. That avoids unnecessary churn while still correcting stale facts promptly.

What does a good dashboard checklist look like?

Example: an operations dashboard restored after the user opens a ticket, then clicks Back.

  • Keep queue filter, search text, selected tab, and scroll position.
  • Refresh SLA timers, ticket statuses for visible rows, unread count, and assignee availability.
  • Keep an open edit dialog’s draft text.
  • Revalidate whether the ticket is still editable before enabling Save.
  • Update the “Last updated” label from the new fetch, not the restored timestamp.

This gives users instant continuity without presenting old operational data as current.

Should every request rerun?

No. Re-fetching everything defeats the point of a restored page and adds visual instability. Re-run only the queries whose correctness depends on elapsed time, background mutations, or changed session state.

What happens to an open dialog?

Usually keep it if it contains user input. But before any write, fetch or submit against the authoritative server state and handle conflicts explicitly. Preserve the draft; do not silently close the dialog.

Next step: classify each dashboard element into either preserved UI state or revalidated server state, then test a real Back navigation with stale data injected.

Reviewed: 2026-09-05.

SOURCES & REVIEW

Sources are linked throughout this guide. Product capabilities can change; consult the linked documentation for your deployment.

Read our editorial approach ↗