Open-source project
middlewarehq/middleware avatar
middlewarehq/middleware

Middleware (middlewarehq/middleware): self-hosted DORA metrics in one Docker container

✨ Open-source DORA metrics platform for engineering teams ✨

1,629 stars170 forksTypeScriptApache-2.0

At a glance

What is it?
Middleware is an Apache-2.0 platform that collects the four DORA metrics from your CI/CD and project management tools and shows them in a dashboard. It installs as a single Docker image with bundled Postgres, Redis and a cron sync, and the docs leave several operational questions open.
Who is it for?
Adopt Middleware if you want DORA metrics on infrastructure you control and you are willing to run a single container with bundled Postgres, Redis and cron, and to check what the sync actually pulls from your integrations before you point it at production data. Do not adopt it if you need per-service or per-team slicing, if you cannot spare the RAM the README asks for, or if you expect a documented upgrade and rollback path.
Can I use it commercially?
Yes. Apache-2.0 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 46 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 18, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What Middleware measures, and who it is actually for

Middleware tracks the four DORA metrics: deployment frequency, lead time for changes, mean time to restore, and change failure rate. The README defines each one plainly, for example lead time as "the time it takes for a commit to make it into production". The audience is named in the same paragraph: engineering leaders who want to measure and analyze team effectiveness. That framing matters, because this is not a CI dashboard you open to debug a pipeline. It is a reporting layer that sits above your existing tools and turns their events into four numbers over time.

The repository topics list dev-productivity, engineering-management and pr-review alongside dora-metrics, which matches the README's feature list: integrations with CI/CD tools, automated collection and analysis, visualization, customizable reports and dashboards, and integrations with project management platforms. The specific vendors are not enumerated in the README text, so anyone evaluating fit should check the integration list in the app rather than assume a given provider is covered.

How the collection pipeline is put together

The architecture is visible in the Dockerfile and docker-compose.yml. There are three Python services and one frontend. The analytics server listens on port 9696 and is reached internally at http://localhost:9696. A separate sync server listens on port 9697, reached at http://localhost:9697, and it is the process that pulls data from your integrations on a schedule. The web UI is served on port 3333. A cron entry is installed at /etc/cron.d/cronjob from setup_utils/cronjob.txt, so the sync runs on a timer rather than only on demand.

State lives in Postgres, with Redis used alongside it, and both are bundled into the image rather than being external services you point at. The compose file mounts two named volumes: dev_postgres_data at /var/lib/postgresql/15/main and dev_keys at /app/backend/analytics_server/mhq/config. The second one holds key material, which is why the README's cleanup instructions remove it separately. The Dockerfile sets DEFAULT_SYNC_DAYS=31, so a fresh deployment looks back roughly a month on its first run. If you want a longer history on day one, that build argument is the knob, and it is set at build time, not in the UI.

Installing Middleware with Docker and opening the dashboard

The README's quick start assumes Docker is installed and running. It creates two volumes first, then starts the container with three published ports and both volumes attached. The image is middlewareeng/middleware:latest.

bash
docker volume create middleware_postgres_data
docker volume create middleware_keys
docker run --name middleware \
  -p 3333:3333 \
  -p 9696:9696 \
  -p 9697:9697 \
  -v middleware_postgres_data:/var/lib/postgresql/data \
  -v middleware_keys:/app/keys \
  -d middlewareeng/middleware:latest
docker logs -f middleware

After the run command returns, follow the logs. The README says to wait for the services to come up, and the app is then available at http://localhost:3333 on the host. The logs are the only progress signal the quick start gives you, so keep that terminal open until the frontend responds.

For a source checkout instead of the published image, the README points at dev.sh in the project root, which writes a .env file and runs docker compose watch. It also mentions local-setup.sh as optional and env.example as the file to edit, including setting ENVIRONMENT=prod for a production-style setup.

bash
git clone https://github.com/middlewarehq/middleware
cd middleware
./dev.sh

The README warns that local development wants at least 16GB of RAM. The compose file binds every published port to 127.0.0.1, including DB_PORT 5434 and REDIS_PORT 6385, so nothing is exposed beyond the host by default. If you change ports, the README says to edit docker-compose.yml rather than passing different flags.

The upgrade path is a container swap, and that is the weak point

There is no migration command in the README. The documented way to move to a newer build is to pull the image, remove the existing container, and start a new one against the same volumes.

bash
docker pull middlewareeng/middleware:latest
docker rm -f middleware || true
docker run --name middleware \
  -p 3333:3333 \
  -v middleware_postgres_data:/var/lib/postgresql/data \
  -v middleware_keys:/app/keys \
  -d middlewareeng/middleware:latest
docker logs -f middleware

Two things stand out. First, this recipe publishes only port 3333, while the install command publishes 9696 and 9697 as well. If something on your network talks to the analytics or sync server directly, the upgrade command silently drops that access. Second, the README does not document rollback. There is no supported way to go back to a previous image version if a new build changes the database schema, and the only destructive escape hatch documented is deleting both volumes. That is a real risk for anyone tracking :latest, and it is the strongest argument for pinning a tag and taking a database dump before each upgrade.

The release history supports that caution. The most recent release listed is 0.3.1 from 2025-05-30, preceded by 0.3.0 on 2025-05-09 and 0.2.0 on 2024-11-21. Releases are infrequent, which cuts both ways: fewer upgrade events to manage, but also long gaps in which a bug you hit may not get a point release.

Where Middleware is the wrong tool

Change failure rate and mean time to restore are only as good as the incident signal feeding them. The README does not describe how incidents are detected or correlated with deployments, so if your team does not record failures in a tool Middleware reads, those two metrics will be thin or misleading. Deployment frequency and lead time are easier, since they come from commits and deploys, but they still depend on your CI/CD integration being configured correctly.

There is also a scope limit. The README describes team-level measurement, not per-service or per-repository breakdowns, and the roadmap is referenced in the table of contents without its contents appearing in the README text. If your question is "which service is slowing us down", this is not the layer that answers it. And because the whole stack, Postgres, Redis, cron, three services and a frontend, runs inside one container, this is a single-host deployment by design. There is no documented multi-node or external-database configuration, so a team that needs high availability should look elsewhere rather than trying to split the image apart.

How it differs from building DORA metrics on top of your CI provider

The obvious alternative is the analytics that already ship with your CI/CD or source host. Those tools already have the commit and deploy events, so the data collection problem is solved for you, and there is nothing to run. The difference is control and join. Middleware pulls from several systems at once, CI/CD plus project management, which is what lets it compute metrics that no single provider sees end to end. A CI vendor only knows its own pipeline; it cannot tell you how long a change sat in review before the pipeline ever ran.

The cost of that join is operational. You are running a container with an embedded database, a scheduler and key material on a volume, and you own the backups, the port allocation and the upgrade. A hosted CI dashboard costs nothing to operate and cannot be self-hosted. Middleware's value proposition is that the data stays on your host, and the price is that the failure modes are yours. That trade is reasonable for a platform team that already runs Postgres and cron in anger, and unreasonable for a small team that wants a number on a screen this afternoon.

Licence and what you are taking on

Middleware is licensed under Apache-2.0, per the licence badge in the README and the LICENSE file in the repository root. That is a permissive licence: it allows commercial use and modification, and it includes a patent grant. It also means there is no copyleft obligation if you fork it or embed parts of it in an internal tool. This is a description of the licence text, not legal advice; if you plan to redistribute a modified build, read the LICENSE file and the NOTICE requirements yourself.

The maintenance picture is mixed and worth stating plainly. The repository is not archived, and the last push was on 2026-08-03. But the release cadence is slow, with 0.3.1 in May 2025 as the newest tagged release. Commits landing on main between releases is not the same as a supported version, and the README documents no versioning or support policy. Budget for reading the commit history when you upgrade, not just the release notes.

The upgrade cost is the container swap described above: pull, remove, run, watch the logs. There is no documented migration step and no documented rollback, so the practical cost is the dump you take yourself before each pull. The troubleshooting section covers the common failure, a container name conflict, with docker rm -f middleware, and it shows how to wipe all data by removing both volumes. That last command is the only reset path the README offers, which tells you how the project expects you to recover from a bad state.

Editorial conclusion

Adopt Middleware if you want DORA metrics on infrastructure you control and you are willing to run a single container with bundled Postgres, Redis and cron, and to check what the sync actually pulls from your integrations before you point it at production data. Do not adopt it if you need per-service or per-team slicing, if you cannot spare the RAM the README asks for, or if you expect a documented upgrade and rollback path. Verify two things first: the DEFAULT_SYNC_DAYS value your deployment uses, and whether the ports 3333, 9696, 9697 and 5434 are free on the host, because the compose file binds all of them to 127.0.0.1.

Frequently asked questions

How do I install Middleware?

The README's quick start requires Docker to be installed and running. It creates two volumes, middleware_postgres_data and middleware_keys, then runs the middlewareeng/middleware:latest image with ports 3333, 9696 and 9697 published and both volumes attached. The app is then available at http://localhost:3333.

What is Middleware software?

Middleware is an open-source tool that helps engineering leaders measure and analyze team effectiveness using the DORA metrics. The README lists deployment frequency, lead time for changes, mean time to restore and change failure rate as the four values it tracks.

Is an API a middleware?

The README does not discuss APIs as middleware. It describes Middleware as a DORA metrics platform with an analytics server on port 9696 and an internal sync API on port 9697, which are internal components of the application rather than the subject of the tool.

Official sources

  1. License: Apache-2.0
  2. middlewarehq/middleware on GitHub
  3. Project website
  4. README
  5. Releases
Community notes

Community notes