How I: Analytics and Monitoring for Indie Developer

Starting a solo journey requires adjustment of the tooling to the current needs. High availability and the degree of how “cool” software is does not matter anymore. Today I am sharing my way to get aware of what's going on with the traffic and uptime at (almost) no costs!

How I: Analytics and Monitoring for Indie Developer
Laptop screen full of analytics dashboards.

Starting a solo journey might seem tough for many reasons. Today, I’m focusing on tools for a micro-budget to cover crucial aspects. "What we don’t measure, we can’t control." When working alone, you don’t want to waste time checking service availability or reinventing analytics. Read on to learn how this can be achieved with a couple of low-cost tools.

What is Analytics and Monitoring?

Analytics, in its basic form, means gathering and aggregating metrics to analyze the data. The goal is to understand trends and improve performance: both high-level and low-level components.

A high-level component could be a landing page, while a low-level component might be a server or its part that performs specific tasks, ensuring it doesn’t slow down.

In a typical scenario, our software makes a request to an analytics server to record an action, often providing context, like the URL for a page view event. We then take a time period of interest and create bars, charts, or use advanced analytics/visualization tools to understand the data.

Monitoring, on the other hand, involves understanding “normal” software behavior and boundaries. When behavior deviates from expectations, it’s noted as an “event.”

Unlike analytics, we don’t expect software to report itself. Monitoring is an independent system that watches over the software, using methods like:

  • Scanning logs for response codes or log levels (e.g., "error")
  • Using healthcheck URLs where software reports its status
  • Sending HTTP/TCP/Ping probes to check if the server is running and generating responses
  • Using server agents to gather metrics like memory, disk, and CPU usage

The simplest response from a monitoring system is an alert. For example, if our server returns HTTP code 500 instead of the expected 200, we know there's a problem and need to notify the team immediately.

Incidents are more complex and involve creating a record of an issue that must be addressed. For example, "On this date, service X under URL Y responded with 500." The team would then investigate the cause, starting with log analysis and possibly debugging specific payloads.

When I Am the Team

There are many tools for software teams that simplify their work. Often, these tools are free additions to larger services, or part of the open-source culture, loved by many teams because they avoid "vendor lock-in." These tools provide high automation but require attention and effort to set up and maintain.

Running a solo software company means doing everything on a smaller scale. We don’t need SSO support or automated tickets in our process management tool. When we’re alone, knowing there’s a problem is enough—there’s no complex process other than addressing it ourselves.

Building complex software might be tempting, but it often leads to overkill, with all energy spent on setup. It’s better to skip analytics and monitoring than to run unreliable services. These tools must be reliable.

The Grand Trio

My infrastructure isn’t large, but it’s growing. I have a couple of VPS running several websites under a few domains.

There is a Raspberry Pi 4 as part of my bare metal setup.

Here’s the trio that helps me manage it: EaseProbe, Plausible, and... Telegram.

Telegram

Telegram is a messaging service, but with unique features that turn it into a communication hub. Using Telegram Bots, it’s easy to add functionality in the form of a chat app or even a web-based app. I’ve created a few simple tools, but for brevity, I’ll skip the details here.

The Telegram bot is an HTTP-based interface that uses JSON, allowing for automation. For this article, it’s enough to send messages to users and channels.

EaseProbe - A Simple and Efficient Monitoring Tool

I discovered this tool a while ago, and it ran on my Raspberry Pi until I spent 15 minutes learning its capabilities. It’s written in Go and easily deployable as a single binary. To run it on the Pi, I had to compile it myself (ARM, you know).

EaseProbe integrates natively with Telegram Bots to send alerts. It also offers a variety of connectors, from Ping, HTTP, and TCP to database connectors, allowing for a comprehensive probe of your service.

A probe checks or validates a service’s status. Different approaches may be needed depending on the service.

Servers

  • Host probe: gathers metrics like CPU, disk usage, memory, and load.
  • Ping: a simple protocol to test if the server is reachable.

Web Apps (HTTP)

There are many ways to monitor, but the most reliable is a health check. If an app has a dedicated health check, use an HTTP probe to test for a proper response, typically HTTP 200 OK.

Non-HTTP Services

For non-HTTP services, probes like ping, TCP, shell, and dedicated probes for popular services are available. I don’t use these at the moment, but you can explore them on EaseProbe GitHub.

Plausible - Privacy-Friendly, Self-Hosted Analytics

While researching options, I considered a self-hosted solution since I was renting a large VPS. Setting it up takes time and attention, but it’s rewarding to learn more about the tools I use.

I chose Plausible Community Edition (self-hosted) without hesitation. They also offer a feature-rich hosted solution, which I might move to later, but for now, I’m happy with the Core, a well-designed, GDPR-friendly analytics tool.

Out of the box, it does exactly what I needed: tracks page visits. It’s as simple as including a JavaScript file that automatically tracks page views.

Later, I wanted to track button clicks. That’s where Plausible shines. To do this, I only had to:

  1. Change the JavaScript filename to script.tagged-events.js
  2. Add a class to the element, with the event name prefixed by plausible-event-name=

For example, adding plausible-event-name=FormSubmit allowed me to track clicks on a button leading to the Apple Store download page for Focus Schedule.

To track form submissions passing validation and anti-spam filters, I fine-tuned the event trigger.

I also enabled external link tracking by injecting script.tagged-events.outbound-links.js, which tracks all <a href> tags, capturing the href value as context.

At first, I thought this feature was limited to the hosted solution, but I discovered that the event is still sent. I added a custom goal for "Outbound Link: Click" to see the stats.

You can learn more about custom goals and outbound link tracking in the official documentation here.

Start Small to Become Big

Many failures taught me to consider limited resources. Even my curiosity and enjoyment in software have limits. I don’t have two months to set up a full-scale Kubernetes cluster or custom GitLab and Grafana instances, and I have no reason to do so right now.

Without a real need to scale, we shouldn’t overcomplicate things. It’s easy to say "I wanted to learn it," and that’s fine for learning projects, but these should be separate from production projects. Learning should stop at 20% of the effort, while making it production-ready may require three times the effort—well beyond the indie developer’s journey.