Skip to content
Core Web Vitals & measurement

Speed Behind the Login: Measuring Portals Without Field Data

Behind a login the public field dataset holds nothing. How to measure inside the portal, which metrics carry, and where the limits differ from a home page.

15 min read FelddatenSaaSPortale

A portal behind a login has a measurement problem that has little to do with its technology: the public field dataset that fuels almost every discussion about load time does not know these pages. It only admits what a search engine could reach as well. Everything that appears after signing in falls out structurally. At the same time no full-page cache applies there, because every response is bound to a session. Anyone who wants to steer speed in a SaaS product or a customer portal therefore has to produce the numbers themselves. This article shows which metrics carry in the signed-in area, how to set up your own collection, and why long tables and hours-long sessions need different limits than a home page.

Key takeaways

  • The public field dataset only admits a page when it is publicly discoverable and has enough visitors; for an origin the documentation names two requirements (Chrome UX Report). Behind a login, typically neither is met.
  • The thresholds themselves stay valid: 2.5 seconds for the largest contentful paint, 200 milliseconds for interaction response, 0.1 for layout shift, each at the 75th percentile (web.dev). Only the data source is missing.
  • The replacement is your own collection inside the product: record metrics per view type rather than per address, because portal addresses carry tenant, case and record numbers.
  • Long tables hit the node count: up to Lighthouse 12 the DOM size audit warned above roughly 800 nodes in the body and reported an error above roughly 1,400 nodes (Lighthouse). Since Lighthouse 13 of October 2025 a DOM size insight without published node counts has taken its place; as an order of magnitude both figures remain usable.
  • Inner pages carry more JavaScript than home pages - a mobile median of 660 KB against 632 KB (Web Almanac 2025). In the signed-in area the lever therefore sits in runtime, not in images.
  • A budget per view type makes the measurement fit for acceptance: list view, detail view, form and report each get their own limits instead of one value for the entire portal.

Why no field data exists behind a login

The field dataset that reports and tools rely on collects measurements from real browser sessions. An origin is only included if it meets two requirements (Chrome UX Report): it must be publicly discoverable and have enough visitors. Discoverability is judged by the same criteria as a search engine applies. A view that only comes into existence after signing in does not meet that - regardless of how many people use it every day. In a portal, the difference between field data and your own measurement therefore does not decide accuracy, it decides whether any numbers exist at all.

The documentation names three states in which a page counts as not publicly discoverable: a response with a status other than 200 after all redirects, a robots header carrying noindex, or a robots meta tag with the same value in the document. Those three states are the norm in a portal: a request without a session ends on the login screen, and the signed-in area carries noindex for good reason. For SaaS applications this means the public part - home page, pricing, documentation - shows up in the dataset, while the product itself stays empty.

What this means for prioritisation

Without field data you lose both the comparison with other providers and the distribution across real devices and networks. What remains is your own collection. It reflects the actual data volumes, roles and connections of your users and supplies the numbers that are otherwise missing in the signed-in area.

Which thresholds still apply

The missing data source changes nothing about the target values. For a good experience the largest contentful paint should happen within 2.5 seconds of the page starting to load, interaction response should be 200 milliseconds or less, and layout shift should stay at 0.1 or below (web.dev). These are thresholds for the assessment, not measurements - they apply regardless of who does the measuring.

More important than the threshold is the rule behind it: the recommendation is to look at the 75th percentile of page loads, segmented across mobile and desktop devices (web.dev). An average hides exactly the sessions that matter - the account with 4,000 rows in the list, the tablet in the warehouse, the connection out in the field. Anyone who carries the Core Web Vitals over into a portal therefore carries over not only the numbers but the way they are evaluated.

The difference between a public page and a signed-in area affects the reference frame more than the metric itself. The comparison below shows what shifts.

Metric or dimensionPublic pageSigned-in area
Data sourceaggregated browser field datasetyour own collection inside the product
Reference frameorigin and individual addressview type, role and size class
Page loadfirst delivery, often from cacheresponse per session, no full-page cache
Interaction responsefew interactions per loadhundreds of interactions per session
Layout stabilityimages, banners, consent layerrows and filters loaded after the fact
Time framethe provider's rolling windowyour own window, aligned to releases

There is one more peculiarity: many portals switch views without a full page load. The documentation of the dataset spells this out - such route transitions look like new page views to the user, while for the browser and the underlying platform APIs the entire experience belongs to the first load (Chrome UX Report). Knowing how to measure soft navigations is therefore not a detail in a portal but the precondition for the second and third view to produce values at all.

Your own collection in the signed-in area

The collection starts with a decision that is hard to correct later: what do you group by? Portal addresses carry tenant, case and record numbers; grouping by address gives you thousands of groups with one measurement each. What works is grouping by view type - list view, detail view, form, report - plus the role and, where relevant, the size class of the tenant. That is also the data-minimising route: what measurement without consent allows depends largely on how little a collection says about the individual person.

portal-rum.js
// Record metrics per view type, not per address
const view = () => ({
  type: document.body.dataset.viewType,   // list | detail | form | report
  role: document.body.dataset.role,
  rows: Number(document.body.dataset.rows || 0)
});

const buffer = [];
const record = (name, value) =>
  buffer.push({ name, value: Math.round(value), ...view() });

function evaluate(type, entry) {
  if (type === 'largest-contentful-paint') record('lcp', entry.startTime);
  if (type === 'event' && entry.interactionId) record('inp', entry.duration);
  if (type === 'long-animation-frame') record('laf', entry.duration);
}

const observe = (type, extra = {}) => {
  new PerformanceObserver((list) => {
    for (const entry of list.getEntries()) evaluate(type, entry);
  }).observe({ type, buffered: true, ...extra });
};

observe('largest-contentful-paint');
observe('event', { durationThreshold: 40 });
observe('long-animation-frame');

// Send in one batch when the view is left
addEventListener('visibilitychange', () => {
  if (document.visibilityState !== 'hidden' || buffer.length === 0) return;
  navigator.sendBeacon('/api/rum', JSON.stringify(buffer.splice(0)));
});

Sending belongs at the end of a view, not in the middle of it. sendBeacon delivers on leaving without holding up the transition; for regular interim batches there is now a way to send measurement data with a delay that needs no timer of your own. In both cases the same principle applies: the collection must not degrade the very metric it collects.

View type instead of address

List view, detail view, form and report behave differently in technical terms. Only this grouping turns thousands of individual values into a distribution you can read.

Data volume per load

Row count, column count and filter state belong with every measurement. Without them you cannot tell later whether a view is slow or a tenant is simply large.

Age of the session

How long the tab has been open explains part of the response times. The value costs nothing and separates a fresh load from a view that has lived in the same tab for hours.

Response time per action

Sorting, filtering, expanding: a portal produces hundreds of interactions per session. Only their distribution shows which action is expensive and how often it occurs.

The server's share

A timestamp from the application in the response header separates backend waiting from work in the browser. Without that split, experience shows that optimisation lands in the wrong place.

Nodes and memory

Node count in the body and allocated memory belong in the record. Both grow in production without a single line of code changing.

The order that has proven itself

First record the view types separately, then reduce the most expensive server response, then cut the node count of the largest list, then untangle runtime in the browser. Starting with the last point moves work around instead of removing it.

Long tables and the node count

Portals show lists, and lists grow with the account. Up to Lighthouse 12 the DOM size audit warned when the body element contained more than roughly 800 nodes and reported an error above roughly 1,400 nodes (Lighthouse); since Lighthouse 13 of October 2025 it has been replaced by a DOM size insight for which no node counts are published. As an order of magnitude the figures remain usable: a table with 200 rows and twelve columns amounts to 2,400 cells before header row, controls and borders are added. That order of magnitude is therefore typically exceeded on the first page of results.

For comparison: across pages measured on mobile, the median number of elements per page fell from 653 in 2022 to 594 in 2024, and the 90th percentile from 1,832 to 1,716 (Web Almanac 2024). A portal view with 2,400 cells therefore sits well above what is measured on public pages at the 90th percentile. Knowing how to reduce DOM size is no side topic in a portal - and because many rows only come into being through connected third-party systems, the node count is often decided in the backend.

  • Put only the visible window into the tree and swap it while scrolling; fix the row height beforehand so the scrollbar stays calm.
  • Render cells without their own behaviour as text instead of nested elements with icon, tooltip and menu.
  • Handle per-row actions through one shared listener on the table instead of one listener per row.
  • Fill expandable sections only when they open; a collapsed section with 40 fields otherwise counts in full.
  • For very long lists, check content-visibility so the browser may skip areas outside the viewport.

The number missing from the test

Test accounts are small. A view developed against 20 records shows 4,000 at the customer. That is why every measurement needs the row count, and every budget needs a note on the size class it applies to. Without that note, a green value from the development environment is no proof for production.

Long-running sessions need different limits

A public page is opened, read and left. A portal stays open - through the morning, often through the whole working day. That shifts the weight: the first page load happens once, interaction response happens hundreds of times. Memory that goes unnoticed on a single load adds up over hours; how frontend memory leaks come about is therefore an operational question in the signed-in area, not a footnote.

The composition of the transferred data shifts as well. In a mobile median, inner pages accounted for 660 KB of JavaScript against 632 KB on home pages, while home pages on average request around 45.8 percent more bytes than inner pages (Web Almanac 2025). For a portal that means: total weight goes down, script volume does not - the lever sits in the runtime of the code. And because every response is bound to a session, no full-page cache applies; which layers are left is shown by a look at how cache layers stack in an editorial system.

portal-budget.json
{
  "budget_per_view_type": [
    { "view": "list",   "rows_up_to": 200,  "ttfb_ms": 400, "inp_ms": 200, "max_nodes": 1400 },
    { "view": "list",   "rows_up_to": 2000, "ttfb_ms": 600, "inp_ms": 200, "max_nodes": 1400 },
    { "view": "detail", "rows_up_to": 0,    "ttfb_ms": 400, "inp_ms": 200, "max_nodes": 800  },
    { "view": "form",   "rows_up_to": 0,    "ttfb_ms": 400, "inp_ms": 150, "max_nodes": 800  },
    { "view": "report", "rows_up_to": 0,    "ttfb_ms": 900, "inp_ms": 200, "max_nodes": 800  }
  ],
  "percentile": 75,
  "window_days": 30,
  "split_by": ["device_class", "role", "size_class"],
  "session": { "max_memory_mb": 250, "runtime_hours": 8 }
}

From measurement to acceptance

A measurement only becomes a tool once someone can read something from it that carries a decision. For B2B portals that usually means: a budget per view type, a percentile instead of an average, and a size class the value applies to. If the weight sits in the backend, the route leads through server optimisation; if it sits in the browser, through the runtime of the code. Which case applies is decided by the split between waiting and work - and that split is in the data as soon as the server's share is recorded.

  1. Name the view types and mark them in the markup so every measurement has a group.
  2. Roll out the collection and let it run for two weeks before anything is changed - without a baseline there is no proof later.
  3. Build the 75th percentile per view type, segmented across mobile and desktop devices.
  4. Set budgets that fit the size class of the account and write them into the acceptance criteria rather than into a report.
  5. Check against the budget on every release and record the comparison with the previous run.

The most common finding in such collections is not a single slow page but an action that is used often and sits just above the threshold. Knowing how to improve interaction response is therefore usually the point with the highest return per effort in a portal - well ahead of the first page load, which a user experiences once a day.

Behind a login there is no external number to compare yourself against. There is only your own measurement - and it is worth exactly as much as the grouping it was collected with.

Project experience from performance work on SaaS products and customer portals

The effort for the setup is manageable: mark the view types, register three observers, provide an endpoint of your own. The real work is the evaluation - and it pays off wherever hundreds of people work with the same list every day. If you would rather shorten the start: in a performance analysis we record the views one by one and set the budgets together with your team.

This article is based on data from: Chrome UX Report (methodology and eligibility criteria), web.dev (Core Web Vitals: thresholds and percentile), Lighthouse (DOM size audit), HTTP Archive Web Almanac 2024 (Markup) and HTTP Archive Web Almanac 2025 (Page Weight).

Related Articles

Core Web Vitals & measurement

Templates, Not the Home Page: Where Load Time Is Made

Teams optimize the home page while visitors land on category, product and article pages. How to measure by template and prove the order of work.

15 min read
Core Web Vitals & measurement

Performance Measurement Without Consent: What Is Allowed

Section 25 TDDDG comes before the GDPR: when a Vitals measurement is device access, how narrow the exemption is and what stays measurable without consent.

15 min read
Front-end optimisation

Frontend Memory Leaks: When Long Sessions Slow Down

The interface starts fast and turns sluggish after twenty minutes: how front-end memory leaks arise, how to measure them over time and how to get rid of them.

12 min read