Skip to content
Projects

pkvartsianyi/spatio has 54 GitHub stars and 5 forks. GitHot measured 0 stars in 24 hours. Last checked 2026-11-15 05:53 UTC. Last push 2026-11-04.

How these counts are measured

What you can do

  • Spatial Queries: Radius search, 2D/3D Bounding box, K-Nearest Neighbors (KNN), Cylindrical queries.
  • Object-Centric API: Query around moving objects directly without manual coordinate lookups.
  • Trajectories: Optimized storage and querying of historical movement paths over time.
  • Durable Persistence: CRC-checked append-only trajectory log with configurable sync policy and checkpoint recovery.

Measured star growth

in 24h
0
in 7 days
Collecting history
in 15 days
Collecting history
in 1 month
Collecting history

Net star changes over overlapping periods, not daily totals. Missing measurements are left blank. Stars measure attention, not software quality.

About

An embedded spatial database designed for applications that need to store and query location-based data efficiently.

Data

README.md

Original

Spatio Logo

Spatio

License: MIT Crates.io PyPI npm Documentation Rust Docs

Spatio is a high-performance, embedded spatio-temporal database written in Rust. It's designed for real-time tracking of moving objects, with hot/cold state separation, durable persistence, and native Python, TypeScript and Go bindings.

Website · API docs · llms.txt

Quick Start

Python

pip install spatio
import spatio

# Open or create a database
db = spatio.Spatio.memory()

# Upsert an object's location (longitude, latitude)
nyc = spatio.Point(-74.0060, 40.7128)
db.upsert("cities", "nyc", nyc, {"population": 8000000})

# Find objects nearby
nearby = db.query_radius("cities", nyc, 100000, limit=10)
# Returns: [(object_id, point, metadata, distance), ...]

TypeScript

npm install spatio-db
import { Point, Spatio } from 'spatio-db'

// Open or create a database
const db = Spatio.memory()

// Upsert an object's location (longitude, latitude)
const nyc = new Point(-74.006, 40.7128)
db.upsert('cities', 'nyc', nyc, { population: 8000000 })

// Find objects nearby
const nearby = db.queryRadius('cities', nyc, 100000, 10)
// Returns: [{ objectId, point, metadata, distance }, ...]

Rust

[dependencies]
spatio = "0.4"
serde_json = "1"
use spatio::{prelude::*, Point3d};

fn main() -> Result<()> {
    let db = Spatio::memory()?;

    let nyc = Point3d::new(-74.0060, 40.7128, 0.0);
    db.upsert("cities", "nyc", nyc.clone(), serde_json::json!({}), None)?;

    let nearby = db.query_radius("cities", &nyc, 100_000.0, 10)?;
    println!("Found {} cities", nearby.len());

    Ok(())
}

Architecture: Hot/Cold State

Spatio follows a specialized architecture for tracking moving objects:

  • Hot State: Current locations are kept in-memory using a sharded concurrent DashMap and a high-performance R*-tree spatial index.
  • Cold State: Historical movement (trajectories) is persisted to an append-only log on disk. :memory: databases have no log: they keep the last buffer_capacity updates per object (default 100), and delete removes them.
  • Recovery: At startup, the Hot State is automatically rebuilt by scanning the latest entries in the Trajectory Log.

Features

  • Spatial Queries: Radius search, 2D/3D Bounding box, K-Nearest Neighbors (KNN), Cylindrical queries.
  • Object-Centric API: Query around moving objects directly without manual coordinate lookups.
  • Trajectories: Optimized storage and querying of historical movement paths over time.
  • Durable Persistence: CRC-checked append-only trajectory log with configurable sync policy and checkpoint recovery.
  • Lightweight: No external services, no SQL overhead, and a zero-setup embedded engine.
  • Cross-language: Native high-performance Python bindings via PyO3, and Node.js/TypeScript bindings via napi-rs.
  • Server Mode: Includes an optional lightweight TCP server for remote access.

Use Cases

Spatio fits applications that track things that move and ask where they are now and where they have been:

  • Delivery and logistics fleet tracking
  • Drones and airspace monitoring, using 3D and altitude-band queries
  • Geofencing with polygon queries
  • Nearby search around a moving object

How Spatio Compares

Spatio PostGIS SpatiaLite Redis GEO Tile38
Deployment In-process library, optional server Server In-process library Server Server
Query language Native API SQL SQL Commands Commands
Movement history Built in Model it yourself Model it yourself Model it yourself Model it yourself
Stored geometry Points with metadata Full geometry Full geometry Points Full geometry

Choose PostGIS or SpatiaLite for general GIS work, such as joins, arbitrary geometries and hundreds of spatial functions.

Configuration

Spatio exposes a Config builder for tuning performance and persistence.

use spatio::config::{Config, PersistenceConfig};

let config = Config::default()
    // Updates kept in memory per object: a read cache for file databases,
    // and the entire history of a `:memory:` database
    .with_buffer_capacity(100)
    .with_persistence(PersistenceConfig {
        // Records buffered before the log is flushed to the OS
        buffer_size: 512,
    });

let db = Spatio::open_with_config("path/to/db", config)?;

with_max_buffered_objects caps how many objects keep that history in memory (default 100,000). The log is unaffected.

db.flush() makes every acknowledged write durable. db.compact(keep_since) shrinks the log by dropping older history, keeping the latest update of each live object. Writes wait while it runs, and it needs free disk space for a second copy of what it keeps, so run it before the disk is full.

Timestamps are seconds since the epoch. Writes stamped more than an hour ahead of the clock are rejected. An update older than an object's current one is added to its history without moving it.

Examples

Tracking Moving Objects

// Update location (upsert)
db.upsert("delivery", "truck_001", position, metadata, None)?;

// Find trucks near a warehouse (coordinate-based)
let nearby = db.query_radius("delivery", &warehouse_pos, 5000.0, 10)?;

// Find drones near a specific drone (object-based)
let near_neighbors = db.query_near("drones", "drone_alpha", 500.0, 5)?;

3D Spatial

// Track drones with altitude
let drone_pos = Point3d::new(-74.006, 40.712, 100.0);
db.upsert("drones", "drone_1", drone_pos, json!({}), None)?;

// 3D Bounding box query
let in_airspace = db.query_within_bbox_3d("drones", min_x, min_y, min_z, max_x, max_y, max_z, 100)?;

Historical Trajectories

// Query movement history for a specific vehicle
let start = SystemTime::now() - Duration::from_secs(3600);
let history = db.query_trajectory("logistics", "truck_001", start, SystemTime::now(), 500)?;

API Overview

Real-time Tracking

  • upsert(namespace, object_id, position, metadata, options)
  • get(namespace, object_id)
  • delete(namespace, object_id)

Spatial Queries

  • query_radius(namespace, center, radius, limit)
  • query_bbox(namespace, min_x, min_y, max_x, max_y, limit)
  • query_within_cylinder(namespace, center, min_z, max_z, radius, limit)
  • query_within_bbox_3d(namespace, min_x, min_y, min_z, max_x, max_y, max_z, limit)
  • knn(namespace, center, k)

Object-Relative Queries

  • query_near(namespace, object_id, radius, limit)
  • query_bbox_near_object(namespace, object_id, width, height, limit)
  • query_cylinder_near_object(namespace, object_id, min_z, max_z, radius, limit)
  • query_bbox_3d_near_object(namespace, object_id, width, height, depth, limit)
  • knn_near_object(namespace, object_id, k)

Server Mode

Spatio includes a dedicated server crate (spatio-server) for multi-process or remote access.

# Start the server
cargo run -p spatio-server

Connect using the native Rust client (spatio-client):

use spatio_client::SpatioClient;

let client = SpatioClient::connect("127.0.0.1:3000".parse()?).await?;
let stats = client.stats().await?;

Documentation

License

MIT - see LICENSE