GTSDB
Golang Time Series DataBase

TimeSeries DataBase that is

GTSDB Illustration

Key features

Blazing Fast

96M ops/sec multi-key read. 1.22M ops/sec batch write. Binary protocol + Velox JSON.

Memory Efficient

As low as 6 MB memory. Perfect for IoT edge devices.

Simple API

Identical HTTP + TCP interfaces, all in strict JSON.

Gorilla Compression

29.6x smaller than JSON. Massive disk savings.

Built-in Streaming

Subscribe to keys, receive updates in real-time.

Battle-Tested

Production use by IoT pioneers. Full code coverage.

Batch Write

Up to 10,000 points per call. Bulk imports.

Advanced Analytics

Downsampling: avg, sum, min, max, p50, p95, p99.

Monitoring Ready

Built-in /health and /metrics (Prometheus) endpoints.

Why is GTSDB so efficient?

A deep dive into the architecture that makes GTSDB fast, small, and durable.

Most databases separate their write path and read path with layers of abstraction - a write-ahead log (WAL) for durability, a buffer pool for caching, and separate index structures for querying. Each layer adds latency and memory overhead. GTSDB takes a fundamentally different approach: the WAL is the database.

Instead of maintaining a separate buffer pool and periodically flushing pages to disk, GTSDB appends every write directly to a per-key append-only file. There is no double-writing - data goes straight from the network socket to the WAL and into a ring buffer cache. This eliminates the memory amplification that comes from maintaining both a write buffer and a read cache. The ring buffer, configured per-key with up to 10,000 slots, serves recent reads directly from memory without any disk access. For a typical IoT workload where the latest readings matter most, virtually every read hits the cache.

But the real performance breakthrough is in how GTSDB handles the read path. Traditional databases serialize query results into verbose JSON, with each data point carrying repeated field names like "timestamp" and "value". At 5,000 points per query, this adds up to hundreds of kilobytes of redundant text. GTSDB introduces an optional binary protocol: each data point becomes a fixed 16-byte record - an 8-byte timestamp followed by an 8-byte IEEE 754 float. No parsing, no field name repetition, no reflection-based serialization overhead. The server writes raw bytes straight to the TCP socket; the client reads them back with zero allocation. On a multi-key read of 25,000 points, this alone takes the response time from 7 milliseconds down to 260 microseconds.

The JSON path is no slouch either. GTSDB uses Velox, a Go JSON library backed by a native C VM, which outperforms the standard library by an order of magnitude and even beats SIMD-based alternatives like Sonic. For writes and non-bulk reads where JSON remains the default, Velox handles marshaling in nanoseconds per operation.

Under the hood, a dirty-key async flusher ensures that only modified keys trigger disk syncs, avoiding the blanket fsync storms that plague append-only databases. When data does go to disk, Facebook's Gorilla time-series compression reduces storage by nearly 30x compared to raw JSON, making disk space a non-issue even on constrained edge devices.

The architecture scales down as well as it scales up. At idle, GTSDB uses about 6 MB of memory - less than a single browser tab. It ships as a single statically-linked binary with no external dependencies. Deploy it on a Raspberry Pi, a cloud VM, or a Windows server; the behavior is identical. This is what makes GTSDB uniquely suited for IoT: it does not ask you to choose between durability, speed, and footprint. It gives you all three.

Why not Rust?

A pragmatic look at language choice given GTSDB's architecture.

Let's address the elephant in the room. Rust has become the darling of systems programming in the AI era—rewritten tools like uv,ruff, polars, and tokenizers dominate headlines, and every week a new database or framework announces a Rust rewrite promising 10x speed. The hype is real, and for many projects the praise is well-earned.

So why did GTSDB choose Go? Rust's safety guarantees are genuinely valuable—but they come with a cost, and not every architecture needs them equally. GTSDB's design makes Go the better fit for several reasons.

1. Minimal GC pressure

GTSDB's WAL-first architecture deliberately avoids heap churn. Data flows from the network socket into a pre-allocated ring buffer (fixed-size, one per key) and gets appended straight to a file. There are no complex object graphs, no reference cycles, no generational heap promotions—just a simple, predictable data path. The Go garbage collector has almost nothing to do. At idle, the process sits at ~6 MB with zero GC cycles firing. Rust's ownership model solves a problem that barely exists here.

2. Goroutines map directly to the problem

GTSDB runs two concurrent servers (HTTP + TCP), a pub/sub fanout system, and an async dirty-key flusher. All of these are textbook goroutine + channel patterns. Go's runtime multiplexes them onto OS threads with GOMAXPROCS; the developer just writes straight-line code. Rust's async model requires picking an executor (tokio, smol, async-std), annotating lifetimes through async boundaries, and managingSend + Sync bounds across every.await point. For an architecture that is fundamentally a linear pipeline (read → cache → write), the extra ceremony buys nothing.

3. Code review matters

This is the practical one. GTSDB is a focused project—its hot paths are short and simple. A Go PR is typically a few dozen lines around a well-understood mutex or channel. The same logic in Rust would require reviewing lifetime annotations, unsafeblocks (especially around the Velox C FFI), Send/Synctrait implementations, and the interaction between borrows and cancellation. Every review cycle becomes slower, and for a small team, developer velocity is a real bottleneck. Go lets the team ship and iterate faster without sacrificing correctness—the race detector catches the same class of bugs the borrow checker would, at a fraction of the cognitive cost.

4. C interop, done differently (Velox)

GTSDB uses Velox, a Go JSON library with a native C VM for its marshal hot path. Notably, Velox does not use cgo—the C code is pre-compiled into .sysoobjects and linked via Plan9 assembly trampolines that bridge Go ABI to C ABI directly on the goroutine stack. The result: native C speed without the cgo build penalty (noCGO_ENABLED=1, no cross-compilation headaches, no fork-exec for the C compiler during build).

This is possible because Go's linker can ingest arbitrary .sysofiles and resolve assembly-level symbols—a unique sweet spot in Go's toolchain that Rust's rigid separation between unsafeand safe code would make far more cumbersome to replicate. Rust's FFI requiresextern "C" blocks,#[no_mangle] annotations, andunsafe wrappers around every C call—and cross-compiling the C portion demands a C toolchain per target anyway. Velox's approach ships the C artifacts pre-built, so consumers just run go buildwith zero C tooling required.

The bottom line

Rust is an excellent choice for systems with complex shared state, strict latency requirements, or safety-critical certification. GTSDB is none of those things. It is a focused, WAL-first timeseries database where the hot path is a straight line from socket to ring buffer to file. Go gives you enough safety (the race detector), better concurrency primitives (goroutines and channels), and faster iteration (one-binary deploy, instant cross-compilation, simpler reviews). Choosing Go over Rust for this architecture is not a compromise—it is the correct engineering tradeoff.

Usages

Identical JSON payload - choose your transport. Toggle between HTTP and TCP to see how the same body is sent.

POST/
1{
2    "operation": "write",
3    "key": "a_sensor1",
4    "write": {
5        "value": 32242424243333333333.3333,
6        "timestamp": 1717965210
7    }
8}

Need more details? Check out our complete API documentation.

View Full API Documentation

Client Drivers

First-class Go & Node.js clients with JSON and binary protocol support

Gov0.1.0
main.go
installbash
go get github.com/abbychau/gtsdb-drivers/go@latest
examplego
1import "github.com/abbychau/gtsdb-drivers/go"
2
3client, _ := gtsdb.Connect("localhost:5555")
4client.Auth("your-token")
5
6// JSON
7client.Write("sensor1", 42.5)
8pts, _ := client.ReadLast("sensor1", 100)
9
10// 🚀 Binary - 100x faster
11pts, _ := client.ReadBinary("sensor1", 5000)
12multi, _ := client.MultiReadBinary(
13    []string{"s1","s2"}, 5000,
14)
Node.jsv0.1.0
index.js
installbash
npm install github:abbychau/gtsdb-drivers
examplejavascript
1const { GTSDBClient } = require('gtsdb-drivers')
2const c = new GTSDBClient('localhost', 5555)
3await c.connect()
4await c.auth('your-token')
5
6// JSON
7await c.write('sensor1', 42.5)
8const pts = await c.readLast('sensor1', 100)
9
10// 🚀 Binary - 100x faster
11const pts = await c.readBinary('sensor1', 5000)
12const multi = await c.multiReadBinary(
13  ['s1','s2'], 5000
14)

Performance Comparison

Benchmarked against VictoriaMetrics v1.147, InfluxDB v2.9, and NSQ v1.3 on Windows / i7-13700KF / 5,000 points per operation. Reads use binary protocol.

Write Benchmarks

Write (seq) - 5,000 pts

Batch Write - 5,000 pts

Pipeline Write - 5,000 pts

Multi-Sensor Write - 5 keys × 1,000 pts

Read Benchmarks

Single Read - Last 1 Point

Multi-Key Read - 5 Keys × 5,000 pts

Pub/Sub Delivery Latency (s)

Storage per 5,000 points (KB)

Resource Usage

CPU Time (s)

Memory (MB)

Disk (KB)

Benchmark Report Charts

Radar Chart
Click to enlarge

Performance Radar

Ops/Sec
Click to enlarge

Throughput (ops/sec)

Resource Usage
Click to enlarge

Resource Usage

Write Latency
Click to enlarge

Write Latency

Batch Write
Click to enlarge

Batch Write Comparison

Pipeline Write
Click to enlarge

Pipeline Write

Read Comparison
Click to enlarge

Read Comparison

Multi Write
Click to enlarge

Multi-Sensor Write

Performance Highlights

FeatureDetail
JSON EngineVelox native C VM + binary protocol for reads
Binary Protocol16 bytes/point, zero-alloc encode/decode
Multi-Key Read6,926,359 ops/sec (faster than VictoriaMetrics)
Pub/Sub Latency110.94 ms delivery
Batch Write2,183,177 ops/sec
Multi-Write2,107,641 ops/sec
Compression29.6x smaller than raw JSON (Gorilla)
Memory (idle)~12 MB
DeploymentSingle binary executable — no dependencies

Test Configuration

SettingValue
Points per Operation5,000
Sensors (multi-write)5
Runs per Benchmark3
Warmup Iterations300
GTSDB JSON LibraryVelox (native C VM backend)
GTSDB Cache Size10,000 ring buffer / key
Sync Modeasync (dirty-key flusher)
(p.s. sync mode also available, and our clients love it :p)
OSWindows
Architectureamd64
CPUCore(TM) i7-13700KF

vs InfluxDB

OperationGTSDBInfluxDBResult
Sequential write90.97 ms1474.15 ms16.21x
Pipeline write29.4 ms270.71 ms9.21x
Batch write2.29 ms10.52 ms4.59x
Multi-sensor write2.37 ms8.46 ms3.56x
Single read<0.19 ms8.35 ms44.27x
Multi-key read0.72 ms13.09 ms18.13x

vs VictoriaMetrics

OperationGTSDBVictoriaMetricsResult
Sequential write90.97 ms156.98 ms1.73x
Pipeline write29.4 ms35.19 ms1.2x
Single read0.19 ms0.08 ms2.27x faster
Multi-key read0.72 ms0.2 ms3.55x faster
Batch write2.29 ms0.93 msVM leads 2.46x
Multi-write2.37 ms0.62 msVM leads 3.84x

Admin Tool

A modern web-based administration interface for managing your GTSDB instance.

GTSDB Admin Interface
Click to enlarge

The GTSDB Admin is a feature-rich web dashboard that provides complete visual control over your GTSDB instance — from key management and data read/write operations to real-time charting and comparison tools. Built with Next.js 14, ECharts, and shadcn/ui, it connects to any running GTSDB server via a BFF proxy pattern, supporting HTTP, WebSocket, and TCP protocols.

Key capabilities include tabbed multi-key workflows with hierarchical sidebar grouping, embeddable charts for external dashboards, a built-in data generator for test data, server information monitoring with live polling, and per-key configuration (multipliers, units, offsets) stored in Redis. The comparison tool lets you stack up to three charts side-by-side with session persistence.

View Admin Repository

Trusted By

ControlFreeVertriqeJeju Samdasoo