DEV Community

wellallyTech
wellallyTech

Posted on

Quantified Self: Building a Real-Time Health Dashboard with RedisTimeSeries, Go, and Grafana πŸš€

Are you tired of being locked into the "Walled Gardens" of big tech? If you own an Apple Watch, a Garmin for your runs, and a Whoop for recovery, you know the struggle: your health data is scattered across three different ecosystems.

In the world of Quantified Self, data fragmentation is the enemy. To truly understand our physiology, we need a unified view. Today, we’re going to build a high-performance, real-time health monitoring pipeline. We’ll be using RedisTimeSeries for ultra-fast data ingestion, Go for our backend collector, and Grafana to visualize our metrics in a beautiful, geeky dashboard.

By the end of this guide, you’ll have a production-grade setup to sync and analyze your wearable data integration and real-time health monitoring metrics in one place.

The Architecture πŸ—οΈ

The goal is to create a seamless flow from various wearable APIs to a centralized time-series database. Here is how the data flows through our system:

graph TD
    A[Wearable Devices: Apple/Garmin/Whoop] -->|Webhook/API| B[Go Ingestion Service]
    B -->|TS.ADD| C[(RedisTimeSeries)]
    C -->|Query| D[Grafana Dashboard]
    D -->|Visualization| E[User]

    subgraph "Infrastructure (Docker)"
    C
    D
    end
Enter fullscreen mode Exit fullscreen mode

Prerequisites πŸ› οΈ

Before we dive into the code, ensure you have the following installed:

  • Docker & Docker Compose
  • Go (1.20+)
  • A basic understanding of Redis commands

Step 1: Spin up the Stack with Docker 🐳

We’ll use the redis/redis-stack image because it comes pre-packaged with the RedisTimeSeries module, and a standard Grafana image.

# docker-compose.yml
version: '3.8'
services:
  redis:
    image: redis/redis-stack:latest
    ports:
      - "6379:6379"
      - "8001:8001" # RedisInsight UI

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    environment:
      - GF_AUTH_ANONYMOUS_ENABLED=true
    depends_on:
      - redis
Enter fullscreen mode Exit fullscreen mode

Run docker-compose up -d to get your infrastructure humming.

Step 2: Ingesting Data with Go 🐹

We need a lightweight service to receive data (e.g., Heart Rate, HRV, Steps) and push it into Redis. RedisTimeSeries uses the TS.ADD command, which is perfect for high-frequency wearable data.

package main

import (
    "context"
    "fmt"
    "github {dot} com/redis/go-redis/v9"
    "time"
)

var ctx = context.Background()

func main() {
    rdb := redis.NewClient(&redis.Options{
        Addr: "localhost:6379",
    })

    // Simulate receiving a Heart Rate data point
    heartRate := 72.5
    timestamp := time.Now().UnixMilli()
    sensorID := "apple_watch_series_9"

    // TS.ADD key timestamp value [RETENTION retentionPeriod] [LABELS label value...]
    err := rdb.Do(ctx, "TS.ADD", 
        fmt.Sprintf("health:heart_rate:%s", sensorID), 
        timestamp, 
        heartRate, 
        "LABELS", "type", "heart_rate", "source", sensorID,
    ).Err()

    if err != nil {
        fmt.Printf("Failed to add data: %v\n", err)
    } else {
        fmt.Println("βœ… Data point ingested successfully!")
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Visualizing in Grafana πŸ“Š

  1. Open Grafana at http://localhost:3000.
  2. Add a Data Source and search for Redis.
  3. Set the URL to redis:6379.
  4. Create a new Dashboard and add a "Time series" panel.
  5. Use the Query: TS.RANGE health:heart_rate:apple_watch_series_9 - +.

Moving to Production: The "Official" Way πŸ₯‘

While this setup is great for a weekend project, managing multi-source data at scale requires handling rate limits, data normalization, and OAuth2 flows for different wearable vendors.

If you're looking for more production-ready patterns, advanced data synchronization logic, or how to handle massive scale in health-tech apps, I highly recommend checking out the technical deep-dives over at the WellAlly Tech Blog. They cover the nuances of building resilient health data pipelines that go far beyond basic CRUD operations.

Conclusion 🏁

You’ve just broken down the walls of your wearable ecosystem! By leveraging RedisTimeSeries, you have a database that can handle thousands of heart rate samples per second with negligible latency.

Next Steps:

  • Try adding Garmin Connect API integration.
  • Implement TS.CREATERULE in Redis to automatically downsample your data (e.g., calculating hourly average heart rate).
  • Add alerting in Grafana to notify you if your recovery score (HRV) drops too low!

Happy hacking, and stay healthy! πŸƒβ€β™‚οΈπŸ’¨


Love this tutorial? Follow me for more "Learning in Public" sessions. Don't forget to star the repo and share your own dashboards in the comments!

Top comments (0)