MySpeed: scheduled internet speed tests with a 30 day history
A speed test analysis software that shows your internet speed for up to 30 days
At a glance
- What is it?
- MySpeed is a self-hosted JavaScript application that runs recurring speed tests against Ookla, LibreSpeed or Cloudflare servers and stores the results for a retention period you choose. It is built for people who want a local record of line quality rather than a one-off browser test.
- Who is it for?
- Adopt MySpeed if you need a local, long-running record of line quality and already run Docker or Bun on the host that sits on the connection you are measuring. Do not adopt it if you want a single instant reading, or if you cannot give the container persistent storage, because the data volume is the whole point.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 11 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 25, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem MySpeed solves for a home lab or a small office
A browser speed test answers one question at one moment. That is fine when you are diagnosing a fault you already noticed. It is useless when you want to know whether your line degrades every evening, whether an ISP change actually helped, or whether the dropouts you blamed on Wi-Fi were happening at the modem. MySpeed is built around the second question. The README describes it as software that "records your internet speed over a fully configurable retention period", and the repository description puts the default horizon at up to 30 days. The intended user is someone who controls the network endpoint: a home lab operator, a small office admin, or anyone running a server on the connection they want to measure. The project is not a consumer web service. You run it, you own the database, and the history lives on your disk.
How the test scheduling and storage actually fit together
The repository layout makes the shape of the system visible. There is a server/ directory holding the Express application, a client/ directory for the front end, and a top-level package.json that runs both. Tests are scheduled with cron expressions, and the dependency list confirms the mechanism: cron-parser and cron-validator parse and validate the schedule, node-schedule fires the jobs, and moment-timezone handles time zones. Persistence goes through Sequelize, with mysql2 as a driver, so the application talks to a relational database rather than a flat file. Results feed a statistics view that the README shows under Homepage (Statistics View), and the same data is exposed to Prometheus through prom-client, which is why Grafana support is listed as a feature. A Dockerfile defines a multi-stage build: the client is compiled in one stage with Bun, the server dependencies and generated migrations and integrations in a second, and the final image runs bun run server/index.js with /myspeed/data as a volume and port 5216 exposed. Two generated artifacts, migrations and integrations, are produced by scripts in scripts/ before the server starts, which is why the dev script runs generate-migrations and generate-integrations first. The practical consequence is that the container needs a writable data volume, not just a running process.
Installing MySpeed from the Dockerfile and running a first test
The README points to separate Linux and Windows setup guides on docs.myspeed.dev rather than listing install steps inline, so the exact host-level instructions are on that site. What the repository does give you is a Dockerfile that builds a runnable image. The final stage declares a volume at /myspeed/data and exposes port 5216, so a build and run from a clone looks like this. The volume mount is the part to get right: without it, the test history disappears when the container is replaced.
docker build -t myspeed .
docker run -d --name myspeed -p 5216:5216 -v myspeed-data:/myspeed/data myspeedThe image sets TZ=Etc/UTC, which matters because cron schedules are evaluated in the container's time zone unless you override it. If your tests should run at 20:00 local time, pass a TZ value or the schedule will drift against your wall clock. Once the container is up, the web interface is on port 5216. From there you add a server, choose between Ookla, LibreSpeed and Cloudflare as the test backend, and set the interval with a cron expression. The README does not document the exact field names in the server-add form, so treat the UI as the source of truth for those.
If you prefer to run from source, the package.json scripts are the entry points. The dev script generates migrations and integrations, then starts the server with bun run --watch server/index.js and the client dev server alongside it.
bun install
bun run devThe build:binary script compiles a standalone MySpeed binary with bun build --compile, which is the path to take if you want to avoid a container runtime on the host.
Where MySpeed is the wrong tool
MySpeed measures throughput between your host and a public test server. It does not measure your LAN, your Wi-Fi airtime, or the latency of the services you actually use. If your complaint is that video calls stutter while a speed test reads 500 Mbps, MySpeed will record the 500 Mbps and tell you nothing about the jitter on the call path. Continuous measurement against a third-party endpoint also has a cost: every scheduled test consumes bandwidth on the line you are trying to characterise, and on a metered or capped connection a tight cron interval is self-defeating. The retention setting is the other trap. The project advertises retention "from a few days to forever", and forever means the database grows without bound. The v1.0.9 release notes mention storage management, so there is some handling for this, but the README does not document a retention policy mechanism, a size cap, or a pruning schedule. If you set unlimited retention on a busy schedule, plan to manage that database yourself. Finally, the health check notifications cover email, Signal, WhatsApp and Telegram. If your alerting runs through something else, you are integrating via the Prometheus endpoint instead.
MySpeed against running Ookla's own CLI on a cron job
The obvious alternative is to skip the application and schedule the Ookla speedtest CLI yourself, writing each result to a file or a time series database. That approach is smaller and has no web UI to maintain. The difference is in what you get for the extra weight. MySpeed bundles server selection across three backends, so you can compare an Ookla result against a LibreSpeed or Cloudflare result without writing adapters for each. It renders statistics and a list view out of the box, and it exposes Prometheus metrics through prom-client, which means a Grafana dashboard is a scrape configuration away rather than a parsing project. The CLI route gives you raw numbers and leaves every visualisation, every schema decision and every alert rule to you. If you already have a Grafana stack and only want one number per hour, the CLI is less machinery. If you want the history, the comparison across backends, and the notification channels without building them, MySpeed is the shorter path.
Maintenance, upgrades and the MIT licence
The last push to the development branch was on 2026-09-21, three days before this writing, so the repository is not dormant. The most recent tagged release is v1.0.9 from 2024-05-21, which is worth noting: the version number in package.json is also 1.0.9, so work since that tag has landed on the development branch without a corresponding release. If you deploy from a release tag you are running code that is over a year old, and the storage management and backend support described in the v1.0.9 notes are the ceiling of what you get. Building from development gets you current code with no release note to read first. Upgrades through the container path are a rebuild and a restart, but the schema is managed by generated migrations, so the container runs generate-migrations at build time and Sequelize applies them at startup. Back up /myspeed/data before replacing a container. The project is MIT licensed, which permits commercial and private use and modification; the LICENSE file at the repository root is the authority. That is a permissive licence and imposes no copyleft obligation on your own code, but it also means no warranty, and nothing here is legal advice.
Editorial conclusion
Adopt MySpeed if you need a local, long-running record of line quality and already run Docker or Bun on the host that sits on the connection you are measuring. Do not adopt it if you want a single instant reading, or if you cannot give the container persistent storage, because the data volume is the whole point. Before committing, verify three things on the docs site: which speed test backend you intend to use and whether it is reachable from your network, what retention period you configure, and whether the health check notification channel you need is one the project documents.
Frequently asked questions
How do I run MySpeed with Docker?
Build the image from the repository Dockerfile and run it with port 5216 published and a volume mounted at /myspeed/data. The volume is required if you want the test history to survive container replacement. The image sets TZ=Etc/UTC, so override the time zone if your cron schedules should follow local time.
Which speed test servers does MySpeed support?
The README lists Ookla, LibreSpeed and Cloudflare as the available speed test servers, and the v1.0.9 release notes mention LibreSpeed and Cloudflare support as additions. You choose between them when configuring a server in the interface.
How long does MySpeed keep test results?
Results are stored for a retention period you configure, which the README describes as anywhere from a few days to forever, and the repository description cites up to 30 days. The README does not document an automatic pruning schedule, so unlimited retention means you manage database growth yourself.
Can MySpeed send alerts when a test fails?
Yes. The README lists health checks that notify you via email, Signal, WhatsApp or Telegram in case of errors or downtime. For other alerting systems, the Prometheus endpoint is the integration point.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/gnmyt-myspeed)