Fresh features and traceable training data
Models are only as trustworthy as the data behind them. Synchronoid records where every value came from, so you can explain a prediction, rebuild a dataset and prove what a model saw.
Nobody can say what the model was trained on
Training sets are assembled from many sources by scripts that change over time. Months later, someone asks why a feature had a strange value, and no one can answer.
Feature tables go stale when a feed fails silently, and bad rows slip into training without a trace.
Provenance and replay for every dataset
Every field carries its source, fetch time and run id. A training set is a query on the published layer at a known point in time, and the raw layer lets you rebuild it exactly.
Data quality checks block bad data before it reaches a feature table, and alerts tell you when a source goes quiet.
Built for data you have to explain
Provenance on every value
Ask why a feature looks the way it does and get the source, time and run that produced it.
Point-in-time datasets
Rebuild a dataset as it was on any date from the change history in the published layer.
Quality gates
Checks block bad data from reaching feature tables and training sets.
Replay from raw
Change a transformation and re-run it over stored payloads without calling the source again.
Fresh features
Schedules and sensors keep feature tables current. Sources that fail are paused and flagged.
Lineage graph
See which sources, assets and tables feed each model input in the control room.
A feature table with its history attached
Published assets track changes by default, so every version of a feature row is kept with its provenance.
- Export snapshots to your warehouse or object storage
- Pull records with provenance through the REST API
- Stream changes to your feature store with a change feed
import synchronoid as sy @sy.asset(layer="published", deps=[customer_events]) def customer_features(ctx, customer_events): ctx.log.info("building features") table = customer_events.aggregate( key="customer_id", sessions_30d="count(session_id)", avg_basket="mean(basket_value)", ) return table.merge(key="customer_id", track_changes=True) # Why is avg_basket 41.2 for customer c-1042? prov = customer_features.provenance("c-1042", "avg_basket") # -> source=shop_events, fetched_at=2026-10-28T02:00Z, run=run_8f3a
“When a model result looked odd, we used to spend days tracing it by hand. Now we open the record, see which feed and which run produced the value, and move on.”
Beta customer
Train on data you can explain
Request access and we will help you connect your first feature sources.