Data processing at scale. Built for geospatial.
Build powerful data pipelines with reusable blocks in any language.
What is Spade?
Spade is a data processing system designed for massive data with first-class geospatial support. It lets you build complex workflows by connecting reusable, isolated computational blocks.
Processing steps are independent blocks that execute in isolation — each one a sandboxed subprocess with typed inputs and outputs. Write them in Python, R, Go, Rust, or TypeScript.
Define your workflows as declarative YAML pipelines. The scheduler resolves dependencies and executes blocks in parallel, handling caching, map/reduce operations, and fault recovery automatically.
Deal Yourself a Winning Hand
Everything you need to build, run, and scale data processing pipelines.
Multi-Language Blocks
Write blocks in Python, R, Go, Rust, or TypeScript. Spade handles the rest.
Declarative Pipelines
Define workflows as YAML. The scheduler resolves dependencies and parallelizes execution.
Geospatial First
Native support for raster, vector, and tabular geospatial data through GDAL integration.
Map/Reduce at Scale
Fan out across collections and reduce results back together, automatically.
Secure by Default
Each block runs in an isolated sandbox with restricted filesystem and network access.
CLI + Web UI
Develop locally with the CLI. Deploy and collaborate through the web interface.
How It Works
Define
Write your processing block as a simple function with typed inputs and outputs.
def handler(src: RasterFile)
-> RasterFile:
result = process(src)
return RasterFile(result)
Compose
Chain blocks into a pipeline using YAML or the visual flowchart editor.
blocks:
- name: reproject
inputs: [source]
- name: analyze
inputs: [reproject]
Execute
The scheduler handles dependencies, parallelism, caching, and sandboxed execution.
$ spade run pipeline.yaml
✓ reproject (2.1s)
✓ analyze (4.3s)
Pipeline complete!
Simple by Design
Type-safe inputs and outputs. Automatic parameter loading. Zero boilerplate.
from spade import run, RasterFile
def handler(source: RasterFile) -> RasterFile:
# Your processing logic here
return RasterFile(path=result)
if __name__ == "__main__":
run(handler)library(spade)
handler <- function(source) {
# Your processing logic here
RasterFile(path = result)
}
run(handler)import { run, RasterFile } from "spade";
function handler(source: RasterFile): RasterFile {
// Your processing logic here
return new RasterFile(resultPath);
}
run(handler);package main
import "github.com/spade-dev/spade-go"
func handler(source spade.RasterFile) spade.RasterFile {
// Your processing logic here
return spade.NewRasterFile(resultPath)
}
func main() {
spade.Run(handler)
}use spade::{run, RasterFile};
fn handler(source: RasterFile) -> RasterFile {
// Your processing logic here
RasterFile::new(result_path)
}
fn main() {
run(handler);
}
Built for Real-World Data
Remote Sensing
Processing satellite imagery at scale, including reprojection, tiling, and analysis across massive raster datasets.
Learn More →Geospatial ETL
Extracting, transforming, and loading spatial datasets across formats and coordinate systems at any scale.
Learn More →Scientific Pipelines
Reproducible research workflows combining data from multiple providers and processing steps.
Learn More →Ready to Play?
Get started in minutes with the Spade CLI.
$ spade init python
$ spade add my-block
$ spade run pipeline.yaml