A single-binary Grafana Loki alternative

Loki does not index your logs. It indexes the labels you attach to them.

That one design decision explains everything people like about Loki and everything they trip over. Storage is cheap because only labels are indexed. Search is fast when you pick the right stream. And the day someone adds a label with ten thousand values, the whole thing gets slow and nobody knows why.

Where Loki fits, honestly

Loki is good software solving a real problem at real scale. If you already run Prometheus and Grafana, Loki slots in beside them and you get metrics and logs on one dashboard with the same label vocabulary. At Kubernetes scale, its object-storage economics beat anything a single server can do.

This page is for the other case: you are a small team, you picked Loki because it was the self-hosted option everyone recommends, and you now maintain a logging stack instead of using one.

Count the moving parts

A working Loki install is not one thing.

  • Loki — monolithic mode is one process, but read/write/backend or full microservices mode is several.
  • A collector — Promtail, or Grafana Alloy since Promtail went into maintenance.
  • Grafana — Loki has no UI of its own. You query it through Grafana.
  • Object storage — S3, GCS or MinIO for chunks. Filesystem works for one node and stops being a good idea after that.
  • A compactor — for retention and index compaction.

Each of those has a config file, an upgrade path, and a way to fail. None of them is hard on its own. Together they are a part-time job.

Central Logging is one executable:

./centrallogging

That starts an HTTPS server with an auto-issued certificate, a web UI, and an ingest API. No collector to deploy, no Grafana to stand up, no bucket to create. Deploy has the rest, and there is not much of it.

Side by side

Grafana Loki Central Logging
Components to run Loki + collector + Grafana + object storage One binary
Storage Chunks in object storage SQLite on local disk
Index Labels only Full-text index plus SQL over every column
Query language LogQL SQL and full-text search
UI Grafana Built in
Cardinality management You own it Not a concept
Cron monitoring No Yes
Uptime monitoring No Yes
Host monitoring No Yes
Clustering / HA Yes No
Multi-tenancy Yes No
Licensing Open source, or Grafana Cloud pricing $187 once
Scale ceiling Very high ~10GB/day

The cardinality trap

Loki builds one stream per unique combination of label values. Streams are the unit of everything: storage, indexing, query planning.

So this is fine:

{app="api", env="prod"}

And this is a bad afternoon:

{app="api", env="prod", user_id="8814", request_id="a3f9..."}

Every distinct user_id creates a stream. Chunks fragment, the index grows, queries slow down, and ingestion starts rejecting writes. The fix is to move those fields out of labels and into the log line, where they are no longer indexed and you find them by grepping with |= instead.

That is a real skill, and it is a skill about Loki rather than about your logs. You are designing a schema for a database you did not want to think about.

Central Logging has no labels. Lines go into a table with a timestamp, and any field inside them is reachable with json_extract. High-cardinality fields cost nothing special because nothing is pre-indexed by them.

LogQL and SQL answer different questions

LogQL starts with a stream selector. You must name the stream before you can filter it:

{app="api"} |= "error" | json | status >= 500

That reads well and it is fast. What it does not do is answer analytical questions without turning into a metric query with its own syntax.

Central Logging gives you SQL over a logs table with timestamp and msg columns:

SELECT
    json_extract(msg, '$.status')  AS status,
    json_extract(msg, '$.path')    AS path,
    COUNT(*)                       AS hits
FROM logs
WHERE json_valid(msg)
  AND json_extract(msg, '$.status') >= 500
  AND timestamp > strftime('%s', 'now', '-1 hour')
GROUP BY status, path
ORDER BY hits DESC
LIMIT 20;

Group by, join, window functions, subqueries. If you know SQL you already know the query language, and there is no stream to select first.

When SQL is more than the question deserves, full-text search is there too:

+timeout -healthcheck payment

One thing to know about timestamp: it is when the server received the line, not when your application emitted it. Under normal conditions they are close. If ordering by event time matters, parse your own timestamp field out of msg and sort on that.

Moving your log stream over

Loki users ship with Promtail or Alloy. Neither speaks Central Logging’s API, so this is a swap rather than a redirect.

System and journald logs. Install the CL Agent. It reads the journal on Linux and posts to the server. This replaces the Promtail journal scrape.

Applications that already log JSON. POST the lines. Newline-separated, as many as you like per request:

curl -X POST https://logs.example.com/api/v1/ingest_logs/YOUR-SOURCE-TOKEN \
    -d @mylogs.txt

The token can go in a header instead of the URL if you would rather not have it in a path:

curl -X POST https://logs.example.com/api/v1/ingest_logs \
    -H "Authorization: Bearer YOUR-SOURCE-TOKEN" \
    -d @mylogs.txt

gzip bodies work too.

Containers. The Docker guide covers getting container stdout off the host before docker rm takes it with them.

Existing syslog infrastructure. The rsyslog guide covers omhttp with a disk-backed queue, so a server restart loses nothing.

Things Loki does that this does not

A fair comparison lists these, because they are the reasons to stay.

  • Horizontal scale. Loki spreads ingest and query across machines and stores chunks in object storage. Central Logging is one process on one server with one disk. That is a real downgrade in both ceiling and resilience.
  • Cheap long retention. Years of logs in S3 costs very little. Years of logs on a local SSD costs what SSDs cost.
  • One pane with your metrics. If your team lives in Grafana and correlates logs with Prometheus series by shared labels, that workflow does not exist here.
  • Multi-tenancy. Loki isolates tenants with X-Scope-OrgID. Central Logging has one admin account and no per-user permissions.
  • The ecosystem. Alloy, Grafana dashboards, Mimir, Tempo, and everything built around them.
  • A vendor to call. Grafana Labs sells support. Central Logging is email.

What you get in exchange

  • Nothing to design before you search. No labels, no cardinality budget, no chunk tuning.
  • Backups are file copies. SQLite files in a directory. No object-storage lifecycle rules, no snapshot API.
  • Monitoring in the same binary. Cron monitoring, website monitoring, host monitoring and Prometheus scraping. Loki users run those as separate tools.
  • One fixed cost. No per-GB metering, ever.
  • An open format. Any SQLite client reads your data. Leaving needs no export step.

Who should choose which

Stay with Loki if you run Kubernetes at scale, if your team already lives in Grafana, if you need years of retention on cheap storage, or if multi-tenancy is a requirement.

Switch if you chose Loki because it was the self-hosted default, if your log volume is comfortably under 10GB/day, if nobody on the team enjoys explaining cardinality, or if you want cron and uptime monitoring without adding two more services.

Try it

The free download is the complete product, not a trial.

Run it next to Loki for a week. Fork a copy of your log stream into it. Then ask which one you opened when something broke.

14-day refund if you buy and it does not fit. Deploy has the setup.

💌 Get notified on new features and updates

Only sent when a new version is released. Nothing else.