Skip to content
Warehouse & storage export

Your data, in your own bucket.

Every night SegmentHub writes events, profiles, visitors and campaign statistics to storage you own, in a format your warehouse loads without a conversion step. The bucket, the credentials, the storage bill and the retention policy are all yours — the same principle as bringing your own mail relay and your own ad credentials.

s3://your-bucket/segmenthub/

acme/events/

dt=2026-09-05/

part-00001.parquet

part-00002.parquet

_load.sql

_manifest.json

dt=2026-09-06/

part-00001.parquet

_manifest.json

acme/profiles/

acme/email_campaign_stats/

Manifest = safe to load
Re-runnable partitions

Six datasets, every day

Each with a fixed, published column contract — because once a partition is loaded, those names are in someone's models and dashboards.

events

by event time

profiles

by last seen

visitors

by last seen

campaign_stats

on-site

email_campaign_stats

daily rows

push_campaign_stats

daily rows

Your own attribute names and event parameters travel in a JSON column rather than widening the table per account, so every tenant loads into the same fixed schema and a new attribute never breaks yesterday's model.

Three formats, one layout your tools already understand

Parquet

Snappy-compressed columnar files with the best storage and scan economics. Arrays stay real arrays; JSON columns are strings your warehouse parses on read.

NDJSON

Gzipped, one object per line, with nested structure intact. Loads everywhere, and a human can decompress a part and read it — which matters more than it sounds at 3am.

CSV

Gzipped and flattened, for the spreadsheet and the legacy loader. Escaping is done properly, because attribute values routinely contain commas, quotes and newlines.

Hive-style partitions

Files land under dt=YYYY-MM-DD/, which BigQuery, Athena, Redshift Spectrum, Spark and DuckDB all discover as a partition column with no configuration. Data files start with part- and metadata with an underscore, so a wildcard load can never accidentally parse the manifest as data.

The manifest is the commit marker

Parts are written first and the manifest last, so "is this partition safe to load" is one cheap test. It carries the schema, per-file row counts, byte counts and checksums, and a line saying where the rows came from — which is the answer to the first question anyone asks about a light-looking day.

A partition is a unit of work that can be redone

The scheduled export, a ninety-day backfill, a retry after a bucket outage and a re-export you queue by hand are all the same code path reaching the same ledger row. That is why none of them can double a row in your warehouse.

Backfill on request

Events are re-read from the platform's own event archive rather than teed off the live stream, so any day the archive still holds can be exported today — and they are partitioned by when each event happened, not when it was archived.

Replace, never append

A re-run deletes the stale parts a shorter run leaves behind before it writes the manifest, so "replace the partition" is true rather than approximately true. Today is never exported: its partition is not closed yet.

Never at the cost of the platform

The sweep runs every fifteen minutes on its own worker pool with a per-account ceiling, so one tenant catching up on three months cannot slow the indexing your audience queries depend on.

Into the warehouse, not just into a bucket

BigQuery loads natively. Each day targets its own table partition and replaces it, so a retry corrects a day rather than doubling it. The schema is passed explicitly rather than auto-detected — a day where one column happened to be empty would otherwise land as a different type and break the loads weeks later.

Snowflake, Athena and Trino get ready-to-run SQL. Every partition can carry a generated script with a COPY INTO, a LOAD DATA and a CREATE EXTERNAL TABLE, written from the same schema the files were written with, so the two cannot disagree.

An existing table is left alone. You may have clustered it, added columns or set a retention policy, and none of that is ours to overwrite.

The connection test writes and deletes a real object. It is the only honest check — a read-only key passes everything else and then fails at 03:00 on a partition nobody is watching.

Partition ledger

events · 2026-09-05Completed
profiles · 2026-09-05Completed
events · 2026-09-04Running
visitors · 2026-09-04Queued
events · 2026-09-03Retrying

One row per dataset and day, not per attempt. A failed partition backs off and retries on its own; the panel can queue any date range for re-export. Illustrative interface values.

Answer "can we get our data out?" with a bucket path.

Pair it with the reporting module for day-to-day questions and the REST API for everything in between.

Set up your first export