All work
Corporate caseIn production

Custom sales BI

Sales Dashboards

No more arguing about which number is right: 13 dashboards, one rule, and the API returns the same value the card shows.

Role
Author · product, architecture and engineering
Period
Jun to Oct 2026
Stack
  • TypeScript
  • Node.js
  • Fastify
  • Next.js
  • React
  • PostgreSQL
  • SQL Server
  • SSE
  • OAuth2 + PKCE
  • Docker
dashboards in production
13
commits in 4 months
1,017
test files
555
SQL migrations
95

Figures measured from the repository.

Qualification funnellive · refreshes every 30 s
Updated 2:32 pm
Leads today128+12% vs. average
Qualified4132% of leads
Meetings booked23daily goal: 25
Time to first contact18 minmedian

Today's funnel

  • Came in128
  • Contacted96
  • Qualified41
  • Meeting booked23

Leads per hour

051015202508h: 908h09h: 1609h10h: 2110h11h: 1811h12h: 712h13h: 1113h14h: 2414h15h: 1415h16h: 816h

Today's ranking

SDRAttemptsMeetings
1Ana R.528
2Bruno T.476
3Carla M.395
4Diego S.314
Illustrative recreation with fictitious data. The real UI shows internal names and figures.

Context and problem

The sales team of a credit fintech made decisions on scattered numbers: BI dashboard replicas, side spreadsheets and one-off extracts. Every consumer applied its own rule, and the same metric showed different values on the floor TV, in the management meeting and in the e-mailed report.

The platform brings it all into one place: 13 dashboards for SDRs, closers, post-sale, credit and leadership, TV panels that run on their own, and an API that gives other systems exactly the same number shown on the card.

Environment constraints

  • The CRM quota belongs to the account, not the token. More integrations do not add throughput; they just split the same budget. Everything that talks to the CRM must be controlled in one place.
  • Treacherous sources. The CRM returns batch errors inside an HTTP 200 and reports totals that do not match composite filters; the data warehouse sometimes returns fewer rows without saying so.
  • A wrong number is worse than a late one. A frozen metric with missing items stays wrong forever.
  • Role-based access without friction. Company single sign-on, permissions per tab and per action, and TVs that work with nobody logged in.

Decisions that shaped the product

Architecture

CRMREST API · webhooksData warehouseSQL Server · viewsSheets and bureausUploads · external DBsCRM clientQueue, priority, quotaSchedulers16 staggered jobsPure rulesNo I/O · testedDashboardsRBAC per tab and actionAPIFastify · REST + SSEDaily snapshotsPostgreSQL · auditTV panelsTokenized linkTreated-data APISame number as the cardCircuit breakerPer account and methodLast known goodPartial read rejected

The CRM, a data warehouse, spreadsheets and bureau databases feed staggered schedulers. Every CRM call goes through a client with a queue, priorities and quota control. Business rules are pure, tested functions, and the result becomes a daily snapshot in PostgreSQL. The same API serves the dashboards, the TVs and external consumers, who get exactly the number on the card.

Operating lessons

  • Errors inside success. Batch sub-errors arrive in an HTTP 200 and do not trip a breaker on their own. The client inspects every response body before treating it as success, and never retries a quota error.
  • Totals that lie. With composite filters, pagination continues until consecutive empty pages and deduplicates by id instead of trusting the reported total.
  • Rows that vanish. Data-warehouse queries carry a sentinel count; if the row count does not match, the read fails loudly.
  • Thundering herd on restart. Without staggering, every scheduler fired at once on each restart and drained the quota. Now they start offset.
  • Reprocessing the past safely. Rebuilds run as a dry run by default, with a database lock and a volume guard before writing.

My role

I conceived and built the platform end to end (product, architecture, backend, frontend, integrations and operations) in a spec-driven workflow (59 specs) with an incident log in a “measure, don’t opine” format.

What the product delivers

  • Single sign-on with OAuth2 + PKCE, two login modes switchable without logging anyone out, and sessions with an absolute cap.
  • Permissions per tab and per action, mapped from directory groups and editable in the admin panel.
  • TV panels via tokenized links, in a carousel, with no login.
  • Excel export toggled per dashboard, and a portable report as a single HTML file that runs the same components offline.
  • Daily snapshots, versioned goals and an audit trail.

What I would do differently

  • Run CI on pull requests too. Today automatic validation happens only after merge.
  • One source per rule from day one. Rules fixed in one file and forgotten in another caused rework until the identity tests existed.
  • Plan the move out of in-memory state earlier. The single process was the right call, but every new in-memory cache raises the cost of scaling later.

Want something like this for your team?

Get in touch