Features
Everything muscles does, with the main features first.
What companies choose muscles for
- Rollup ladders Per-second, per-minute and per-hour totals are kept as rows arrive, so a dashboard over years of data reads a few summary rows.
- Tables that live elsewhere Query Iceberg, PostgreSQL, ClickHouse, Elasticsearch and more in place, and join them with each other and with your stored tables.
- Durable writes A write is acknowledged after it is on disk, so a crash after that loses nothing, and a retried batch is stored once.
- Kafka ingest Avro topics become tables with the columns of their schema, and a record is acknowledged after it is synced.
- Cold tier on S3 Parts older than an age you set move to your bucket and stay queryable.
- ClickHouse HTTP interface ClickHouse drivers, Grafana, JDBC tools and Polars connect over HTTP.
- Column policies and masking One statement masks or refuses a column for a role, on the one copy of the table.
- Full-text and vector search Rank text with BM25 and embeddings by distance inside SQL, with no search cluster beside the database.
- Tamper-evident audit log Who ran what, in hash-chained blocks that a check can prove intact.
- Prometheus remote write Prometheus pushes its metrics in, and you query them with SQL and join them to your tables.
- Alerts in SQL A rule over a query result fires to Alertmanager or a webhook.
- One binary, then a cluster One static binary, a container image, a Helm chart and an operator; add query, ingest and data nodes when one server is not enough.
- Time series, rollups and logs
- Analytical SQL
- Functions, types and formats
- Getting data in
- Data that lives elsewhere
- Search, vectors and language models
- Security and compliance
- Durability, storage and upgrades
- Running it
- Connect your tools
- Tracing, console and documentation
Time series, rollups and logs
Tables sort by time, rollups answer time-bucket queries from rows that are already summed up, and views keep aggregates up to date as rows arrive.
Rollup ladders
CREATE ROLLUP builds a ladder of resolutions, such as one second, one minute and one hour, over a source table. Every rung of the ladder keeps the count, sum, average, minimum, maximum and last value per time bucket and per key, updates as rows arrive, and survives a restart.
A trading desk stores every tick of a few thousand symbols. One ladder gives it per-second, per-minute and per-hour volume, high, low and average price for each symbol, so a chart of the last month reads a few buckets.
CREATE ROLLUP ticks_r ON ticks KEY (sym)
AGGREGATE (count(*) AS n, sum(qty) AS vol, min(px) AS lo,
max(px) AS hi, avg(px) AS mid)
RESOLUTIONS (1s, 1m, 1h);
SELECT toStartOfMinute(ts) AS minute, sym,
sum(qty) AS vol, min(px) AS lo, max(px) AS hi
FROM ticks GROUP BY minute, sym ORDER BY minute, sym;
Materialized views that update as rows arrive
A materialized view updates with every insert. Keep per-minute aggregates of access logs and query the aggregate instead of the raw lines.
One view counts 5xx responses per route and minute as the log lines arrive. Another lists the clients that request many different paths, which is a sign of scanning.
Alerts in SQL
CREATE ALERT defines a rule over a SQL result with a duration, labels and annotations. Alerts go to Alertmanager or to webhooks, and system.alerts lists the firing ones.
A substation stays above its load limit for fifteen minutes, and the alert reaches the on-call engineer through Alertmanager.
Time-bucket queries use the rollup on their own Available
A query that groups by
toStartOfMinute,toStartOfHour,date_truncortoStartOfIntervalreads the coarsest rung that fits plus the newest raw rows, and returns the same answer as a scan of the raw table.Raw rows age out, rollups stay Available
Once a rung holds a time range in full, muscles can drop the raw parts for it, so raw ticks age out while the minute and hour rungs stay. A query that reaches into the dropped range is refused, or returns a partial answer marked as such when you ask for one.
Views stay small Available
A view keeps one row per group, and background merges add up the partial counts, sums, minimums and maximums.
Backfill and rebuild of views Available
CREATE MATERIALIZED VIEW ... TO t BACKFILLfills a new view from the rows already in the source, andREBUILD MATERIALIZED VIEWreplaces its contents. Both survive a crash and replicate.A view that runs out of memory lags and catches up Available
All background work shares one memory budget. A view whose refresh does not fit falls behind, sets the metric
muscles_matview_laggingto 1 and catches up when memory is free.muscles_matview_lag_secondssays how far behind it is, so a dashboard can show the delay.Alert delivery Available
Alerts retry with backoff and wait in a bounded queue per target, and a firing alert is sent again on an interval.
Recording rules Available
CREATE RECORDING RULEruns a query on a schedule and exposes the result as Prometheus metrics on an authenticated endpoint.Time-grid queries Available
GROUP BY host EVERY 10sresamples a series onto a regular grid, withFILL, andrate,increase,avg_over_time,sum_over_timeandmax_over_timeread a range behind each grid point.
Analytical SQL
The dialect is close to ClickHouse SQL.
ASOF join
An ASOF join matches each row to the last row of another table at or before its own timestamp. The ON clause names the columns that must be equal and the one comparison of the time columns, and USING (sym, ts) says the same in short, with the time column last. The planner picks a sorted-merge or a hash algorithm, and the setting asof_join_algorithm overrides the choice.
Each trade gets the last quote at or before its own timestamp, so a report shows how far each trade was from the spread at that moment.
One row per key, the newest version
ReplacingMergeTree(version) with DEDUP KEY keeps the newest row for each key, and SELECT ... FINAL reads the merged result.
Order events arrive more than once with a rising version, and the table keeps the latest status of each order.
Columnar scans Available
A query reads only the columns it names, and sparse marks and zone maps let it skip data that cannot match.
Standard SELECT Available
WHERE,GROUP BY,HAVING,ORDER BYwith nulls first or last,LIMITandOFFSET,LIKEandILIKE,CASE, and aliases usable in every clause.Joins Available
INNER, LEFT, RIGHT and FULL equi-joins take
ONorUSING, a subquery or a CTE can be either side, andGROUP BYworks over a join.Subqueries and CTEs Available
Subqueries work in
FROM,IN,EXISTSand as single values,WITHclauses can read tables, and a derived table can be one side of a join.UNION and DISTINCT Available
UNION ALL,UNION DISTINCTandSELECT DISTINCTwork, also with aggregates and insideINSERT ... SELECT.Totals and rollups in GROUP BY Available
WITH TOTALSadds a totals row, andWITH ROLLUPadds a row for each shorter key prefix and a grand total.Expressions over aggregates Available
A SELECT list or a
HAVINGclause can combine aggregates, such assum(a) / count(), and compare them with constants.Query parameters Available
A query can carry typed placeholders such as
{name:Int64}, so a client does not build SQL by pasting values.Settings per query and per session Available
SELECT ... SETTINGSandSETchange the session settings, among them limits, join behaviour, search options andquery_priority.EXPLAIN and catalog statements Available
EXPLAIN,DESCRIBE,SHOW CREATE TABLE,SHOW TABLES,SHOW DATABASESandUSEwork, and the schema queries that DataGrip sends oversystem.tablesandsystem.columnssucceed.INSERT SELECT and CREATE TABLE AS SELECT Available
Copy a query result into a table, such as a daily summary built from raw events. You can name a subset of columns, ask for an atomic copy, run the copy on a sharded cluster, and make a retry safe with a token.
ALTER TABLE and UPDATE Available
Add, drop, rename and retype columns, change a TTL, add skip indexes, and update rows with a
WHEREclause. An update rewrites the affected parts, as a ClickHouse mutation does.Column defaults Available
A column can have a constant
DEFAULT, and an insert that leaves the column out gets the default in every input format.Dictionaries Available
CREATE DICTIONARYloads a table into memory with a flat, hashed or complex-key layout, anddictGet,dictGetOrDefaultanddictHaslook a key up inside a query.IP-range lookups Available
An
IP_TRIEdictionary maps an address to the network that contains it, for geo and allow-list lookups such as labelling each access-log line with the country and network of the client.Decimal numbers Available
Decimal(P, S)columns hold up to 18 digits and support arithmetic, casts and aggregates, also on a cluster, so invoice lines sum to the cent without float rounding.
Functions, types and formats
The reference pages list every function, type, format and setting. Here they are by family, with what each family is for.
340 scalar functions, by family
The reference lists 340 scalar functions, about 500 names when the ClickHouse spellings count.
String functions Available
Build, cut, pad, search and split text, with UTF-8 versions of the length and case functions:
concat,substring,left,right,replace,reverse,repeat,translate,position,starts_with,edit_distanceand more.Regular expressions Available
Match, extract and replace with a regular expression:
match,extract,extract_all,extract_groups,replace_regexp_one,replace_regexp_all,count_matches.Date and time functions Available
Bucket, shift, compare and format timestamps, all in UTC:
toStartOfMinute,toStartOfHour,toStartOfDay,toStartOfYear,toStartOfInterval,date_trunc,date_diff,date_add,date_sub,toYYYYMMDD,formatDateTime, ISO weeks and Unix timestamp conversion.Type conversion Available
About 70 conversions between integers, floats, decimals, dates, date-times, strings and IP addresses, each with
OrNullandOrZerovariants where ClickHouse has them.Math functions Available
Arithmetic, rounding, trigonometry, logarithms, powers, number theory, and the gamma and error functions:
abs,round,ceil,floor,pow,gcd,lcm,factorialand the integer division and modulo variants.JSON functions Available
Read a value, a key list or a type out of a JSON string:
json_extract_string,json_extract_int,json_extract_float,json_extract_bool,json_extract_raw,json_extract_keys,json_has,json_length,json_type,is_valid_jsonand the simple variants.URL functions Available
Take a URL apart and encode or decode it:
domain,top_level_domain,protocol,path,query_string,fragment,port,extract_url_parameterand thecut_*family.Hash and encoding functions Available
Hash a value for sampling, joins or masking, and convert between binary, hex and base64:
md5,sha1,sha256,sha512,city_hash64,sip_hash64,xx_hash64,wy_hash64,hex,unhex,bin,base64_encode.IP address functions Available
IPv4andIPv6column types, conversion to and from text and numbers, andis_ipv4_string,is_ipv6_string.Bit functions Available
bit_and,bit_or,bit_xor,bit_not,bit_test,bit_countand shifts.Array and lambda functions Available
Transform, filter, sort and sum arrays, with lambdas written as
x -> expr:arrayMap,arrayFilter,arrayExists,arraySum,arraySort,arrayConcat,arraySlice,arrayDistinct,arrayIntersect,arrayCumSumand about 25 more.Map functions Available
Map(K, V)columns withmap_keys,map_values,map_concat,map_from_arrays, and the aggregatessumMap,minMap,maxMap.Conditional and NULL functions Available
coalesce,if_null,null_if,assume_not_null,is_null,greatest,least, with three-valued logic in conditions.Formatting and system functions Available
format_readable_size,format_readable_quantity,format,to_type_name,version,host_name,timezone.Trained models in SQL Available
stochasticLinearRegressionandstochasticLogisticRegressiontrain a model as an aggregate, andeval_ml_methodapplies it to new rows.
55 aggregate functions, by family
Beyond count, sum, avg, min, max, any, argMin and argMax, the reference lists 47 more.
Quantiles Available
quantile,quantiles,median, with exact and interpolated variants of each.Distinct counts and sketches Available
uniq,uniqExact,uniqUpTo,groupBitmap,topK.Statistics and tests Available
Variance, covariance, correlation, skewness, kurtosis, entropy, linear and logistic regression, and the tests
studentTTest,welchTTest,mannWhitneyUTest,kolmogorovSmirnovTest.Event-sequence aggregates Available
windowFunnel,retention,sequenceMatch,sequenceCountanalyse ordered events per user or session, such as how many sessions went from product view to cart to checkout within an hour.Aggregate combinators Available
-If,-OrNull,-Array,-ForEach,-Stateand-Mergeapply to almost every aggregate and stack, as insumIfOrNull.Aggregate state columns Available
AggregateFunctioncolumns store the intermediate state of an aggregate, and-Stateand-Mergecombine states across rows and parts.
Window functions Available
row_number,rank,dense_rank,ntile,lag,lead,first_value,last_value,nth_value,percent_rank,cume_dist, plus 15 aggregates as windows, withROWSandRANGEframes and named windows.36 column types Available
Signed and unsigned integers from 8 to 64 bits, 32- and 64-bit floats, decimals, booleans, strings and fixed strings, dates, date-times and nanosecond timestamps, UUIDs, IPv4 and IPv6 addresses, enums, arrays and maps.
128-bit integers Available
Int128andUInt128columns store and return exact values in DDL, inserts, literals, comparisons,ORDER BYand every output format, so a 128-bit transaction id keeps all its digits.NULL values Available
Every column type accepts NULL, and
IS NULL,coalesceand the aggregates treat it as SQL does.Compression codecs Available
Columns compress with lz4 by default, and a
CODEC(...)clause picks delta, double-delta, gorilla or run-length coding. Anautomode picks one per column.Data-skipping indexes Available
minmax,set,bloom_filter,ngrambf_v1,tokenbf_v1indexes let a scan skip blocks, inCREATE TABLE,CREATE INDEXandALTER TABLE ... ADD INDEX.Result formats Available
TabSeparated and its variants, CSV, JSON, JSONCompact, JSONEachRow, Native and RowBinary, 17 names in all, and Arrow IPC over the HTTP API.
Generated rows Available
numbers()andnumbers_mt()produce a series of integers for tests, calendars and gap filling.128-bit arithmetic and 256-bit integers Planned
Arithmetic and aggregates over
Int128andUInt128columns, and theInt256andUInt256types, are planned.
Getting data in
Rows reach muscles over HTTP, from Kafka, from Prometheus or from a small agent next to the source. A write is acknowledged after it is synced to disk.
Kafka ingest
muscles reads Confluent Avro topics through a schema registry, creates tables from the schema and acknowledges a record after the write-ahead log is synced. It needs Kafka 4.2 or later. Amazon MSK is supported soon.
An order topic becomes a table with the columns of its Avro schema, and the finance team queries the orders as they arrive.
Prometheus remote write
Prometheus, Grafana Alloy and vmagent push samples to POST /api/v1/write. The first write creates the table, and you read the samples with SQL.
A platform team sends service metrics from Prometheus and joins ninety days of them with a table of deployments to see which release raised latency.
Store-and-forward agent
muscles agent runs next to the data source. It tails log files and the systemd journal, takes pushed writes on a loopback port and keeps batches on disk. It resends a batch until the server acknowledges it, and an insert token stops a resend from storing anything twice.
A depot server tails the log of its scanner gateway. When the uplink drops for an hour, the agent keeps the batches on disk and sends them in order when the link returns.
Inserts with safe retries
INSERT ... VALUES and INSERT ... FORMAT accept JSONEachRow, CSV, TabSeparated, RowBinary and Native. A column you leave out takes its default. Each table remembers the last 1000 insert tokens, so a retried batch is acknowledged and stored once, also after a restart.
A gateway posts JSON lines every second. When a batch fails, it sends the same batch with the same token, and the table gains no duplicates.
Duplicate-safe Kafka tables Available
KAFKA DEDUPkeeps one row per key when Kafka redelivers a record, and the offsets are stored with the rows when you ask.Schema evolution policy Available
A table created from an Avro schema follows an
evolveorstrictpolicy when the schema changes, andsystem.schema_historylists the versions.Quarantine for bad records Available
A record that cannot be stored goes to
ingest_quarantine, and an operator can skip one record by name.Kafka operations Available
Administrators can pause, resume and reset a topic over the API, and drain a node before a restart. Lag metrics show how far ingest is behind.
Agent sources Available
The agent reads plain, rotated and gzip files in order across rotations and the journal with a cursor, and its loopback port takes
INSERT ... FORMAT JSONEachRowand Prometheus remote write.Agent enrichment Available
Stages in the agent add a geo lookup from a CSV, a prefix, a cut, a regular-expression flag or a label before the batch leaves the machine.
Kafka topics to Iceberg Available
muscles dumpwrites the records of a Kafka topic to an Iceberg table on S3.Microcontroller buffering Planned
A small library for the ESP32 is planned to keep compressed readings in flash and upload them when the network returns. The server side exists:
POST /api/v1/edge/ingesttakes a checksummed device batch and stores a resent batch once.Kafka setup in the console Planned
The console is planned to let you add a cluster once, see its status on a card, pick a topic from a list and get a suggested number of consumer threads.
Data that lives elsewhere
You do not have to store everything in muscles. It reads other systems and lake files in place, joins them with your tables, and it can move old data to S3.
Tables that live elsewhere
CREATE EXTERNAL TABLE declares a table in another system. A SELECT reads it in place, and it joins other external tables and your stored tables with every join kind, ASOF included.
Available: Iceberg, PostgreSQL, MySQL, MariaDB, ClickHouse, Redis, Elasticsearch, Snowflake, Google Sheets.
Planned: Prometheus, Apache Solr, MongoDB, Vertica, kdb+, Cassandra, BigQuery, Databricks, Microsoft SQL Server, Oracle, Delta Lake, Apache Hive, Apache Druid, Apache Pinot, Redshift, StarRocks, InfluxDB 2, InfluxDB 3, QuestDB, QuasarDB, TDengine, Amazon Timestream.
An analyst at an online shop joins the orders in its Iceberg datalake with the customer table in PostgreSQL, from the same SQL console and without an export.
Cold tier on S3
Parts older than an age you set move to S3 and stay queryable. A cold read fetches only the columns and granules the query needs.
Ninety days of shipment events stay on local disks, and older parts move to a bucket.
Secrets stay out of SQL Available
An external table names an environment variable for its password, so the statement and the query log never carry the secret.
Import from S3 and local files Available
IMPORT PARQUETandIMPORT ICEBERGload files from S3 or a local directory into a table in one crash-safe statement.Parquet reader Available
Parquet files with plain, dictionary, gzip, zstd and snappy pages, NULLs, decimals and lists of numbers or strings are read.
Iceberg tables Available
Any Iceberg table can be read, with deflate, snappy and zstandard manifests and delete files.
Parquet export Available
SELECT ... INTO OUTFILE '...' FORMAT Parquetwrites a result to a Parquet file in a directory that the operator allows.Several disks Available
A storage policy spreads parts over named disks and volumes, and a disk stops receiving new parts when it is nearly full.
AWS Glue catalog Planned
Reading Iceberg tables through an AWS Glue catalog is planned.
Search, vectors and language models
Text search, vector search and calls to a language model run inside SQL.
Full-text search
CREATE INDEX ... TYPE fulltext indexes a string column by words. With min_gram and max_gram it also holds fragments of words, so LIKE '%fund%' can use it. hasToken finds rows by whole words and bm25Score ranks them.
Help articles are ranked by how well they match the words of a support ticket.
Embeddings and vector search
Store embeddings as float arrays and rank rows with L2Distance or cosineDistance. Search is exact by default, and a TYPE vector index is available for speed.
The ten help articles closest to a customer's question, by the distance of their embeddings.
Language model functions
llmClassify, llmSummarize and llmEmbed call a language model endpoint that you configure on your own network. Only administrators can use them, and the server caches results and applies limits.
Incoming support tickets are labelled refund, delivery or fault with one query.
Tokenizers and ranking settings Available
A text index can use the default tokenizer, n-grams or a custom separator, and the settings
bm25_k1andbm25_btune the ranking.Vector distance functions Available
l1_distance,l2_distance,linf_distance,cosine_distance,dot_product,normalize_l2and the norms work on float arrays.Approximate vector index Available
The
vector_search_approximatesetting lets an IVF index answer a search faster, andsearch_nprobetrades recall for speed.
Security and compliance
Who can see what, who changed what, and how to erase data.
Column policies and masking
CREATE POLICY refuses, hides or hashes a column, filters rows with a predicate or embargoes recent rows, for a role or a user, per column, table or schema. One statement can keep a role out of a whole database.
Support staff query the customers table. The email column reads as a hash, and mrr, the monthly recurring revenue, is refused.
Tamper-evident audit log
The opt-in audit log records who ran what. Its blocks are hash-chained, and SYSTEM VERIFY AUDIT reports the first block that does not match.
An auditor asks for proof that the log of data access was not edited, and the check returns the chain as intact.
Policies follow views Available
A view or rollup built from a refused column is refused too, at any depth, and
UPDATEandDELETEgo through the same read policies.Masking functions Available
mask_hash,mask_partial,mask_redact,mask_nullhide parts of a value in a query.Row deletion for GDPR requests Available
DELETE FROM ... WHEREmakes rows unreadable when it returns, and the next merge removes them from disk. Only administrators can run it, so an erasure request deletes every row that carries the customer id.Compliance certificates Planned
Certificates such as SOC 2 and ISO 27001.
Audit blocks on write-once storage Available
The audit directory can sit on a write-once volume, and an anchor of the chain tip detects a shortened log.
Single sign-on Available
Users sign in with an OpenID Connect provider, so staff use the company identity provider and support reads the tables without write access. An allow list limits who can sign in, and the identity claim is configurable.
Password login and login throttling Available
A users file holds Argon2id hashes,
muscles hash-passwordcreates a line, and repeated failed logins are throttled for the address and for the user.Login behind an authenticating proxy Available
muscles can trust the user name that an oauth2-proxy in front of it sends, or listen on a Unix socket so that only the proxy reaches it.
Roles and capabilities Available
Administrators hold every capability, viewers read only, and each privileged action such as DDL, import, flush, rule creation and row deletion checks its own capability.
Query history that respects owners Available
system.query_logand query profiles show a viewer only their own statements, and administrators see all of them.Secrets redacted from logs Available
Literals in connection statements are masked in the query log and the audit log.
Per-user quotas Available
Quotas limit what one user can run, and
system.quotasandsystem.quota_usageshow the limits and the live counters.Browser and network guards Available
The HTTP interface refuses cross-site browser requests and requests with a foreign Host header, signs node-to-node requests, and can require a token for
/metrics.Sessions and tokens Available
Tokens expire, a session refreshes only while it is young, and a refresh checks the user and role again.
Protection from slow and flooding clients Available
The server bounds the time to read a request, limits connections per address before sign-in, and disconnects readers that stall.
Typed error codes Available
Error bodies carry a code such as
not_foundorreplica_read_only, and the ClickHouse interface returns ClickHouse numeric codes.
Durability, storage and upgrades
What happens to your data when the disk, the process or the version changes.
Upgrades keep your data
A new release reads the stored formats of earlier beta releases, and muscles migrate copies a running deployment into a new server, checks each table by digest, follows new writes and cuts over.
A depot database moves to a new server while the scanners keep sending.
Replication
Replication ships parts through S3 and a Kafka commit log to a replica, together with table definitions. It is off by default, and an operator promotes a replica by hand.
A replica in a second site serves reports. If the primary fails, an operator promotes the replica.
Durable writes Available
Each table has a write-ahead log with CRC32C frames. A write is acknowledged after its fsync, and a failed fsync fails the write.
Immutable compressed parts Available
Memtables flush to immutable parts with checksums, and background merges keep the part count low.
Recovery from a damaged log Available
Boot repairs a torn log tail on its own. An operator can choose to salvage the records before a corrupt frame, and the salvaged rows stay replayable until a part covers them.
Snapshots and restore Available
/admin/snapshotwrites a consistent copy of a node to a directory, andmuscles restorechecks every file against its checksum before it puts the copy in place, so you can take a snapshot before a risky change and restore it on a spare node.Format label on every image Available
Each release image carries a label with a digest of the stored formats, and
muscles formats --jsonprints the same digest. Equal labels mean the data directory survives the upgrade, and the operator reads them before it rolls an upgrade.Retention with TTL Available
CREATE TABLE ... TTL ts + INTERVAL 90 DAYdeletes parts whose newest row is older than the interval, once the operator turns the sweeper on, so raw meter readings can go after the rollups cover their range.Schema changes replicate Available
Table creation, drops and column changes travel to replicas in a signed schema snapshot, and tables made by
IMPORTreplicate too.Replicas catch up by themselves Available
A replica that was offline downloads what it missed when it starts, so it needs no manual resync.
Flush and merge control Available
flush_max_rowsandflush_interval_msset when a memtable becomes a part, and an administrator can flush a table on demand.Versioned stored formats Available
Every stored and wire format starts with a magic and a version, and a reader rejects an unknown version.
Running it
Single node first, then query, ingest and data nodes, replicas and Kubernetes.
Query, ingest and data nodes
A node runs as all, query, data or ingest. Query nodes send a query to the shard nodes and merge the partial results.
Ingest nodes absorb a flash-sale spike while analysts query from nodes of their own.
Distributed queries Available
Aggregates, joins, windows,
DISTINCT, totals and decimal sums run across shards and return the answer a single node would give.Kubernetes Available
Tagged container images, a Helm chart and an operator. The chart runs one StatefulSet per shard.
Operator resources Available
The operator manages an ingest cluster with an autoscaler and users through custom resources, and a pause annotation stops reconciliation at a safe point.
systemd units Available
Hardened systemd unit templates ship for the server and the agent.
Ingest before queries Available
Ingest and DDL take the CPU before heavy queries. The session setting
query_priorityacceptshigh,normalandlow, so a long report runs at low priority while sensor writes keep their place.Query limits Available
The operator can cap the run time, the rows read, the rows returned, the memory of one query and of all queries, and the number of concurrent queries.
Spill to disk Available
Large
GROUP BYandORDER BYsteps write spill files instead of failing, within a disk budget.One memory budget Available
Queries, merges and view refreshes draw on one budget, and work that does not fit waits or lags instead of ending in an out-of-memory crash.
Result row cap Available
A result above
max_query_rowsfails with a typed error, or withresult_overflow_mode = 'break'returns the first rows and marks the result as truncated.Configuration Available
Every setting is an environment variable or a YAML key, and the configuration reference lists them.
Background work on its own tier Planned
Merges and view refresh are planned to run on a worker, so a large rollup rebuild cannot slow ingest.
Query nodes behind a load balancer Planned
Any query node is planned to serve progress, profile and stream requests for a query that another node ran, so a reporting portal can spread its queries over several small query nodes. An asynchronous query API is planned after it.
Config reload from a mounted file Planned
A ConfigMap file is planned to reload without a restart. A bad file keeps the last valid configuration and raises a metric; a bad file at start still stops the node.
Connect your tools
Dashboards, notebooks and drivers reach muscles over HTTP.
ClickHouse HTTP interface
ClickHouse drivers connect to the HTTP interface, and muscles accepts a subset of ClickHouse SQL. The interface takes the user from headers or basic auth, and reads readonly, database and query settings from the URL.
A team points its Grafana ClickHouse data source at muscles over HTTP and ports its dashboards one at a time.
Python and Polars
scan_muscles reads a table as a lazy frame and pushes column selection, filters and limits to the server. write_polars writes a frame in chunks with a token per chunk, and follow yields new rows as batches.
A notebook pulls only the needed columns of a tick table and writes the cleaned frame back.
ClickHouse drivers Available
Connect with
clickhouse-connectfor Python,clickhouse-jdbc,clickhouse-goor the ClickHouse data source of Grafana.Grafana Available
A data source plugin, ready dashboards and alert rules. The plugin signs in with a user name and password and renews its token when it expires.
JDBC and JetBrains tools Available
A JDBC driver lets DataGrip, the IntelliJ database tools and DBeaver run queries and browse the schema.
Trino connector Available
Trino reads muscles tables through a connector that pushes down columns, limits and simple filters, so a Trino query can join a muscles click table with a warehouse table.
Client libraries Available
Clients for Go, Python, Java, Rust and C++ send SQL over HTTP. You get them with your onboarding.
JSON, streaming and Arrow Available
POST /api/queryreturns columnar JSON,/api/query/streamstreams a result, and/api/query.arrowreturns an Arrow IPC stream.Terminal client Available
muscles cliruns statements interactively or with--execand prints a table, CSV or JSON lines.Compressed responses Available
The ClickHouse interface compresses responses with gzip, deflate or lz4 when the client asks for it, and accepts compressed insert bodies, so a laptop on a metered link downloads a day of readings as gzip.
Grafana Live Planned
Panels are planned to update as rows arrive instead of polling, so a line-side screen shows rejects per minute as they happen.
Polars streaming Planned
Reading with
collect(engine="streaming")batch by batch, and sinking a lazy frame straight into a table, are planned, so a year of sensor data can be processed on a laptop without loading it all.
Tracing, console and documentation
Traces, metrics, the console and the reference pages.
Tracing
muscles exports traces for queries, flushes, merges and boot over OTLP, to Jaeger or any OTLP/HTTP collector. A query trace nests the parse, plan, scan and aggregate steps.
See how long a slow dashboard query took, and whether a flush or a merge ran at the same time.
Metrics and health probes Available
/metricsexports 278 Prometheus metrics, and/health,/readyand/startupzserve probes.System tables Available
Tables such as
system.parts,system.columns,system.query_log,system.rollups,system.alertsandsystem.policiesshow what the server holds and has run.Part, trace and profile logs Available
system.part_log,system.trace_logand the processor profile log are tables, so you can query how flushes, merges and queries behaved.Web console Available
A SQL editor, a catalog browser, query profiles, ingestion status and a Queries page that filters by statement kind, user and final state, so an on-call engineer can list the failed queries from a phone.
Query history and a plan for every query Available
The server keeps a durable query history and a profile for each query, and the console draws its stage graph with time, rows and bytes per stage and live progress while it runs, so you can see which stage of a funnel query reads the most bytes.
Pipeline graph Available
The console draws the path from Kafka topics through tables, views and rollups.
Map-key completion Available
The SQL editor suggests the keys that exist in a map column when you type
tags['.Opt-in usage counts Available
The console can count which of its buttons you use. The counts are off by default and stay in your browser.
Optional AI assistant Available
The console can offer an assistant that writes SQL from a question, when the operator turns it on.
Reference pages generated from the code Available
Every SQL function, type, setting, environment variable, metric, error code and format has a reference page generated from the code.
Force a trace for one query Planned
A URL parameter, a
traceparentheader and a setting in the query are planned to force a trace of one slow panel query, also from the Grafana data source.Traces stored in muscles Planned
A separate muscles deployment is planned to store traces and serve them to Jaeger or Grafana, so one database holds the logs, the metrics and the traces.
Want to try this on your own data? The first 30 days are free. See how the private beta works or write to hello@muscles.dev.