Building a Migration Status Dashboard for Executives

Problem Statement

Executives do not want crawl logs; they want one screen that answers “is the migration working, and if not, how bad is it?” Without a curated dashboard, leadership pings the migration lead for status every hour, and the lead burns cutover time writing prose instead of fixing issues. A focused dashboard with a handful of KPIs and clear thresholds turns anxiety into a glance, and it converts the inevitable post-launch dip from a panic into a labelled, expected event. The dashboard is deliberately not the engineering view: engineers need request traces and error breakdowns, while leadership needs four numbers and a sentence. Building the executive layer separately is what keeps both audiences served without one drowning the other. This page is part of Stakeholder Communication Plans; start there for the wider communications framework.

Executive dashboard data flow Three data sources, analytics, server logs, and Search Console, feed a KPI layer that renders four executive tiles with status thresholds. Executive Dashboard Data Flow Analytics Server logs Search Console KPI layer Exec tiles Aggregate + threshold Traffic vs baseline 5xx/4xx error rate Index coverage %
Analytics, logs, and Search Console feed a KPI layer that drives four threshold-coloured executive tiles.

When to Use This Approach

  • Leadership is tracking the migration as a business risk and wants near-real-time status.
  • Multiple stakeholders ask for updates and the migration lead needs to stop answering them one by one.
  • You need a single source of truth that distinguishes “expected dip” from “real incident”.
  • Post-launch monitoring must span analytics, error rates, and index coverage, not just one tool.
  • You want thresholds that turn raw numbers into a red/amber/green decision without interpretation.

Step-by-Step Instructions

1. Pick Four KPIs, Not Forty

Executives lose signal past four or five metrics, so choose the ones that map to revenue and risk: organic sessions vs baseline, error rate, index coverage, and Core Web Vitals status. Everything else belongs in the engineering view.

# kpis.yml — the only metrics on the executive screen
kpis:
  - { id: traffic,   label: "Organic sessions vs baseline", unit: "%" }
  - { id: errors,    label: "5xx + 4xx error rate",         unit: "%" }
  - { id: coverage,  label: "Valid indexed URLs",           unit: "%" }
  - { id: cwv,       label: "Core Web Vitals passing",      unit: "%" }  # ties to CWV baseline

2. Wire the Data Sources

Each KPI needs a live source: analytics for traffic, server or CDN logs for errors, Search Console for coverage. Pull on a short interval so the screen is current during cutover. Be honest about latency: realtime analytics and access logs update within seconds, but Search Console index coverage lags by days, so label that tile as a trailing indicator rather than implying it reflects the last hour. Cache each source’s last good value and the time it was fetched, so a transient API failure degrades gracefully to “last known” instead of flashing a misleading zero across the executive screen.

# errors KPI — compute 5xx+4xx rate from the last 5 minutes of access logs
tail -n 100000 /var/log/nginx/access.log \
  | awk '{c++; if ($9 ~ /^[45]/) e++} END {printf "%.2f\n", (e/c)*100}'  # error %

# coverage KPI — Search Console API, valid vs total inspected URLs
curl -s "https://searchconsole.googleapis.com/v1/urlInspection..." -H "Authorization: Bearer $TOKEN"

3. Attach Thresholds and Colour

A number alone forces interpretation, so bind each KPI to red/amber/green bands derived from your baseline. Anchor traffic to the recorded baseline so an “expected dip” reads green while a real drop reads red. The bands encode judgement once, in calm conditions, so that nobody has to decide at 2 a.m. whether 91% of baseline is acceptable — the colour already says so. Keep the error band tighter than the traffic band, because a rising error rate is a leading indicator of a broken redirect or origin, whereas a traffic dip is a lagging, partly-expected effect of reindexing.

# Map a KPI value to a status colour using baseline-anchored bands
def status(kpi, value):
    bands = {
        'traffic':  [(95, 'green'), (85, 'amber')],   # % of baseline sessions
        'errors':   [(1, 'green'),  (5, 'amber')],    # % error rate (lower better)
        'coverage': [(95, 'green'), (90, 'amber')],   # % valid indexed
    }
    for threshold, colour in bands[kpi]:
        if (value >= threshold) == (kpi != 'errors'):
            return colour
    return 'red'   # below all bands = red, escalate

4. Add One Narrative Line and a Refresh Stamp

Executives trust a dashboard more when one sentence explains the headline and a timestamp proves it is live. Keep the narrative to a single, plain line owned by the comms lead. The narrative does the interpretive work the tiles cannot: it distinguishes “amber because traffic is dipping as modelled” from “amber because something is wrong”, which is the difference between leadership staying calm and leadership convening an emergency call. The refresh stamp matters just as much, because a beautiful dashboard frozen on stale data is worse than no dashboard — it invites confident decisions on wrong numbers. Show the stamp prominently and let it turn red if the data feed itself goes quiet.

# headline.txt — one line + freshness, updated on each refresh
STATUS: AMBER — traffic at 91% of baseline (expected dip), errors 0.4%, coverage 96%
Updated: 2026-06-19 22:48 UTC  (auto-refresh 60s)

Worked Example

A marketplace migrates oldmarket.example.com to market.example.com. The dashboard shows four tiles. Two hours post-cutover, traffic sits at 91% of the recorded baseline — amber by band, but the narrative line reads “expected dip, within model”, so leadership stays calm. The error tile spikes to 6.2% (red) when a redirect rule misfires on the /seller/ path.

Because the error KPI is threshold-coloured, the red tile is visible instantly and the migration lead is already fixing it before an executive asks. The fix — correcting the /seller/ regex so it stops returning 500s — takes eleven minutes, and the tile returns to green at the next 60-second refresh. The narrative line updates to “AMBER — traffic recovering, errors normalised”, and leadership watches the recovery happen rather than fielding a stream of contradictory rumours.

By the next morning the traffic tile has climbed to 97% of baseline and flips to green, the coverage tile holds at 96%, and the single red incident is a documented blip rather than a crisis. The traffic baseline that anchors the green band comes from the traffic and conversion mapping work, and the decision timeline shown alongside it is pulled from the go-live runbook. The whole view rolls up into the Pre-Migration Auditing & Risk Assessment record.

Verification

Confirm the dashboard is live, accurate, and threshold-correct before cutover.

# Confirm the error KPI matches a manual log count
grep -c ' 50[0-9] ' /var/log/nginx/access.log   # cross-check 5xx count

# Confirm refresh is actually current (timestamp within last 2 minutes)
date -u +"%Y-%m-%d %H:%M UTC"

# Confirm a forced red value renders red, not amber (threshold test)
python -c "from dash import status; print(status('errors', 7))"

Watch for these failures: too many tiles so the headline drowns; thresholds not anchored to the baseline so a normal dip alarms leadership; and a stale refresh stamp that lets executives act on hour-old data. Guard against a single broken feed silently zeroing a KPI — if the Search Console pull fails, the coverage tile should show “no data” rather than a misleading 0%, because a false red is as damaging to trust as a false green. Decide before cutover who owns the dashboard during the incident window, so that if a tile goes red there is a named person watching it rather than an assumption that “someone” will notice.

FAQ

How many KPIs should an executive dashboard show? Four to five at most. Beyond that the screen stops being a glance and becomes a report; pick the metrics that map directly to revenue and risk (traffic, errors, index coverage, Core Web Vitals) and push everything else to the engineering view.

How do I stop an expected traffic dip from looking like a failure? Anchor the traffic KPI to the recorded baseline and add a one-line narrative. A 9% dip in the first hours is normal during reindexing, so a baseline-anchored green band plus the words “expected dip, within model” keeps leadership from over-reacting.

How often should the dashboard refresh during cutover? Every 30 to 60 seconds for the first few hours, then back off to a few minutes once metrics stabilise. A visible refresh timestamp matters as much as the interval, because it tells executives the numbers they are reading are current rather than stale.

Related

← Back to Stakeholder Communication Plans