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
- 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.�
- Create a telemetry module. Make a new file, e.g.,
telemetry.js. Export a singleton object with methods liketrackEvent(userId, eventName, properties)andgetKpis(). Keep it dependency-free for now—use Node’s built-incryptofor IDs and your database driver for storage. - Design a simple events table. In your database, create a table
eventswith columns:id(UUID),user_id,event_name(string),properties(JSONB or TEXT), andcreated_at(timestamp). Indexuser_idandcreated_atfor fast queries. - 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. - 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. - 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’.
- Create a getKpis() method. In your telemetry module, add a function that runs these queries in parallel using
Promise.alland 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. - Expose an endpoint. Add a route in your app, e.g.,
GET /api/kpis, that returns the result ofgetKpis(). Protect it with an admin check or a secret token. This endpoint can be polled by a dashboard or monitoring tool. - 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. - 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_idandcreated_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
eventstable 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_atindex 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
- 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.
- How many events should I track? Start with 5–10 that map to your KPIs. Quality over quantity.
- What if my app is multi-tenant? Add a
tenant_idcolumn to the events table and filter by it in queries. - Can I use this with MongoDB? Yes—use a collection for events and aggregation pipelines for KPIs. The same principles apply.
- 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.
- 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
- Google Desktop Search Widget on Windows 11
- WhatsApp: How to Block Unknown Numbers
- How to Exit Vi in Linux: A Simple Guide
- iPhone Stuck on Setting Up Apple ID: Fixes
- How to Build a Computer Stand (Saturday Workshop)
- Customize Touch Keyboard Themes in Windows 11