meldra

Telemetry you can prove.

A utility can prove a reading was authentic at the meter, and separately that a warehouse row hasn't changed. Nothing joins the two. meldra verifies telemetry at the ingestion boundary and writes the proof into the lakehouse, so an answer arrives with its evidence attached.

Example response GET /v1/query/submit

Settled consumption, feeder F‑4471, period 2026‑08‑01 to 2026‑08‑31

4,182,904kWh

Iceberg snapshot
7742901883364117205
Contributing rows
1,428,096 — all verified at ingest
Merkle root
a41f…9c02, anchored RFC 3161
Status
Reproducible. Re-run returns the same figure.

The gap is between the meter and the record

Encryption and authentication at the meter are solved problems — IEC 62351 and DLMS handle them. What isn't solved is integrity that survives into the data lake, and what you can hand a third party months later.

When Ofgem or a settlement counterparty challenges a figure today, substantiating it means pulling source readings, matching them to the aggregate and writing a narrative. That's days of senior analyst time, and what it produces is an argument rather than a proof.

meldra changes what you hand over. Every answer carries the exact data snapshot it was computed from and a verification that the contributing readings were checked at the gateway and unaltered since. Your counterparty re-runs it and gets the same number. The dispute ends in arithmetic instead of negotiation.

Two things happen at the wire

Ingress routes derive from a shared secret and a 60-second epoch window, with three windows valid at once to tolerate clock drift. There is no fixed endpoint to scan for.

Valid traffic is verified and recorded

Each block carries a hardware monotonic nonce and an ECDSA P‑256 signature. The gateway performs an atomic nonce compare-and-swap, recomputes the hash and verifies the signature before the reading is written. Verification state becomes a first-class column in Iceberg, not a log line. A broken chain link is flagged CHAIN_GAP rather than silently dropped, because a missing reading is evidence.

Invalid traffic is diverted, not blocked

Existing AMI standards respond to detected reconnaissance by blocking, which tells the attacker they've been seen. They rotate address and try again; you learn nothing. meldra sends an invalid or stale route to an isolated decoy that returns plausible synthetic telemetry, and flags the source. The attacker keeps probing a system that isn't real.

Every number here was measured

Benchmarked against a specific commit, single thread, on commodity hardware. The conditions column is part of the claim.
OperationMeasuredConditions
Verified ingest 0.108 ms/block 1,000 blocks, ECDSA P‑256 + SHA‑256 + nonce compare-and-swap
Throughput 9,254 blocks/sec Single thread
Route validation 0.007 ms HMAC‑SHA256, constant-time compare — 142,052/sec
Diversion to decoy 0.020 ms Invalid route path — 50,295/sec
Headroom, 3M-meter estate 5.4× Against roughly 1,700 blocks/sec sustained

Where 1,700 comes from: 3,000,000 meters × 48 half-hourly readings ÷ 86,400 seconds = 1,667 blocks per second sustained. We're happy to show the arithmetic.

What we can't claim yet

These are unmeasured or unfinished. We publish them because you'd find them anyway, and because a vendor claiming a clean history isn't one you should believe.

  • Detection accuracy and false-positive rate

    Not measured. Neither is attacker containment duration. We won't put a number on any of them until we've run it.

  • Multi-thread and multi-gateway throughput

    Every figure above is single-thread. Horizontal scaling is designed but not benchmarked.

  • Nothing has run against real meters

    All measurements come from a meter simulator producing signed blocks. No production AMI estate has been through this.

  • Scan pushdown needs explicit filters

    SQL WHERE predicates aren't automatically translated into Iceberg expressions yet, so callers who need file pruning must populate filters themselves.

  • The fast scan path is conditional

    The zero-materialisation Arrow path only engages when no access-control policy applies to the query. With masking in force, the data is materialised.

  • Two defects we found in our own gateway

    One was an availability bug: the nonce counter advanced before signature verification, so a single unsigned packet could permanently lock out a meter. We exploit-tested it, fixed it and pinned it with regression tests. The write-up is public.

Your storage, your data, your exit

Tables are Apache Iceberg on your own object storage. Spark, Trino, DuckDB and Dremio can read every byte with us entirely out of the picture. If meldra disappears tomorrow, your data is untouched and readable.

Access control is enforced below the query engine. Masking is applied to the Arrow data before the relation is registered with DuckDB, so column aliasing, subqueries, CTEs and SELECT * cannot recover a masked value — the value was never in the relation the engine saw. That's a stronger property than rewriting SQL, which creative queries defeat.

The catalogue maps to the IEC Common Information Model: 61970‑301 for the base model, 61968 for distribution including part 9 for meter reading. A CIM RDF export is implemented and tested. CIM has no way to express provenance — no standard class for "this reading was verified at ingest, here's the proof, here's the anchor." That hole in the standard is where our work sits.

Come and break it

The most useful sixty seconds we can spend with you: two terminals, no slides. Meters posting signed readings. The route rotates and the meters follow it. A scanner hits the old route, receives a plausible response, and never learns it's talking to a decoy. Then we change one byte in a stored reading, run the verifier, and it names the block.

Read the specification

Welcome back

Sign in to access your data lakehouse

Create account

Your data lake, powered by AI

Already have an account? Sign in

Check your email

We've sent a 6-digit code to

your@email.com
Code expires in 10:00

Forgot password?

Enter your email and we'll send a reset code.

Enter reset code

We sent a 6-digit code to

your@email.com
Code expires in 10:00

Set new password

Choose a strong password for your account.

Create Iceberg Table

Select your preferred method to register a new Apache Iceberg table in the catalog namespace.

Ingest via CSV Upload (Recommended)

Upload your dataset file, customize headers/schema formats, and commit files directly to your S3 bucket.

Create via SQL Prompt (DDL)

Open the interactive console and execute a standard CREATE TABLE SQL script to initialize table structures.

Account Settings

User Information

Email Address operator@utility.grid.ai
Subscription Tier Trial
Status Active
Member Since -

Change Password

Preferences

Controls number and date formatting across the app (e.g. 1,000.50 vs 1.000,50). Full interface translation is on the roadmap.

API Access

Generate a long-lived token to connect external tools — including the real MCP (Model Context Protocol) server in backend/mcp_server.py — to your account. Shown once; store it somewhere safe.

Data Lake Connection

Connect your S3 lake
Demo mode — toggle to connect your own S3 warehouse.

Quick Prompts

Article Reader

Video