If you’re a cyclist who’s ever wondered whether Strava Premium is worth it—or resented paying $80/year just to see your Normalized Power and training curves—VeloMate might be your answer. I

t’s a self-hosted analytics platform that calculates all the advanced metrics Strava hides behind a paywall, stores everything locally, and gives you interactive Grafana dashboards to obsess over your training data.

Think of it as TeslaMate for cyclists: automatic data ingestion from Strava, local computation of sophisticated fitness metrics (CTL, ATL, TSB, Normalized Power, Intensity Factor), and pre-built dashboards that actually make sense.

No subscriptions, no black boxes, no proprietary algorithms you can’t trust.

What is VeloMate?

is an open-source cycling data platform built for self-hosters, data enthusiasts, and cyclists who want complete control over their training analytics.

At its core, VeloMate does three things:

  1. Pulls your activities from Strava — Automatically syncs every 10 minutes using OAuth 2.0. No manual uploads, no endless clicking
  2. Computes advanced metrics locally — Normalized Power, Training Stress Score, Chronic Training Load, Acute Training Load, Training Stress Balance—all the cycling-specific metrics that show how your fitness is actually trending
  3. Visualizes everything in Grafana — Three pre-built dashboards covering overview (lifetime stats, fitness curves), activity details (power zones, aerobic decoupling), and long-term progression (6-month trends, personal records)

It also includes an intelligent route planner that generates cycling routes by combining 10 data sources: elevation, weather, air quality, popular Strava segments, cafes, viewpoints, bike shops, elevation profiles, daylight safety, and your own ride history.

Why VeloMate instead of Strava Premium?

  • No subscription fee — One-time deployment, then free forever
  • Your data, your infrastructure — Stays on your server; nothing uploaded to third parties
  • Metric transparency — Every calculation uses cycling-standard formulas from Golden Cheetah and WKO5
  • Multi-device smarts — Merge data from your Garmin, smartwatch, and phone intelligently (power data wins, but keeps HR from another device if it’s richer)
  • Offline dashboards — After initial sync, Grafana dashboards work even if Strava API is down
  • Extensible — Full access to PostgreSQL; run any custom analysis you want

VeloMate requires:

  • A server to run Docker (Raspberry Pi 4+ works, but 2GB+ RAM recommended)
  • A Strava account with API credentials (free tier is fine)
  • Home coordinates configured for route planning
  • ~5 minutes of initial setup

It’s not a mobile app; you’ll view dashboards via web browser. The route planner is CLI-only, but spits out interactive HTML previews and downloadable GPX files.


Tech Overview

VeloMate is built on a straightforward architecture:

The Ingestor (Python service, runs every 10 minutes):

  • Authenticates to Strava via OAuth 2.0
  • Pulls new activities and per-second telemetry (GPS, heart rate, power, cadence, elevation)
  • Classifies rides (outdoor road, gravel, indoor trainer, Zwift, e-bike)
  • Computes metrics: NP, IF, VI, EF, TRIMP (per activity) and CTL/ATL/TSB (daily aggregate)
  • Handles multi-device deduplication automatically
  • Stores everything in PostgreSQL

The Database (PostgreSQL 15):

  • Four main tables: activities, activity_streams (per-second data), athlete_stats (daily fitness curves), sync_state (API bookmarks)
  • Indexed for fast Grafana queries
  • Data persists in Docker volumes; survives restarts

The Dashboards (Grafana 12.4, pre-configured):

  1. Overview — Lifetime stats, fitness curves (CTL/ATL/TSB), daily charts split by ride type
  2. Activity Details — GPS map, power/HR zones, power duration curve, aerobic decoupling, per-km splits
  3. All Time Progression — 6-month scatter plots with trend lines, FTP progression, zone polarization, YoY comparisons

The Route Planner (Python CLI):

  • Accepts distance or duration targets, waypoints, surface preference (road/gravel/MTB), weather checks
  • Integrates 10 data sources: Valhalla routing (OpenStreetMap), Overpass (POIs), Komoot (highlights), Open-Meteo (weather), elevation, ride density, daylight times, and more
  • Outputs GPX + interactive HTML preview with route statistics

License: AGPL-3.0 ❤️


Self-Hosting VeloMate with Docker

Prerequisites

Before starting, you’ll need:

  • Docker + Docker Compose installed
  • A Strava account (free)
  • 512 MB+ RAM (1GB+ recommended)
  • Your home coordinates (for route planning)

Getting Strava API Credentials

  1. Go to
  2. Create an app (doesn’t need to be public)
  3. Copy your Client ID and Client Secret
  4. Authorize it at: https://www.strava.com/oauth/authorize?client_id=YOUR_CLIENT_ID&response_type=code&redirect_uri=http://localhost&scope=read,activity:read_all
  5. You’ll get a code in the URL; exchange it for a refresh token (VeloMate README has the exact curl command)

Deployment

# Clone the repository
git clone https://github.com/elduty/velomate.git
cd velomate

# Copy the example environment file
cp .env.example .env

# Edit .env with your credentials
# Required fields:
# STRAVA_CLIENT_ID=xxx
# STRAVA_CLIENT_SECRET=xxx
# STRAVA_REFRESH_TOKEN=xxx (from oauth above)
# POSTGRES_PASSWORD=choose-a-strong-password
# GRAFANA_PASSWORD=choose-a-strong-password

nano .env  # or your favorite editor

# Start the stack
docker compose up -d

# Wait for PostgreSQL to be ready (~30 seconds)
# Check status
docker compose ps

What this does:

  • Starts PostgreSQL 15 (port 5423, persistent storage)
  • Starts the VeloMate Ingestor (pulls from Strava every 10 minutes)
  • Starts Grafana 12.4 (port 3021, pre-configured dashboards)

First run takes 5-15 minutes:

  • Ingestor will pull your last 12 months of activities from Strava
  • Computes Normalized Power, Training Stress Scores for each ride
  • Calculates daily CTL/ATL/TSB fitness curves
  • All data indexed and ready for dashboards

Access your dashboards:

http://localhost:3021
username: admin
password: (whatever you set GRAFANA_PASSWORD to)

On first login, you’ll see three dashboards: Overview, Activity Details, and All Time Progression.

Syncing Continues Automatically

After setup, the ingestor runs every 10 minutes (configurable) and keeps your metrics up to date:

  • New activities from Strava → automatically synced
  • Metrics pre-computed → no lag in dashboards
  • Historical activities → retroactively updated if your FTP changes (via VELOMATE_RESET_RIDE_FTP env var)

Install the CLI on your local machine:

# Clone or download the repo
cd velomate

# Create Python environment
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt

# Create config
mkdir -p ~/.config/velomate
cp config.example.yaml ~/.config/velomate/config.yaml

# Edit with your home coordinates and DB connection
nano ~/.config/velomate/config.yaml

# Generate a route
velomate plan --distance 50 --loop

# Output includes GPX download link + interactive HTML preview

The CLI connects to your PostgreSQL database (so it uses your ride history and metrics for route intelligence) and generates routes using Valhalla (free, open routing engine).


Why This Matters

The cycling data space is dominated by Strava and Garmin—massive platforms that extract value from your data. VeloMate flips the model: your data stays with you.

More importantly, fitness metrics are not magic. Training Stress Score, Chronic Training Load, Normalized Power—these are well-established formulas from exercise physiology. There’s no reason they should be locked behind a paywall. VeloMate computes them using the same algorithms as Golden Cheetah (free, desktop tool) and WKO5 (paid, coaching tool), but in a scalable, self-hosted package.

If you’ve ever wanted to:

  • See your actual fitness trends (CTL/ATL/TSB) without paying Strava
  • Merge data from multiple devices intelligently
  • Query your own data with SQL
  • Generate training-aware route recommendations
  • Keep full control of your health data

…then VeloMate is worth 30 minutes of setup time.


Conclusion

VeloMate brings the self-hosting philosophy to cycling analytics. It’s not a replacement for Strava’s social features or segment leaderboards—those aren’t the point. But if you care about your data, your fitness trends, and your routes, it’s a solid alternative that respects your privacy and doesn’t ask for a credit card.

Next steps:

  1. Set up Strava API credentials (5 minutes)
  2. Deploy with docker compose up -d (2 minutes)
  3. Watch your fitness curves build as data syncs (10-15 minutes)

Alternatives to consider:

  • — Desktop app, manual imports, same metrics, no ingestor
  • — Similar architecture, but for Tesla vehicles (inspiration for VeloMate)
  • Strava Premium — $80/year, cloud-hosted, less transparent

For self-hosters who want full control and transparency, VeloMate is the clear winner.


FAQ

VeloMate handles it gracefully. Metrics prioritize power data (more accurate), but fall back to heart rate when power isn’t available. Each activity shows which streams were used for calculations (in the database).
The ingestor needs internet to pull from Strava. But once data is synced, Grafana dashboards work fully offline. Route planning requires internet for routing/weather APIs.
Yes—anything that syncs to Strava. Garmin watches, Apple Watch, Zwift, indoor trainers all work. VeloMate merges multi-device data intelligently.
No. VeloMate only communicates with Strava (for sync) and optional routing APIs (Valhalla, Overpass, Open-Meteo). No third parties, no analytics, no telemetry.
A year of cycling data (200-500 rides) takes ~500MB-2GB PostgreSQL storage. Depends on power meter and sensor density. SRAM very cheap at scale.
Yes, Pi 4+ (2GB RAM minimum, 4GB+ recommended). Fitness metric calculations are lightweight. Main bottleneck is dashboard rendering if you have 5+ years of historical data.
On first run, VeloMate pulls your last 12 months automatically. After that, it syncs incrementally every 10 minutes. You can configure POLL_INTERVAL_MINUTES in .env.
Yes. Latest release v1.2.0 (March 2026) added point-to-point routing. Active development with regular updates and community support.

Ready to take control of your cycling data? and start self-hosting your fitness analytics.