English

A Day in the Life of a Business Analyst (B2B SaaS, IC Track)

Before my laptop is open, there are 11 Slack messages asking why MRR is down. None of them are wrong. None of them have the same answer.

One PM is looking at the executive dashboard, which pulls from a dbt model that ran at 5 AM. One CSM is looking at a Salesforce report that defines MRR as committed contract value. The VP of Finance is looking at the revenue recognition view, which excludes anything not yet invoiced. They're all correct, and they're all looking at different numbers, and by 9:30 AM somebody is going to ask me which one is "the real MRR." That answer takes 20 minutes to give and another 20 to defend. Welcome to Tuesday.

What the JD promised vs what Tuesday actually looks like

The job description said "drive business insights" and "partner with leadership on strategic decisions." I took it. The reality is that my week is roughly 60% SQL and data plumbing, 30% translating between Engineering and Product (and Sales, and Finance, and that one CS director who only communicates in voice memos), and 10% actual analysis. The insight only happens when the plumbing runs clean. A BA who can't keep dashboards green never gets invited to the strategy table. They're too busy in the basement fixing the pipes.

Here's the hour-by-hour for a normal day. Stack: Snowflake for the warehouse, dbt for transformations, Looker for BI (with some Hex notebooks for ad-hoc), Notion for specs, Jira for ticketing.

8:00 AM — Dashboard health check

Before I respond to a single Slack message, I do the same five-minute pass every morning:

  1. Did the dbt run finish? Check the dbt Cloud job overview. Green across the board, or did fct_revenue fail at 4:47 AM because someone shipped a schema change?
  2. Freshness timestamps on the exec dashboard. Open the executive Looker dashboard. The "last updated" tile should say "today, 6 AM-ish." If it says "yesterday," something upstream is stale.
  3. Row counts vs yesterday. Three queries against the warehouse (orders, opportunities, active accounts). If row counts dropped by more than 5%, an upstream Fivetran sync is broken.
  4. Top three KPIs. New logo count, MRR, and gross retention. Are they within sane ranges, or is one showing a 40% week-over-week swing that screams "definition broke"?
  5. The "did anyone touch the semantic layer last night" check. Look at the LookML repo for merges in the last 12 hours.

Here's a sanity-check query I keep pinned in Snowflake. It runs in under five seconds:

select
  date_trunc('day', created_at) as day,
  count(*) as orders,
  sum(amount) as gmv
from analytics.fct_orders
where created_at >= dateadd('day', -7, current_date)
group by 1
order by 1 desc;

If today's row is missing or the GMV swings wildly, I know before the CEO does. That's the entire point. Catching a broken join at 8:05 AM is a three-minute fix. Catching it at 9:35 AM after the all-hands has already started is a 90-minute fire drill plus an apology email.

9:00 AM — Ad-hoc request triage

The queue is in three places, because of course it is. Jira intake board for formal requests. The #data-help Slack channel for "quick questions." A shared Notion page where one of the directors keeps adding asks because she refuses to use Jira. I check all three.

This morning: five new asks. My job is not to answer them. My job is to triage.

  • "Can you pull churn by plan tier for last quarter?" Blocking. The CFO wants it for the board deck on Thursday. If the semantic layer is clean, this is a 15-minute query. If fct_subscription_events still has the old plan_id join issue, it's two hours. Estimate: 30 minutes. Take it.
  • "Curious, how many of our trial users come from LinkedIn?" Curious, not blocked. The marketing dashboard already has acquisition source split. Reply with a screenshot and a link. Two minutes.
  • "Need to know our Q1 win rate by industry." Already exists in the sales performance Looker dashboard. Send the link and one sentence on which filter to apply. Three minutes.
  • "Can you build a dashboard for our new pricing experiment?" Real work. Needs a 30-minute scoping conversation, not a SQL query. Reply: "Got it, let's spend 20 minutes Thursday scoping the decision this dashboard needs to drive."
  • "This number on the CS dashboard looks weird, can you check?" Could be nothing, could be everything. Open it. The number is fine. The legend is wrong because someone renamed a measure. 10-minute fix in LookML.

The triage rule that saved my sanity: separate "blocked" from "curious." Blocked means a decision can't move forward without an answer. Curious means someone is in a Looker explore and got nerd-sniped. Curious gets pointed at self-serve. Blocked goes to the top of the queue. If everything is "blocked," nothing is.

The data team I'm on is three people. Across us, we get 8 to 12 net-new ad-hoc requests per week. Without triage, the queue eats the whole job.

11:00 AM — Mid-day requirements interview

A PM books 45 minutes on my calendar. The agenda says: "Engagement dashboard scoping." I've been here before. The PM wants "a dashboard for engagement." That is not a request. That's a feeling.

My job in this meeting is to get to the actual decision the dashboard will drive, then work backward to two or three metrics that aren't vanity. Here's the question script I use, and I literally have it open in a Notion doc when the meeting starts:

  1. What decision will you make differently after looking at this dashboard? (If they can't answer, the dashboard is a vanity ask. Stop here.)
  2. Who else needs to see it, and what decision do they make?
  3. How often will you look at it (daily, weekly, monthly)? (Daily means you need a Slack alert, not a dashboard.)
  4. What number, if it changed, would make you do something this week?
  5. What's the threshold? What counts as 'good' vs 'bad'?
  6. What's already in place that's almost this, but not quite? (Often there's an existing Looker explore that does 80% of it.)
  7. If we can only ship two charts, which two matter most?

Today's PM said "engagement dashboard." After 30 minutes of those questions, what they actually need is one chart (weekly active users by feature cohort) plus a Slack alert when WAU drops more than 10% week-over-week. Build effort: half a day. Original ask, taken at face value: probably two weeks for something that nobody would open after the first sprint.

The PM who asks for "a dashboard" usually needs one chart and a Slack alert. Roughly 70% of the time, in my experience.

1:30 PM — Async with eng and product

Lunch was a sandwich at my desk while reviewing a dbt PR. This is the translator part of the job, and it's the part nobody tells you about in interviews.

Comment on the dbt PR. An analytics engineer is refactoring dim_accounts and renaming a column from account_owner_id to owner_user_id. The PR description doesn't mention the four downstream Looker explores that reference the old name. I leave a comment with links to each affected explore and a note that we either need (a) a column alias for backward compatibility or (b) a coordinated LookML PR shipped at the same time. This 10-minute comment prevents three Slack DMs at 9 AM tomorrow asking why the sales dashboard is broken.

Respond to a product spec. A PM has written a spec for a new in-app onboarding flow and tagged me asking if I can "track engagement with each step." Looking at the event tracking, the events they want don't exist. The current product instrumentation fires onboarding_started and onboarding_completed, full stop. To answer the question they actually care about (where do users drop off in the flow), we need step-level events: onboarding_step_viewed with a step_name property. I write that up in the spec doc with the exact event schema, point them at the existing tracking plan in Notion, and add a Jira ticket on Engineering's backlog to add the events.

This is the work that doesn't show up in any dashboard but separates a BA who gets re-hired from one who doesn't. Engineering speaks tables and schemas. Product speaks features and outcomes. Stakeholders speak in feelings and Slack messages. The BA bridges all three. dbt PRs reviewed before lunch save Looker outages after lunch. That's the job.

3:00 PM — End-of-day exec data pull

The VP of Sales pings me at 2:55 PM. Board prep call is at 4. He needs Q-to-date pipeline by segment, broken out by stage and weighted by stage probability. Slide is being built right now.

The SQL is fine. I have a saved query for this exact cut. It looks roughly like:

select
  segment,
  stage,
  count(*) as opps,
  sum(amount) as pipeline_amount,
  sum(amount * stage_probability) as weighted_pipeline
from analytics.fct_opportunities
where close_quarter = 'Q2-2026'
  and is_active = true
group by 1, 2
order by 1, 2;

The hard part isn't the query. It's the caveat. The VP wants one number on the slide. I have to decide which one and tell him why. Three options, all defensible:

  • Pipeline amount (raw sum): biggest number, looks great, includes deals that have a 10% chance of closing.
  • Weighted pipeline (sum × stage probability): more honest, smaller, what most CFOs prefer.
  • Committed pipeline (only stages 4 and above): most conservative, what we report in the QBR.

I send the data with a one-paragraph note: "Slide should use weighted pipeline. That's what the CFO presented last quarter, and using a different definition this quarter will trigger a 'why did the methodology change' question. If the VP wants the raw number for narrative, list it as a footnote."

The data takes four minutes. The recommendation takes 12. The recommendation is the part that gets me invited back next quarter.

4:30 PM — The "this report is wrong" panic

Right on cue. A Director of Customer Success Slacks me: "Hey, the new logo number on the CS dashboard says 47 for April, but Salesforce says 52. Can you look?"

This is the most common emergency in the job, and it is almost always the same root cause. Here's the 20-minute debug I run, in order:

  1. Definition check. What does the dashboard call a "new logo"? In Looker, it's filtered to is_first_paid_invoice = true. In Salesforce, the report is filtered to opportunity_stage = 'Closed Won' AND account_type = 'New Logo'. Those are different definitions. An opportunity can be Closed Won but not yet have a paid invoice (5-day billing lag). That alone usually explains a 5-deal gap.
  2. Timezone check. Salesforce reports in the user's local time. The Looker dashboard is in UTC. April 30th in Pacific Time is May 1st in UTC. One or two deals always get caught in this.
  3. Filter check. Is the Salesforce report including renewals or upgrades? Sometimes the "new logo" filter is misconfigured.
  4. Data freshness check. When did the Salesforce-to-Snowflake sync last run? If it ran 10 minutes ago, fine. If it ran six hours ago, two more deals may have closed since then.
  5. Actual data bug. Only after ruling out the first four do I check whether there's an upstream issue.

Today's answer: definition mismatch. Looker is using paid-invoice; Salesforce is using closed-won. Both are "right," they just answer different questions. The Looker number is the right one for the CS team's purposes (we should celebrate paying customers, not paper closures), but I document the difference in the dashboard description so this doesn't happen again next month.

The communication matters as much as the diagnosis. I never reply with "the Salesforce report is wrong." I reply with: "Both are correct, but they're measuring different things. Here's what each one means, here's why they differ this month, and here's which one to use for the CS QBR." Nobody gets defensive. Nobody escalates. The director thanks me and moves on.

"This report is wrong" is almost always a definition disagreement, not a data bug. Maybe 80% of the time. The other 20% is real bugs, and those get a Jira ticket and a postmortem.

5:30 PM — Wrap

Five ad-hoc requests came in this morning. I closed three. Two got pushed to tomorrow with a Slack reply explaining why, so nobody wonders. One I added to the analytics engineering backlog as a recurring request. The "churn by plan tier" pull comes in roughly twice a quarter, and it's time to make it a self-serve dashboard so it stops landing in my queue. That's the highest-leverage move I'll make all day, and it took two minutes.

Last thing I do before closing the laptop: a one-line note in my Notion daily log. What did I ship, what did I learn, what got pushed. Tomorrow morning, when the 11 Slack messages start again, that log is how I remember which fires were already burning.

The honest scorecard

At the end of a good day, the BA shipped one piece of real analysis (the engagement dashboard scoping that turned a two-week build into a half-day chart-plus-alert), unblocked three stakeholders (the CFO churn pull, the VP Sales pipeline cut, the CS director new-logo question), and prevented one wrong-number incident (the dbt PR comment that saved tomorrow's Looker outage).

That's the job. Not "drive insights." Not "be a strategic partner." Show up, keep the dashboards green, translate between the people who can't talk to each other, and answer the question behind the question.

The 10% that is real strategic analysis only happens when the 90% runs clean. The BAs who get promoted are the ones who figured this out by month three.

Learn More