learn-business-intelligence-with-phoebe / Builder session 8 of 10
Learn Business Intelligence with Phoebe · Builder track · Session 8 of 10

Ship it

A dashboard on your laptop helps exactly one person. Tonight it goes live: which workspace it lives in, how it refreshes (and what a gateway is for), who sees which rows, and how three hundred people find it without three hundred Slack messages. This is the least glamorous session in the track and the one that decides whether your b6 build becomes infrastructure or a screenshot.

🟠 Builder track Practitioners: analysts · DE · DS · PMs Runs in your browser · no install
0-3 · Welcome 3-20 · Distribute + refresh 20-42 · Security + build-along 42-45 · Q&A
Part 0

The launch checklist

Shipping a dashboard is four questions, answered in writing before anyone gets a link: Where does it live? (workspace and app) How does it refresh? (cadence, and whether a gateway sits in the path) Who sees what? (roles and row-level security) How do people find it? (distribution method and endorsement). Every BI platform asks the same four; only the menu labels change. Tonight we answer all four for Daybreak's exec view.

Live - presented in session Self-study - read after class ▶ SQL box - runs a real database Official sources covered
★ What you walk out with today A distribution decision tree (app vs share vs embed vs subscription vs alert), a refresh plan that knows when a gateway is required, a working mental model of row-level security - static and dynamic - demonstrated in live SQL, and Daybreak's complete launch checklist you can copy for any real dashboard.
Part 1 · covers PL-300 "create and manage workspaces and assets"

Workspaces, apps, and distribution 7 min live

The workspace is where builders work; the app is the polished, read-only face that viewers actually open. Never hand executives a link into your dev workspace - they will bookmark a half-finished page and screenshot it into a board deck. Once the app exists, distribution is a menu with five honest options, and the right one follows from audience size and need.

Dashboard ready. Who needs it, and how? Broad, stable audience A few people, ad-hoc Lives in a portal or Teams Email snapshot on schedule Ping when a number crosses a line App Direct share Embed Subscription Alert Default for anything exec-facing: the app. Sharing raw workspace links is how drafts leak.
🔍 Click to zoom - the distribution decision tree: match the method to audience size and need
LiveWorkspace hygiene - dev, test, prod4 min

Workspaces are cheap; sprawl is not. Three habits keep a tenant navigable:

  • Separate dev from what viewers see. Build and break in a dev workspace; promote to a test or prod workspace, and publish the app from prod. Viewers never watch you refactor live.
  • Name for the finder, not the builder. "Daybreak - Revenue (Prod)" beats "phoebe_test_v3_final". Six months from now, someone searches - make sure they find the right one.
  • One named owner per workspace. When refresh breaks at 6am (part 2), someone specific gets the alert. "The team owns it" means nobody does.
Real world

The forty-dashboard graveyard. A new analyst inherits a workspace with forty items: drafts, copies of copies, "v2_FINAL_new". Nobody knows which three the business actually uses, so nothing can be deleted, so trust in all forty erodes together. Hygiene is not tidiness - it is what keeps the real dashboard findable and believed.

LiveThe five methods, in vendor nouns3 min

Same tree, two toolbars:

  • App - broad, stable audiences get the curated bundle. Direct share - a link or permission for a handful of people, ad-hoc. Embed - the dashboard appears inside a portal, wiki, or Teams channel. Subscription - an emailed snapshot on a schedule. Alert - a notification when a number crosses a threshold.
In Power BI / In Tableau Power BI: workspaces publish apps; subscriptions and data alerts hang off dashboards; choosing the distribution method is a named PL-300 skill, alongside creating and configuring workspaces and publishing, importing, and updating items. Tableau: you publish workbooks and data sources to Server or Cloud, then manage them with subscriptions and data-driven alerts - domain 4 of the Data Analyst exam.
Part 2 · covers PL-300 semantic model scheduled refresh + identify when a gateway is required

Refresh - the heartbeat 7 min live

Import-mode data (b1's default answer) is a snapshot, and a snapshot starts aging the moment it is taken. Scheduled refresh is what keeps it honest. Two decisions: the cadence, and the path. Cadence follows the business question, not ambition. The path has one classic complication: when the source lives on-premises or behind a firewall, the cloud BI service cannot reach it - a gateway must relay the refresh. "Identify when a gateway is required" is a named PL-300 skill because it is the number-one "why is refresh failing" suspect in real tenants.

Source warehouse or database Gateway only if source is on-prem Semantic model refreshed on schedule App viewers fresh numbers Refresh fails → alert the named owner, not silence Cloud source? The gateway box disappears - the service reaches the source directly. On-prem or firewalled source = gateway required. It is the first suspect when refresh fails.
🔍 Click to zoom - the refresh path, with the gateway relay and the failure-alert branch every launch needs
LiveChoosing a cadence3 min

Match the refresh to the question's rhythm, not to "as often as possible":

  • Daily exec pack: decisions happen in a morning meeting → refresh once, before the meeting (6am). Hourly refresh would burn source capacity to update numbers nobody reads until tomorrow.
  • Ops floor: people act within the hour → hourly, or consider a live connection (b1's trade-off returns).
  • Monthly board view: monthly refresh after close, then endorsed and frozen. Mid-month wobble creates questions, not decisions.

Then wire the failure alert: a refresh that fails silently is worse than no refresh, because the dashboard keeps confidently showing last week. Cadence + alert together are the heartbeat.

Self-studyThe Monday-morning refresh postmortem3 min read
Real world

The stale-dashboard incident. Friday night a database password rotates; the gateway's stored credentials go stale; every refresh through the weekend fails - silently, because nobody configured failure notifications. Monday 9am, a regional lead reads the exec dashboard, sees "flat week", and cancels a planned promotion push. The numbers were Thursday's. The data was fine, the model was fine, the charts were fine - the launch was incomplete: no failure alert, no named owner, no "last refreshed" timestamp on the page. All three cost nothing and any one of them would have caught it.

Moral: a shipped dashboard is data + refresh + someone watching the refresh. Put "last refreshed" on every page you ship; it is the cheapest trust signal in BI.

Part 3 · covers PL-300 "secure and govern Power BI items"

Security - who sees what 8 min live

Three layers, coarse to fine. Workspace roles (admin, member, contributor, viewer) decide who can edit versus only look. Item-level access shares one report or semantic model without opening the whole workspace. And the fine-grained star: row-level security - one dashboard, where each viewer sees only their own rows. RLS comes in two flavors: static roles carry a fixed filter (the "Seattle" role always filters city = Seattle), while dynamic RLS filters by the logged-in user's identity - one role, personalized rows, usually driven by group membership. On top sit trust markers: endorsement (promoted by the owner, or certified by a central authority - the tiers from leader a5) and sensitivity labels that follow the data into exports.

LiveRLS in one line of SQL3 min

Strip away the portal screens and RLS is just this: the platform appends a WHERE clause the viewer never sees. Here is what Daybreak's dashboard effectively runs when the Seattle manager opens it:

SELECT c.city,
       ROUND(SUM(oi.quantity * oi.unit_price), 2) AS revenue
FROM orders o
JOIN order_items oi ON oi.order_id = o.order_id
JOIN customers c ON c.customer_id = o.customer_id
WHERE c.city = 'Seattle'
GROUP BY 1;

Everything the platform adds - roles, group membership, the security dialog - exists to attach the right invisible WHERE to the right person, reliably, at scale.

LiveStatic vs dynamic RLS3 min
Static RLSDynamic RLS
The filterFixed per role: the Seattle role hard-codes city = SeattleComputed per viewer: filter matches the logged-in user's identity
Roles neededOne per slice - 40 cities means 40 rolesOne role serves everyone
NeedsJust the role definitionsA mapping table: user → city (or region, channel...)
MaintenanceNew city = new role = model changeNew manager = one row in the mapping table
Best forA few stable slicesMany viewers, org-chart-shaped access

Either way, membership is granted by adding users or groups to the RLS role - and PL-300 tests both the role setup and the membership step.

LiveThe RLS matrix - write it before you build it2 min

Before touching the security dialog, write the matrix in plain language and get it signed off. Daybreak's:

RoleSeesFlavor
ExecAll rows, all cities, all channelsNo RLS filter
City managerOnly their own city's customers and ordersDynamic (user → city mapping)
Channel leadOnly orders from their own channelDynamic (user → channel mapping)

A written matrix turns "did we secure it right?" from a feeling into a checklist - and it is the artifact auditors ask for.

Demo 1 of 2

Write Daybreak's launch checklist ★ 12 min · everyone builds

The b6 exec view goes live tonight - on paper. We answer the four launch questions in order, and the result is a one-page checklist you can reuse for any real dashboard at work.

Name the home. Workspace "Daybreak - Revenue (Prod)", owner: you. Publish the app "Daybreak Executive View" from it - viewers open the app, never the workspace.

Set the heartbeat. Scheduled refresh daily at 6am, before the 9am leadership sync. Failure alert to the owner. Gateway needed? No - Daybreak's warehouse is a cloud source, so the service reaches it directly.

Define who sees what. Copy the RLS matrix from part 3: exec sees all, city managers see their city (dynamic), channel leads see their channel (dynamic). Add the manager group to the role membership.

Endorse it. Request certification for the exec view so it carries the highest trust mark - this is the same promoted-vs-certified ladder leader session a5 set up, now applied to your own build.

Announce and pin. One message in the leadership channel with the app link, plus a pin where the audience already lives. Distribution without an announcement is a tree falling in an empty forest - the habit loop from leader a4.

★ The reusable artifact Four questions, five steps, one page: home + heartbeat + who-sees-what + trust mark + announcement. Every dashboard you ever ship gets this checklist; only the answers change.
Demo 2 of 2

Your turn: route it, secure it, re-run it ★ 8 min · build your own

Three quick reps: pick distribution methods against the tree, write one dynamic-RLS sentence, then play viewer-switcher in live SQL.

LiveRep 1 · Pick the method for each audience3 min

Route these through part 1's decision tree, then check yourself:

  • 300-viewer exec pack, read every morning → the app: broad, stable audience, curated bundle.
  • The CFO wants Monday's numbers in email at 7am → a subscription: scheduled snapshot, no login required.
  • Ops needs a ping if daily orders cross a threshold → an alert: nobody should stare at a chart waiting for a number to move.
LiveRep 2 · Write the dynamic-RLS sentence2 min

Every dynamic rule reduces to one sentence of the form: "Filter [table] to rows where [column] equals the value mapped to the logged-in user." For "each city manager sees own city":

"Filter customers to rows where city equals the city mapped to the logged-in user in the manager-city table."

One role, any number of managers, and onboarding a new one is a single mapping row - no model change. If you can write the sentence, you can build the role in any tool.

LiveRep 3 · Switch viewers in live SQL3 min

You are the RLS engine now. Edit 'Seattle' to another city and re-run - you just switched which viewer is logged in. (Not sure which cities exist? Run SELECT DISTINCT city FROM customers; first.)

SELECT c.city,
       ROUND(SUM(oi.quantity * oi.unit_price), 2) AS revenue
FROM orders o
JOIN order_items oi ON oi.order_id = o.order_id
JOIN customers c ON c.customer_id = o.customer_id
WHERE c.city = 'Seattle'
GROUP BY 1;
Homework

Try it yourself - this week ◐ 25-35 min total

Source material

Official sources covered

This session is the deployment slice of both major exams, taught tool-agnostic. Portal click-paths stay with the vendors (mapped in b10). This page covers:

PL-300 · Create and manage workspaces and assetsParts 1-2 · workspaces, apps, publishing, distribution method, subscriptions and alerts, endorsement, scheduled refresh, when a gateway is required
PL-300 · Secure and govern Power BI itemsPart 3 · workspace roles, item-level access, static and dynamic RLS, role membership, sensitivity labels - concepts here; portal clicks stay with Microsoft
Tableau Data Analyst · Publish and Manage Content (domain 4)Part 1 · publish workbooks and data sources, scheduled extract refreshes, subscriptions and alerts - concept level
MS Learn · Manage and secure Power BI pathParts 2-3 · conceptual core; tenant-admin depth stays with Microsoft
Check yourself

Three questions before you go 🎯 ◐ 90 seconds

1 · Scheduled refresh keeps failing for a dashboard whose source is a SQL Server inside the office network. First suspect?

A cloud BI service cannot reach an on-prem or firewalled source directly; a gateway relays the refresh. "Identify when a gateway is required" is a named PL-300 skill for exactly this diagnosis.

2 · Forty city managers should each see only their own city on one dashboard. Best setup?

Static roles work for a few stable slices; at forty, maintenance explodes. Dynamic RLS keeps one role and personalizes rows by identity - a new manager is one mapping row, not a model change.

3 · The exec pack has 300 viewers who will read it every week for years. App or direct share?

Direct share is for a few people, ad-hoc. A broad stable audience gets the app: polished face, no dev clutter, permissions managed once. Workspace links leak drafts.

Builder session 8 cheat sheet · pin this

Four launch questionsWhere does it live? How does it refresh? Who sees what? How do people find it? Answer in writing, then ship.
Workspace vs appBuilders work in the workspace; viewers open the app. Never share dev links - drafts leak.
Distribution menuApp (broad stable) · direct share (few, ad-hoc) · embed (portals/Teams) · subscription (email snapshot) · alert (threshold ping).
Refresh cadenceFollow the question's rhythm: daily exec pack = daily 6am; ops = hourly or live. Never "as often as possible".
Gateway ruleOn-prem or firewalled source = gateway required. First suspect when refresh fails. Cloud source = no gateway.
RLSOne dashboard, per-viewer rows: an invisible WHERE clause. Static = fixed filter per role; dynamic = filter by logged-in user via a mapping.
Trust marksPromoted (owner vouches) vs certified (central authority vouches) + sensitivity labels that follow exports. Ties to leader a5.
Silent failure killsRefresh failure alert + named owner + "last refreshed" on the page - three free defenses against the stale-dashboard incident.