sodcalculator

10 Tech How-To

Build Lean KPI Telemetry for a Node.js SaaS App

Guide 10-12310 · Updated · Step by step

This guide walks you through adding lean KPI telemetry to a Node.js SaaS app: a lightweight, dependency-light way to track the metrics that actually matter (activation, retention, revenue, and health) without bolting on a heavy analytics platform. You’ll end up with a small, self-contained module that records events, computes KPIs, and exposes them via an endpoint—ready for dashboards or alerting.

What You’ll Need

  • A Node.js SaaS app (Express, Fastify, or similar) with a database (PostgreSQL, MySQL, SQLite, or MongoDB).
  • Basic knowledge of JavaScript, SQL, and REST APIs.
  • Node.js 16+ installed.
  • An existing users table and some way to identify a user (e.g., a user ID from authentication).

Step-by-Step

  1. Define your KPIs. Pick 3–5 metrics that reflect your business model. Common SaaS KPIs: monthly recurring revenue (MRR), active users (daily/weekly/monthly), activation rate (percent of new users who complete a key action), churn rate (percent of customers lost), and conversion rate (trial to paid). Write them down with clear definitions—e.g., “active user = any user with a login event in the last 30 days.�
  2. Create a telemetry module. Make a new file, e.g., telemetry.js. Export a singleton object with methods like trackEvent(userId, eventName, properties) and getKpis(). Keep it dependency-free for now—use Node’s built-in crypto for IDs and your database driver for storage.
  3. Design a simple events table. In your database, create a table events with columns: id (UUID), user_id, event_name (string), properties (JSONB or TEXT), and created_at (timestamp). Index user_id and created_at for fast queries.
  4. Implement the trackEvent method. In telemetry.js, write a function that inserts a row into the events table. Use parameterized queries to prevent SQL injection. For MongoDB, use an insertOne call. Keep it async and non-blocking—do not await in the request path unless you need to; fire-and-forget is fine for low-volume apps.
  5. Add event tracking to your app. In your authentication middleware or route handlers, call telemetry.trackEvent(user.id, 'login', { source: 'email' }) on key actions: signup, login, feature use, payment, cancellation. Start with 5–10 events that map to your KPIs. Avoid tracking every click—lean means only what matters.
  6. Write KPI queries. For each KPI, write a SQL query (or aggregation pipeline) that computes it from the events table and your users table. For example, MRR: sum of all successful payment events in the current month. Active users: count distinct user_id from events where event_name = ‘login’ and created_at > now() – interval ’30 days’.
  7. Create a getKpis() method. In your telemetry module, add a function that runs these queries in parallel using Promise.all and returns a JSON object like { mrr: 12345.67, activeUsers30d: 456, activationRate: 0.32, churnRate: 0.05 }. Cache the result for 60 seconds to avoid hammering the DB.
  8. Expose an endpoint. Add a route in your app, e.g., GET /api/kpis, that returns the result of getKpis(). Protect it with an admin check or a secret token. This endpoint can be polled by a dashboard or monitoring tool.
  9. Add basic alerting (optional). In getKpis(), after computing values, check thresholds (e.g., if churn > 0.1) and log a warning or send an email via a service like SendGrid. Keep it simple—no need for a separate alerting system initially.
  10. Test and iterate. Write a few unit tests for the telemetry module using a test database. Verify that events are stored, KPIs are computed correctly, and the endpoint returns the expected JSON. Adjust event names or queries as you learn what’s useful.

Common Mistakes

  • Over-tracking. Adding dozens of event types leads to noise and high storage costs. Stick to events that directly feed your KPIs.
  • Blocking the request path. Awaiting a database insert on every request can slow your app. Use fire-and-forget or a queue for telemetry writes.
  • Ignoring timezones. KPI queries that use “today� must use UTC or a consistent timezone. Otherwise, daily metrics will be off.
  • Not indexing. Without indexes on user_id and created_at, queries will slow down as data grows.
  • Hardcoding KPI definitions. If you change a KPI definition (e.g., active window from 30 to 7 days), update the query and version your endpoint to avoid confusion.

Tips

  • Use a single events table for all event types—it’s flexible and easy to query.
  • Store properties as JSONB (PostgreSQL) or JSON (MySQL) to handle varying event shapes.
  • Add a created_at index with a descending order for recent-event queries.
  • Consider using a time-series database (like TimescaleDB) if you outgrow your primary DB—but start simple.
  • Expose raw events too, so you can debug and build ad-hoc reports.
  • Use environment variables for database connection strings and admin tokens.

Troubleshooting

  • Events are not being stored. Check your database connection and that the table exists. Run the insert query manually. If using a transaction, make sure you commit.
  • KPI values look wrong. Verify your SQL queries with a sample dataset. Check for NULL handling—e.g., SUM() returns NULL on empty sets; use COALESCE(SUM(…), 0).
  • Endpoint returns 500. Look at server logs. Common issues: missing table, permission denied, or a syntax error in the query. Test the getKpis() function directly in a Node REPL.
  • Performance degrades. Add indexes, increase cache duration, or move to a separate analytics database if needed.
  • Duplicate events. If you retry inserts, you might get duplicates. Add a unique constraint on a combination of (user_id, event_name, created_at) or use an idempotency key.

Frequently Asked Questions

  1. Do I need a third-party analytics service? No—this lean approach works well for early-stage SaaS. You can always add a service later if you need advanced funnels or cohorts.
  2. How many events should I track? Start with 5–10 that map to your KPIs. Quality over quantity.
  3. What if my app is multi-tenant? Add a tenant_id column to the events table and filter by it in queries.
  4. Can I use this with MongoDB? Yes—use a collection for events and aggregation pipelines for KPIs. The same principles apply.
  5. How do I handle historical data? If you’re adding telemetry to an existing app, you can backfill by parsing old logs or just start fresh—KPIs will be accurate from now on.
  6. Is it okay to fire-and-forget telemetry writes? Yes, for most cases. If you need reliability, use a message queue like BullMQ.

Related

General steps for current mainstream versions; menus can differ by device and version. See the disclaimer or report an error.

More in this bed

The whole Tech How-To bed →