basalt

Realtime data layer · v4.0

Molten streams.
Solid answers.

Basalt turns raw event streams into typed, joined, queryable tables in milliseconds. One layer for ingest, transforms and serving.

Event to query

4.2 ms

Events / second

1,284,301

Move across the columns

In production at 2,400+ teams

Why Basalt

Every product runs on events. Clicks, payments, sensor ticks, model calls. Most of them cool slowly in a warehouse, hours late and full of cracks. Basalt sets them the moment they land: typed, joined, indexed and ready to query while they still matter.

Ingest to query

< 5 ms

Pipelines replaced

avg. 14

Glue code deleted

~38k lines

Product

From eruption to bedrock.

Ingest

Shape

Serve

prod · eu-north-1

p50

1.9

ms

p99

4.2

ms

Cache hit

98.7

%

p99 latency · last 60 s

ms

GET

/v1/revenue_by_minute?region=eu

200 · 3.1 ms

-- materialized, incrementally maintained

CREATE TABLE

_

revenue_by_minute

_

AS

SELECT

__

window

(ts,

_

'1 minute'

)

____

AS

_

minute,

__

p.region,

__

sum

(p.amount_cents) /

_

100

___

AS

_

revenue,

__

count

(

DISTINCT

_

s.user_id)

__

AS

_

buyers

FROM

_

stream.payments p

JOIN

_

stream.sessions s

_

USING

_

(session_id)

WHERE

_

p.status =

_

'succeeded'

GROUP BY

_

1

,

_

2

;

stream.payments

stream.sessions

revenue_by_minute

api / v1

Throughput

1.28M

ev/s

Sources

17

live

Dropped

0

/ 24h

Time

Event

Region

Set in

  • 14:02:11.482

    payment.succeeded

    eu-n1

    2.1 ms

  • 14:02:11.471

    model.inference

    us-e2

    3.4 ms

  • 14:02:11.455

    session.started

    ap-s1

    1.8 ms

  • 14:02:11.430

    cart.updated

    eu-w3

    2.7 ms

  • 14:02:11.418

    invoice.paid

    us-w1

    1.9 ms

  • 14:02:11.402

    sensor.reading

    eu-n1

    1.2 ms

  • 14:02:11.391

    user.signed_up

    us-e2

    2.4 ms

  • 14:02:11.377

    search.query

    ap-s1

    3.0 ms

  • 14:02:11.360

    payment.refunded

    eu-w3

    2.2 ms

  • 14:02:11.348

    model.inference

    us-w1

    3.8 ms

Ingest

Shape

Serve

prod · eu-north-1

p50

1.9

ms

p99

4.2

ms

Cache hit

98.7

%

p99 latency · last 60 s

ms

GET

/v1/revenue_by_minute?region=eu

200 · 3.1 ms

-- materialized, incrementally maintained

CREATE TABLE

_

revenue_by_minute

_

AS

SELECT

__

window

(ts,

_

'1 minute'

)

____

AS

_

minute,

__

p.region,

__

sum

(p.amount_cents) /

_

100

___

AS

_

revenue,

__

count

(

DISTINCT

_

s.user_id)

__

AS

_

buyers

FROM

_

stream.payments p

JOIN

_

stream.sessions s

_

USING

_

(session_id)

WHERE

_

p.status =

_

'succeeded'

GROUP BY

_

1

,

_

2

;

stream.payments

stream.sessions

revenue_by_minute

api / v1

Throughput

1.28M

ev/s

Sources

17

live

Dropped

0

/ 24h

Time

Event

Region

Set in

  • 14:02:11.482

    payment.succeeded

    eu-n1

    2.1 ms

  • 14:02:11.471

    model.inference

    us-e2

    3.4 ms

  • 14:02:11.455

    session.started

    ap-s1

    1.8 ms

  • 14:02:11.430

    cart.updated

    eu-w3

    2.7 ms

  • 14:02:11.418

    invoice.paid

    us-w1

    1.9 ms

  • 14:02:11.402

    sensor.reading

    eu-n1

    1.2 ms

  • 14:02:11.391

    user.signed_up

    us-e2

    2.4 ms

  • 14:02:11.377

    search.query

    ap-s1

    3.0 ms

  • 14:02:11.360

    payment.refunded

    eu-w3

    2.2 ms

  • 14:02:11.348

    model.inference

    us-w1

    3.8 ms

Step 01

Ingest

Catch every eruption.

Point Kafka, Postgres CDC, webhooks or the SDK at Basalt. Events land in an ordered, replicated log with exactly-once delivery, even when producers retry.

60+ native sources, no connectors to babysit

Schema inferred on first event, versioned forever

Back-pressure that never drops a row

Ingest

Shape

Serve

prod · eu-north-1

p50

1.9

ms

p99

4.2

ms

Cache hit

98.7

%

p99 latency · last 60 s

ms

GET

/v1/revenue_by_minute?region=eu

200 · 3.1 ms

-- materialized, incrementally maintained

CREATE TABLE

_

revenue_by_minute

_

AS

SELECT

__

window

(ts,

_

'1 minute'

)

____

AS

_

minute,

__

p.region,

__

sum

(p.amount_cents) /

_

100

___

AS

_

revenue,

__

count

(

DISTINCT

_

s.user_id)

__

AS

_

buyers

FROM

_

stream.payments p

JOIN

_

stream.sessions s

_

USING

_

(session_id)

WHERE

_

p.status =

_

'succeeded'

GROUP BY

_

1

,

_

2

;

stream.payments

stream.sessions

revenue_by_minute

api / v1

Throughput

1.28M

ev/s

Sources

17

live

Dropped

0

/ 24h

Time

Event

Region

Set in

  • 14:02:11.482

    payment.succeeded

    eu-n1

    2.1 ms

  • 14:02:11.471

    model.inference

    us-e2

    3.4 ms

  • 14:02:11.455

    session.started

    ap-s1

    1.8 ms

  • 14:02:11.430

    cart.updated

    eu-w3

    2.7 ms

  • 14:02:11.418

    invoice.paid

    us-w1

    1.9 ms

  • 14:02:11.402

    sensor.reading

    eu-n1

    1.2 ms

  • 14:02:11.391

    user.signed_up

    us-e2

    2.4 ms

  • 14:02:11.377

    search.query

    ap-s1

    3.0 ms

  • 14:02:11.360

    payment.refunded

    eu-w3

    2.2 ms

  • 14:02:11.348

    model.inference

    us-w1

    3.8 ms

Step 01

Ingest

Catch every eruption.

Point Kafka, Postgres CDC, webhooks or the SDK at Basalt. Events land in an ordered, replicated log with exactly-once delivery, even when producers retry.

60+ native sources, no connectors to babysit

Schema inferred on first event, versioned forever

Back-pressure that never drops a row

Ingest

Shape

Serve

prod · eu-north-1

p50

1.9

ms

p99

4.2

ms

Cache hit

98.7

%

p99 latency · last 60 s

ms

GET

/v1/revenue_by_minute?region=eu

200 · 3.1 ms

-- materialized, incrementally maintained

CREATE TABLE

_

revenue_by_minute

_

AS

SELECT

__

window

(ts,

_

'1 minute'

)

____

AS

_

minute,

__

p.region,

__

sum

(p.amount_cents) /

_

100

___

AS

_

revenue,

__

count

(

DISTINCT

_

s.user_id)

__

AS

_

buyers

FROM

_

stream.payments p

JOIN

_

stream.sessions s

_

USING

_

(session_id)

WHERE

_

p.status =

_

'succeeded'

GROUP BY

_

1

,

_

2

;

stream.payments

stream.sessions

revenue_by_minute

api / v1

Throughput

1.28M

ev/s

Sources

17

live

Dropped

0

/ 24h

Time

Event

Region

Set in

  • 14:02:11.482

    payment.succeeded

    eu-n1

    2.1 ms

  • 14:02:11.471

    model.inference

    us-e2

    3.4 ms

  • 14:02:11.455

    session.started

    ap-s1

    1.8 ms

  • 14:02:11.430

    cart.updated

    eu-w3

    2.7 ms

  • 14:02:11.418

    invoice.paid

    us-w1

    1.9 ms

  • 14:02:11.402

    sensor.reading

    eu-n1

    1.2 ms

  • 14:02:11.391

    user.signed_up

    us-e2

    2.4 ms

  • 14:02:11.377

    search.query

    ap-s1

    3.0 ms

  • 14:02:11.360

    payment.refunded

    eu-w3

    2.2 ms

  • 14:02:11.348

    model.inference

    us-w1

    3.8 ms

Step 02

Shape

Cool it into columns.

Write plain SQL. Basalt maintains every view incrementally, so joins, windows and aggregates stay current with each new event instead of on a nightly schedule.

Streaming joins across unlimited sources

Full lineage from row to raw event

Change a query and backfill runs in the background

Ingest

Shape

Serve

prod · eu-north-1

p50

1.9

ms

p99

4.2

ms

Cache hit

98.7

%

p99 latency · last 60 s

ms

GET

/v1/revenue_by_minute?region=eu

200 · 3.1 ms

-- materialized, incrementally maintained

CREATE TABLE

_

revenue_by_minute

_

AS

SELECT

__

window

(ts,

_

'1 minute'

)

____

AS

_

minute,

__

p.region,

__

sum

(p.amount_cents) /

_

100

___

AS

_

revenue,

__

count

(

DISTINCT

_

s.user_id)

__

AS

_

buyers

FROM

_

stream.payments p

JOIN

_

stream.sessions s

_

USING

_

(session_id)

WHERE

_

p.status =

_

'succeeded'

GROUP BY

_

1

,

_

2

;

stream.payments

stream.sessions

revenue_by_minute

api / v1

Throughput

1.28M

ev/s

Sources

17

live

Dropped

0

/ 24h

Time

Event

Region

Set in

  • 14:02:11.482

    payment.succeeded

    eu-n1

    2.1 ms

  • 14:02:11.471

    model.inference

    us-e2

    3.4 ms

  • 14:02:11.455

    session.started

    ap-s1

    1.8 ms

  • 14:02:11.430

    cart.updated

    eu-w3

    2.7 ms

  • 14:02:11.418

    invoice.paid

    us-w1

    1.9 ms

  • 14:02:11.402

    sensor.reading

    eu-n1

    1.2 ms

  • 14:02:11.391

    user.signed_up

    us-e2

    2.4 ms

  • 14:02:11.377

    search.query

    ap-s1

    3.0 ms

  • 14:02:11.360

    payment.refunded

    eu-w3

    2.2 ms

  • 14:02:11.348

    model.inference

    us-w1

    3.8 ms

Step 02

Shape

Cool it into columns.

Write plain SQL. Basalt maintains every view incrementally, so joins, windows and aggregates stay current with each new event instead of on a nightly schedule.

Streaming joins across unlimited sources

Full lineage from row to raw event

Change a query and backfill runs in the background

Ingest

Shape

Serve

prod · eu-north-1

p50

1.9

ms

p99

4.2

ms

Cache hit

98.7

%

p99 latency · last 60 s

ms

GET

/v1/revenue_by_minute?region=eu

200 · 3.1 ms

-- materialized, incrementally maintained

CREATE TABLE

_

revenue_by_minute

_

AS

SELECT

__

window

(ts,

_

'1 minute'

)

____

AS

_

minute,

__

p.region,

__

sum

(p.amount_cents) /

_

100

___

AS

_

revenue,

__

count

(

DISTINCT

_

s.user_id)

__

AS

_

buyers

FROM

_

stream.payments p

JOIN

_

stream.sessions s

_

USING

_

(session_id)

WHERE

_

p.status =

_

'succeeded'

GROUP BY

_

1

,

_

2

;

stream.payments

stream.sessions

revenue_by_minute

api / v1

Throughput

1.28M

ev/s

Sources

17

live

Dropped

0

/ 24h

Time

Event

Region

Set in

  • 14:02:11.482

    payment.succeeded

    eu-n1

    2.1 ms

  • 14:02:11.471

    model.inference

    us-e2

    3.4 ms

  • 14:02:11.455

    session.started

    ap-s1

    1.8 ms

  • 14:02:11.430

    cart.updated

    eu-w3

    2.7 ms

  • 14:02:11.418

    invoice.paid

    us-w1

    1.9 ms

  • 14:02:11.402

    sensor.reading

    eu-n1

    1.2 ms

  • 14:02:11.391

    user.signed_up

    us-e2

    2.4 ms

  • 14:02:11.377

    search.query

    ap-s1

    3.0 ms

  • 14:02:11.360

    payment.refunded

    eu-w3

    2.2 ms

  • 14:02:11.348

    model.inference

    us-w1

    3.8 ms

Step 03

Serve

Query it like bedrock.

Every table is an API the moment it exists. Read it from your app, dashboards or models with single-digit millisecond latency at p99.

REST, GraphQL and Postgres wire protocol

Edge replicas in 38 regions

Row-level security tied to your auth provider

Ingest

Shape

Serve

prod · eu-north-1

p50

1.9

ms

p99

4.2

ms

Cache hit

98.7

%

p99 latency · last 60 s

ms

GET

/v1/revenue_by_minute?region=eu

200 · 3.1 ms

-- materialized, incrementally maintained

CREATE TABLE

_

revenue_by_minute

_

AS

SELECT

__

window

(ts,

_

'1 minute'

)

____

AS

_

minute,

__

p.region,

__

sum

(p.amount_cents) /

_

100

___

AS

_

revenue,

__

count

(

DISTINCT

_

s.user_id)

__

AS

_

buyers

FROM

_

stream.payments p

JOIN

_

stream.sessions s

_

USING

_

(session_id)

WHERE

_

p.status =

_

'succeeded'

GROUP BY

_

1

,

_

2

;

stream.payments

stream.sessions

revenue_by_minute

api / v1

Throughput

1.28M

ev/s

Sources

17

live

Dropped

0

/ 24h

Time

Event

Region

Set in

  • 14:02:11.482

    payment.succeeded

    eu-n1

    2.1 ms

  • 14:02:11.471

    model.inference

    us-e2

    3.4 ms

  • 14:02:11.455

    session.started

    ap-s1

    1.8 ms

  • 14:02:11.430

    cart.updated

    eu-w3

    2.7 ms

  • 14:02:11.418

    invoice.paid

    us-w1

    1.9 ms

  • 14:02:11.402

    sensor.reading

    eu-n1

    1.2 ms

  • 14:02:11.391

    user.signed_up

    us-e2

    2.4 ms

  • 14:02:11.377

    search.query

    ap-s1

    3.0 ms

  • 14:02:11.360

    payment.refunded

    eu-w3

    2.2 ms

  • 14:02:11.348

    model.inference

    us-w1

    3.8 ms

Step 03

Serve

Query it like bedrock.

Every table is an API the moment it exists. Read it from your app, dashboards or models with single-digit millisecond latency at p99.

REST, GraphQL and Postgres wire protocol

Edge replicas in 38 regions

Row-level security tied to your auth provider

Ingest

Shape

Serve

prod · eu-north-1

p50

1.9

ms

p99

4.2

ms

Cache hit

98.7

%

p99 latency · last 60 s

ms

GET

/v1/revenue_by_minute?region=eu

200 · 3.1 ms

-- materialized, incrementally maintained

CREATE TABLE

_

revenue_by_minute

_

AS

SELECT

__

window

(ts,

_

'1 minute'

)

____

AS

_

minute,

__

p.region,

__

sum

(p.amount_cents) /

_

100

___

AS

_

revenue,

__

count

(

DISTINCT

_

s.user_id)

__

AS

_

buyers

FROM

_

stream.payments p

JOIN

_

stream.sessions s

_

USING

_

(session_id)

WHERE

_

p.status =

_

'succeeded'

GROUP BY

_

1

,

_

2

;

stream.payments

stream.sessions

revenue_by_minute

api / v1

Throughput

1.28M

ev/s

Sources

17

live

Dropped

0

/ 24h

Time

Event

Region

Set in

  • 14:02:11.482

    payment.succeeded

    eu-n1

    2.1 ms

  • 14:02:11.471

    model.inference

    us-e2

    3.4 ms

  • 14:02:11.455

    session.started

    ap-s1

    1.8 ms

  • 14:02:11.430

    cart.updated

    eu-w3

    2.7 ms

  • 14:02:11.418

    invoice.paid

    us-w1

    1.9 ms

  • 14:02:11.402

    sensor.reading

    eu-n1

    1.2 ms

  • 14:02:11.391

    user.signed_up

    us-e2

    2.4 ms

  • 14:02:11.377

    search.query

    ap-s1

    3.0 ms

  • 14:02:11.360

    payment.refunded

    eu-w3

    2.2 ms

  • 14:02:11.348

    model.inference

    us-w1

    3.8 ms

Capabilities

Built for the hard parts.

Delivery

Guarantee

x1 only

Exactly once

Idempotent writes with per-key ordering. Retries, replays and network splits never double-count a payment.

Schema

Evolution

v12v13v14

Schema evolution

Add, rename or retype a field without a migration window. Old readers keep working, new readers see the new shape.

History

Time travel

-30dnow

Time travel

Query any table as of any second in the last 30 days. Debug last Tuesday's numbers with last Tuesday's data.

Network

38 regions

Edge replicas

Read replicas follow your users. Writes stay consistent, reads stay close, and failover takes under a second.

Access

Policy

tenant = ****tenant = acmetenant = ****tenant = acme

Row-level security

Write policies once in SQL. Basalt enforces them on every API, replica and export, keyed to your auth provider.

Operations

Zero downtime

serving · v1backfilling · v2

Live backfills

Rebuild a view across two years of history while the old version keeps serving. Swap atomically when it catches up.

By the numbers

Hard numbers, literally.

Query latency, p99

4.2

ms

Across all public regions, trailing 90 days.

Events per day

2.1

B

Peak sustained load on one production cluster.

Uptime SLA

99.95

%

Financially backed on Scale and Enterprise.

Edge regions

36

From Reykjavík to Singapore, more every quarter.

Developers

Eleven lines to production.

Typed SDKs for TypeScript, Python and Go. Define a source, write a view, read the result. Basalt handles partitioning, retries, scaling and the 3 a.m. pages.

pipeline.ts

pipeline.py

terminal

import

_

{ basalt }

_

from

_

"@basalt/sdk"

;

const

_

db = basalt({ project:

_

"acme-prod"

_

});

await

_

db.source(

"payments"

, { kafka:

_

"payments.v3"

_

});

await

_

db.view(

"revenue_by_minute"

,

_

`

__

SELECT window(ts, '1m') AS minute, sum(amount) AS revenue

__

FROM payments GROUP BY 1`

);

const

_

rows =

_

await

_

db.table(

"revenue_by_minute"

).last(

60

);

_

// 3.1 ms

✓

source payments connected · 1.28M ev/s

✓

view revenue_by_minute materialized in 812 ms

✓

GET /v1/revenue_by_minute ready

Customers

“We deleted fourteen pipelines and a Kafka team's worth of on-call in one quarter. Our fraud model now sees a payment four milliseconds after it happens.”

IA

Ingrid Arnadottir

VP Engineering, Orbitly

Orbitly · Fintech

Tessera · Commerce

Quarry · Logistics

Pricing

Pay for what flows.

Monthly

Yearly

-20%

Hobby

Free forever

$

0

per month

For side projects and prototypes that need real streaming.

10M events / month

3 materialized views

1 region, community support

Scale

Most teams

$

249

per month, then $0.18 per 1M events

For production workloads with SLAs and a team behind them.

1B events included

Unlimited views and sources

99.995% uptime SLA, 3 regions

30-day time travel

Start 14-day trial

Enterprise

Custom

Custom

annual agreement

For regulated data, dedicated clusters and private networking.

Dedicated or BYOC deployment

SOC 2 Type II, HIPAA, GDPR

All 38 regions, private link

Named engineer, 15-min response

Get started

Set your data in stone.

Free up to 10M events a month. No card, no sales call. Your first pipeline is live in about four minutes.

2,400+ teams in production

SOC 2 Type II

38 regions

Get started

Set your data in stone.

Free up to 10M events a month. No card, no sales call. Your first pipeline is live in about four minutes.

2,400+ teams in production

SOC 2 Type II

38 regions

Get started

Set your data in stone.

Free up to 10M events a month. No card, no sales call. Your first pipeline is live in about four minutes.

2,400+ teams in production

SOC 2 Type II

38 regions

© 2026 Basalt Labs

All systems normal

Back to top ↑

404

© 2026 Basalt Labs

All systems normal

Back to top ↑

404

© 2026 Basalt Labs

All systems normal

Back to top ↑

404

Create a free website with Framer, the website builder loved by startups, designers and agencies.