Skip to content

Finstrm

One API for cryptocurrency market data across centralised and decentralised exchanges — with no database behind it.

SectorFintech
EngagementCustom software
Period2026
Core stackGo 1.23
Numbers
83,873Requests/sec, single-symbol ticker endpoint
< 7msP95 latency on every endpoint
64nsPer trade append — zero allocations
0External dependencies at runtime

Conditions: Measured on an Apple M1 Pro, Go 1.23, GOMAXPROCS=8, against a loopback TCP server with 50 concurrent keep-alive connections over a 10-second window, store pre-seeded with 10 symbols across 2 exchanges. These are loopback figures, not production-over-the-internet figures — they measure the software, not the network in front of it.

The problem

Anyone building on crypto market data has to integrate each exchange separately. Different protocols, different symbol formats, different rate limits, different failure modes — and the moment you add a decentralised exchange, none of the assumptions hold.

The usual answer is to write a pile of connectors, dump everything into a time-series database, and query that. It works, but it puts a database between you and data that is only interesting while it is fresh, and it turns a read into a network round trip plus a disk seek.

The brief was a single API — one symbol format, one response shape, one connection — fast enough that consumers could treat it as a local lookup rather than a remote call.

What we built

Finstrm holds all state in process. There is no database, no cache layer and no external service dependency. Feeds land in per-exchange goroutines, fan into a worker pool sized to the machine, and update a store built for lock-free reads. A broker fans the same events out over WebSocket.

The binary is stateless across restarts — market data rebuilds itself from live feeds on startup, which means deployment is copying one file and running it.

Decisions

No database

Market data is only valuable while it is current, and the working set fits comfortably in memory — under 512 MB for 500 symbols across three exchanges. Adding Postgres or a time-series store would have bought durability nobody wanted and cost a round trip on every read. Dropping it removed an entire class of operational work: no migrations, no connection pools, no backups, no failover.

Go, and only Go

Thousands of concurrent inbound events across a dozen feeds is precisely what goroutines and channels are for. The whole system builds with go build and no other toolchain — which matters more than it sounds, because the thing that runs in production is one static binary with no runtime to install.

One symbol format

Every exchange names pairs differently. Normalising to BASE/QUOTE at the connector boundary means consumers write the integration once. Adding a fourth exchange is a connector satisfying an interface — no changes anywhere else in the system.

Result

The original target was 1,000 requests a second. The slowest endpoint does 23,500.

Stack
  • Go 1.23
  • WebSocket
  • The Graph
  • Docker
  • Prometheus

Tell us what needs to exist.

Send a couple of paragraphs about the problem. We will come back with what it would take to build — scope, timeline and cost — or tell you honestly if we are not the right fit.

Next case studyCommand CentreSaaS · 2026 — ongoing →