Skip to main content

A Rust-backed Python clustering library

Project description

rustcluster

Fast, Rust-backed clustering for Python. Six algorithms, sklearn-compatible API, purpose-built embedding clustering with 11x PCA speedup.

Highlights

  • 6 algorithms: KMeans, MiniBatchKMeans, DBSCAN, HDBSCAN, AgglomerativeClustering, EmbeddingCluster
  • EmbeddingCluster — purpose-built pipeline for OpenAI/Cohere/Voyage embeddings (L2-normalize → PCA → spherical K-means)
  • EmbeddingReducer — standalone PCA transformer with save/load (fit once, cluster for free)
  • faer-accelerated PCA — 11x faster than hand-rolled matmul via SIMD-optimized GEMM
  • 3 distance metrics: euclidean, cosine, manhattan
  • 3 evaluation metrics: silhouette score, Calinski-Harabasz, Davies-Bouldin
  • KD-tree acceleration for DBSCAN/HDBSCAN neighbor queries (10-200x on low-d data)
  • Native f32/f64 — no silent upcast, doubles cache efficiency with f32
  • Cluster slotting — snapshot fitted clusters, assign new points 100x faster than refitting
  • Pickle serialization for all fitted models
  • GIL released during all compute — plays well with threads and async
  • 461 tests across Rust and Python

Installation

pip install rustcluster

Or from source (requires Rust toolchain + Python 3.10+):

pip install maturin
git clone https://github.com/mfbaig35r/rustcluster.git
cd rustcluster
maturin develop --release

Quickstart

K-Means

from rustcluster import KMeans

model = KMeans(n_clusters=3, random_state=42)
model.fit(X)
model.labels_           # cluster assignments
model.cluster_centers_  # centroids (k x d)
model.inertia_          # sum of squared distances
model.predict(X_new)    # assign new data

Embedding Clustering

Purpose-built pipeline for dense embedding vectors (OpenAI, Cohere, Voyage, etc.):

from rustcluster.experimental import EmbeddingCluster

model = EmbeddingCluster(n_clusters=50, reduction_dim=128)
model.fit(embeddings)          # L2-normalize → PCA → spherical K-means
model.labels_                  # cluster assignments
model.cluster_centers_         # unit-norm centroids in reduced space
model.intra_similarity_        # per-cluster cosine similarity
model.reduced_data_            # access PCA-reduced data

EmbeddingReducer (Fit Once, Cluster Many)

PCA is 99% of the embedding pipeline runtime. Separate reduction from clustering to iterate for free:

from rustcluster.experimental import EmbeddingReducer

# Pay the PCA cost once
reducer = EmbeddingReducer(target_dim=128)
X_reduced = reducer.fit_transform(embeddings)  # 323K × 1536 → 128 in ~56s
reducer.save("pca_128.bin")

# Iterate on clustering for free
reducer = EmbeddingReducer.load("pca_128.bin")
X_reduced = reducer.transform(new_embeddings)

EmbeddingCluster(n_clusters=50, reduction_dim=None).fit(X_reduced)   # ~4s
EmbeddingCluster(n_clusters=100, reduction_dim=None).fit(X_reduced)  # ~8s
EmbeddingCluster(n_clusters=200, reduction_dim=None).fit(X_reduced)  # ~15s

Matryoshka models (e.g., text-embedding-3-small) can skip PCA entirely:

reducer = EmbeddingReducer(target_dim=128, method="matryoshka")
X_reduced = reducer.fit_transform(embeddings)  # instant — just truncates + L2-normalizes

See the embedding clustering guide for full documentation.

Cluster Slotting (Incremental Assignment)

Fit once, assign new data forever. Snapshot freezes cluster centroids — new points are assigned without re-clustering:

from rustcluster import KMeans, ClusterSnapshot

# Fit and snapshot
model = KMeans(n_clusters=50).fit(X_train)
snapshot = model.snapshot()
snapshot.save("clusters/")

# Later: load and assign new data (no refit needed)
snapshot = ClusterSnapshot.load("clusters/")
labels = snapshot.assign(X_new)                   # 100x faster than refitting

Works with KMeans, MiniBatchKMeans, and EmbeddingCluster. EmbeddingCluster snapshots bake in the full preprocessing pipeline (L2-normalize, PCA, spherical assignment).

Confidence scoring and rejection:

result = snapshot.assign_with_scores(X_new, confidence_threshold=0.3)
result.labels_       # -1 for rejected points
result.confidences_  # [0, 1) — higher means more decisive assignment
result.distances_    # distance to nearest centroid
result.rejected_     # boolean mask

Drift detection:

report = snapshot.drift_report(X_recent)
report.global_mean_distance_  # compare to training baseline
report.relative_drift_        # per-cluster drift

Persistence: safetensors (centroids) + JSON (metadata). A 50-cluster, 128d snapshot is ~50 KB vs GBs of training data.

Validated on 323K CROSS ruling embeddings: 113x speedup, 99.86% training fidelity, equivalent purity to full refit.

Mini-Batch K-Means

from rustcluster import MiniBatchKMeans

model = MiniBatchKMeans(n_clusters=3, batch_size=256, random_state=42)
model.fit(X_large)      # scales to large datasets

DBSCAN

from rustcluster import DBSCAN

model = DBSCAN(eps=0.5, min_samples=5)
model.fit(X)
model.labels_                # -1 for noise
model.core_sample_indices_   # core point indices

HDBSCAN

from rustcluster import HDBSCAN

model = HDBSCAN(min_cluster_size=5)
model.fit(X)
model.labels_              # -1 for noise
model.probabilities_       # soft membership [0, 1]
model.cluster_persistence_ # per-cluster stability

Agglomerative Clustering

from rustcluster import AgglomerativeClustering

model = AgglomerativeClustering(n_clusters=3, linkage="ward")
model.fit(X)
model.labels_     # cluster assignments
model.children_   # merge history
model.distances_  # distance at each merge

Evaluation Metrics

from rustcluster import silhouette_score, calinski_harabasz_score, davies_bouldin_score

silhouette_score(X, labels)         # [-1, 1], higher is better
calinski_harabasz_score(X, labels)  # higher is better
davies_bouldin_score(X, labels)     # lower is better

Distance Metrics

All algorithms accept a metric parameter:

KMeans(n_clusters=5, metric="cosine")
DBSCAN(eps=0.3, metric="manhattan")
HDBSCAN(min_cluster_size=5, metric="euclidean")
Metric Aliases KD-tree acceleration Notes
"euclidean" "l2" Yes Default for all algorithms
"cosine" No (brute force) K-means forces Lloyd (Hamerly assumes Euclidean)
"manhattan" "cityblock", "l1" Yes

Ward linkage requires euclidean metric.

Performance

K-Means vs scikit-learn

Single-threaded, n_init=1, median of 5 runs:

n d k Speedup vs sklearn
1,000 8 8 2.9x
10,000 8 8 2.4x
100,000 8 32 3.2x
100,000 32 32 1.4x

DBSCAN and HDBSCAN use KD-tree acceleration for d <= 16 with euclidean or manhattan metrics, reducing neighbor queries from O(n^2) to O(n log n).

Embedding Clustering

Measured on 323K embeddings (text-embedding-3-small, 1536d → 128d, K=98, Apple Silicon):

Workflow Time
Full pipeline (PCA + cluster) 58s
Subsequent run (cached reduced data) 7.5s
5 clustering configs on cached data 74s
Matryoshka (no PCA needed) ~5s

Full benchmarks: python benches/benchmark.py

Serialization

All models support pickle:

import pickle

model = KMeans(n_clusters=3).fit(X)
data = pickle.dumps(model)
model_restored = pickle.loads(data)  # fitted state preserved

EmbeddingReducer uses a compact binary format:

reducer.save("pca_128.bin")                   # 1.5 KB
reducer = EmbeddingReducer.load("pca_128.bin") # instant

ClusterSnapshot uses safetensors + JSON for portable, safe persistence:

snapshot = model.snapshot()
snapshot.save("clusters/")                     # safetensors + metadata.json
snapshot = ClusterSnapshot.load("clusters/")   # zero-copy load

Development

maturin develop --release              # build
cargo test --no-default-features --lib # Rust tests (197)
pytest tests/ -v                       # Python tests (264)
python benches/benchmark.py            # benchmark vs sklearn
cargo fmt -- --check                   # formatting
cargo clippy --no-default-features --lib -- -D warnings  # linting

Architecture

Three-layer kernel design separating concerns:

  1. PyO3 boundary (src/lib.rs) — input validation, GIL release, dtype dispatch
  2. Algorithm logic (src/kmeans.rs, etc.) — iteration, convergence, ndarray types
  3. Hot kernel (src/utils.rs, src/distance.rs) — raw &[F] slices for auto-vectorization

The embedding pipeline adds:

  1. Embedding module (src/embedding/) — spherical K-means, PCA (faer-backed), vMF refinement, EmbeddingReducer

See docs/architecture-decisions.md for details and docs/lessons-building-rustcluster.md for the full build story.

Contributing

See CONTRIBUTING.md for how to add algorithms, distance metrics, and tests.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rustcluster-0.5.0.tar.gz (257.3 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

rustcluster-0.5.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

rustcluster-0.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.0 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ ARM64

rustcluster-0.5.0-cp312-cp312-win_amd64.whl (1.3 MB view details)

Uploaded CPython 3.12Windows x86-64

rustcluster-0.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

rustcluster-0.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.0 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ ARM64

rustcluster-0.5.0-cp312-cp312-macosx_11_0_arm64.whl (967.9 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

rustcluster-0.5.0-cp312-cp312-macosx_10_12_x86_64.whl (1.1 MB view details)

Uploaded CPython 3.12macOS 10.12+ x86-64

rustcluster-0.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

rustcluster-0.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.0 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ ARM64

rustcluster-0.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

rustcluster-0.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.0 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ ARM64

rustcluster-0.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ x86-64

rustcluster-0.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.0 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ ARM64

File details

Details for the file rustcluster-0.5.0.tar.gz.

File metadata

  • Download URL: rustcluster-0.5.0.tar.gz
  • Upload date:
  • Size: 257.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for rustcluster-0.5.0.tar.gz
Algorithm Hash digest
SHA256 a5ee1dc002a30dfdd1ea0ac0045c872c853e6a980ef2dba158380882b88c13c9
MD5 d50c12cd91e08f91372c9c59610a1de1
BLAKE2b-256 94064d1d77865ad411d81b17a781a542fcee38ed750e4590afadca71d3a0ba08

See more details on using hashes here.

Provenance

The following attestation bundles were made for rustcluster-0.5.0.tar.gz:

Publisher: release.yml on mfbaig35r/rustcluster

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rustcluster-0.5.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for rustcluster-0.5.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 bf3d969b8d61777cb763a8a08656286ef108500cca815fe619fe4fa6362c2ced
MD5 f8a983ebcfa11ac1675b873dc4a576d8
BLAKE2b-256 a53d4bd3bc9ea585294d9c2e9cbe6bea81f9241a678f03d818ed3f6d8fdf36cd

See more details on using hashes here.

Provenance

The following attestation bundles were made for rustcluster-0.5.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on mfbaig35r/rustcluster

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rustcluster-0.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for rustcluster-0.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 81a7e1b6c61aabda35a4c0b25bbf59a2d767177f5dac2fabea1359e13b1ec44d
MD5 422c11c32e7c5b6eaf5f5a9d0f77a067
BLAKE2b-256 8047689c54ac60306198b9d48fd955a61fa30f11833e156158a0c7aef94d84fa

See more details on using hashes here.

Provenance

The following attestation bundles were made for rustcluster-0.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on mfbaig35r/rustcluster

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rustcluster-0.5.0-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for rustcluster-0.5.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 b4ec76614e05314f191e267fe7414c632c4d739434278c716d4210e834ccc4f9
MD5 ef896877594714e05f56ca5a5d7ef5c8
BLAKE2b-256 3d2e693538f02d8e8b5a7699575384172d465549c05a58f427e183ed58cb77fd

See more details on using hashes here.

Provenance

The following attestation bundles were made for rustcluster-0.5.0-cp312-cp312-win_amd64.whl:

Publisher: release.yml on mfbaig35r/rustcluster

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rustcluster-0.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for rustcluster-0.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 b02ad6253cc85b4c889815e08a9b0ca23c6960e783e9f632998a9af5f19ffd09
MD5 e092938bc4662610c254cd5297f4e268
BLAKE2b-256 c039496c0500e86d64388fb2ab30dda4882d3cd853d84c07927bfbf5ca92a955

See more details on using hashes here.

Provenance

The following attestation bundles were made for rustcluster-0.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on mfbaig35r/rustcluster

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rustcluster-0.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for rustcluster-0.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 76e661b1c58302eba4b538a7340ca43c36e1403496f06a8646288cf69d3d2746
MD5 5a52cdfd650315e70aa14c0ac328f464
BLAKE2b-256 824bf6ce01b663b85aa05340f46b3f86b7c09e20b562f309d3ed56a1804c85a2

See more details on using hashes here.

Provenance

The following attestation bundles were made for rustcluster-0.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on mfbaig35r/rustcluster

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rustcluster-0.5.0-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for rustcluster-0.5.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 71ffab18917bd0b94aadb1e2c252bcab45d9023075455091783b56d2756c3fdd
MD5 9931bd913c45f907b304ba9c2e311f31
BLAKE2b-256 b249ca525e353407f204a900bb84fd91c2c1760d900c542a2acdf971a8af63d5

See more details on using hashes here.

Provenance

The following attestation bundles were made for rustcluster-0.5.0-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: release.yml on mfbaig35r/rustcluster

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rustcluster-0.5.0-cp312-cp312-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for rustcluster-0.5.0-cp312-cp312-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 bcaceea26eb757f7f624733d2e53a7276bfcdb414c4af37d9cd379064354a2c5
MD5 4b022b3b96a607c035e78d86b441274c
BLAKE2b-256 27c91718f15fd8bb2f85f079aa41d5696f104008ddbd99557947aa509c6754aa

See more details on using hashes here.

Provenance

The following attestation bundles were made for rustcluster-0.5.0-cp312-cp312-macosx_10_12_x86_64.whl:

Publisher: release.yml on mfbaig35r/rustcluster

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rustcluster-0.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for rustcluster-0.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 44910e861b4d1666416447f104688da0be37a4d4adaa062a9496d6c4a286af89
MD5 ba04ba69f2a790bf7b56c1ae05bea5f2
BLAKE2b-256 058a2ce6de26f0bbf23ee06ac84de19cd53f1ead6a8ba038fddf47824e521d25

See more details on using hashes here.

Provenance

The following attestation bundles were made for rustcluster-0.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on mfbaig35r/rustcluster

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rustcluster-0.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for rustcluster-0.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 0af0bc89cc01c0ffa1a35fcc02e810e6b4649319eb58c8aa597952d991d4f99d
MD5 ff55db2d6b018d9f22c8074966c7635f
BLAKE2b-256 21517c092fa12eeedfbb1e6914354f41014c7e852167dfec11ec8f3524a9e355

See more details on using hashes here.

Provenance

The following attestation bundles were made for rustcluster-0.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on mfbaig35r/rustcluster

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rustcluster-0.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for rustcluster-0.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 a6d2a37417bacd85e70909cedad2f33e1ac7312ec381f00bb75ca9c885dca575
MD5 9747757a71f0688d19d0d4189e6cd624
BLAKE2b-256 04a00d49a2f305ab79f3b128cfa858fe2695b273b8871a4069f9c696edb93f14

See more details on using hashes here.

Provenance

The following attestation bundles were made for rustcluster-0.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on mfbaig35r/rustcluster

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rustcluster-0.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for rustcluster-0.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 b241e3b50f1a1af0908825860d5cc58c0ff9e1b34f67c0b63349efa3c336ff3e
MD5 9231e725d8c67e45e5924719d09ee773
BLAKE2b-256 dff52e9217e23a185de40edc29fb2925074e274db6b567911e6e56466341653d

See more details on using hashes here.

Provenance

The following attestation bundles were made for rustcluster-0.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on mfbaig35r/rustcluster

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rustcluster-0.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for rustcluster-0.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 b62fd2f6ae4e604ddbf55c7fb845f877e7f6e130ae6de64e3d898c5abb2a1d8f
MD5 a201f05161df06b0dbed28ed65f09b6e
BLAKE2b-256 890e44cea2a1107df691df78b9d77781af995d92eb376193c056200672904214

See more details on using hashes here.

Provenance

The following attestation bundles were made for rustcluster-0.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on mfbaig35r/rustcluster

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rustcluster-0.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for rustcluster-0.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 d8b5837e6d476233d475798e282c97e9a4181e2fb4b15715c89c2a96849c76c3
MD5 d99916e7c9dcc23e81388ccac492b799
BLAKE2b-256 c712daf8b6a7c30d5811d3a55258501196d03ab5bc3c67b2ab40b53190826beb

See more details on using hashes here.

Provenance

The following attestation bundles were made for rustcluster-0.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on mfbaig35r/rustcluster

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page