Introducing the Shaped Signal Engine

We built a declarative signal computation engine that eliminates training-serving skew, cuts the iteration cycle from weeks to hours, and ships with 25+ signal primitives. It powers ranking models, search relevance, agent context, and any workload where features need to be fresh, correct, and fast. You define signals once. The engine handles the rest.

Introducing the Shaped Signal Engine

TL;DR: We built a declarative signal computation engine that eliminates training-serving skew, cuts the iteration cycle from weeks to hours, and ships with 25+ signal primitives. It powers ranking models, search relevance, agent context, and any workload where features need to be fresh, correct, and fast. You define signals once. The engine handles the rest.


Your model is live. You have a hypothesis: user-category click-through rate over the last 30 days might be a better signal than the 7-day version you’re using now. In theory, that’s a one-line change. In practice:

  1. You update the feature definition in the training pipeline.
  2. You backfill historical data for the new window.
  3. You retrain the model.
  4. You update the serving pipeline to compute the new feature at query time.
  5. You test for consistency between training and serving.
  6. You deploy.

That’s a multi-week project for a one-line config change. And every step is a chance to introduce the exact skew you were trying to avoid.

We kept seeing this with our customers. The models were fast to train. The queries were fast to serve. The part that took weeks was getting the right features into the right shape, in the right place, at the right time. And once they were there, changing anything meant starting the whole cycle over again. Most teams had given up on rapid feature iteration entirely.

So we built the Signal Engine.

Before Signal EngineWith Signal Engine
1. Update training pipeline1. Change the config
2. Backfill historical data2. Done. (engine handles backfill, retrain, and deploy)
3. Retrain model
4. Update serving pipeline
5. Test for consistency
6. Deploy
Timeline: 2-4 weeksTimeline: hours

The Training-Serving Skew Problem

Every team building ranking, search, or agent retrieval eventually arrives at the same architecture: one codebase for computing features during training and a completely separate codebase for computing those same features during serving.

These two implementations start in sync. Then they drift. Slowly, silently, and in ways that are incredibly hard to debug. A data scientist adds a 30-day windowed aggregation to the training pipeline. An engineer implements it in the serving path, but the window boundary logic is slightly different. The model trains on one distribution and serves on another. Metrics degrade by 2-3% and nobody can figure out why, because the feature values look plausible on both sides. They’re just not the same.

This is training-serving skew, and it’s the single most common source of silent model degradation in production.


What the Signal Engine Does

The Signal Engine is a declarative computation engine. You define features as signals using a typed DSL, and the engine handles compilation, execution, and state management across training, serving, and streaming.

feature_definitions:
  - type: aggregation
    name: clicks_7d
    input: user_id
    aggregation_fn: count
    group_by: [user_id]
    window: 7d

  - type: ratio
    name: purchase_rate
    numerator: purchases_30d
    denominator: views_7d
    smooth: 1.0

  - type: cross
    name: user_category
    inputs: [user_id, item.category]
    method: hash
    buckets: 50000

You define each signal with a type, a name, and type-specific parameters. The engine resolves these at both training and scoring time, guaranteeing identical feature values across both. Aggregation signals only see data before the current row, preventing time leakage. At scoring time, signals resolve from precomputed state in under 5ms.


25+ Signal Primitives

We didn’t want to ship a framework that handles three types of features and makes you build everything else yourself. The Signal Engine ships with over 25 signal types across six categories.

CategorySignal TypesWhat You Get
Numericalexpression, transform, bucket, normalization, clip, castArithmetic, log transforms, discretization, z-score normalization
Time & Contextcyclic_time, time_component, time_since_last, time_diffCyclic encoding (23:00 is close to 00:00), recency signals, seasonality
Aggregationsaggregation, ratio, lag, diffWindowed count/sum/avg/min/max with filters, safe division, sequential patterns
Cross & Interactioncross, factorize, target_encoding, multi_hotHashed crosses with stateless deterministic hashing, target encoding with automatic offline vs online resolution
Search & Geovector_similarity, text_similarity, geo_distance, geo_hashReal-time cosine similarity, BM25, haversine distance between coordinates
Sequences & Vectorssequence, vector_aggregation, vector_flatten, list_op, embeddingID sequences for SASRec/BERT4Rec, embedding pooling, native vector column support

Where Signals Show Up

Signals are a general compute primitive. Anywhere your application needs a real-time derived value from user, item, or interaction data, that’s a signal.

Use CaseWhat Signals DoExample
Ranking & FeedsFeed real-time features to scoring models and feed rankersuser_category_ctr over a 30d window boosts relevant items; ratio of clicks to impressions personalizes feeds
SearchCompute query-item relevance at retrieval timevector_similarity between query and item embeddings, text_similarity for lexical matching, geo_distance for proximity
Agent ContextEnrich retrieval so agents get better context on each usertime_since_last interaction tells the agent what’s fresh; aggregation over recent events summarizes behavior
Faceted FilteringDerive filterable metadata from raw events in real timeis_trending threshold on hourly item velocity enables dynamic facets

Signals are composable: reference earlier signals by name to build chains, and use hide: true on intermediate signals that feed downstream features without appearing in the final set. The engine handles vector columns (embeddings, query vectors) as first-class citizens alongside scalar features. Signals also support inline unit tests that validate at compile time and carry metadata (owner, tags, deprecation status). Treat your signal definitions like code, because that’s what they are.


Production Realities

We built the Signal Engine for production workloads, not notebooks. Three design decisions reflect this.

Null Safety

Every signal declares a strategy for handling missing data: fill_value, mean, mode, or error. When a join fails, a lookup returns empty, or a user has no history, the engine substitutes a default before passing data to the model. You never get a segfault from a missing value in production.

on_null: { strategy: fill_value, value: 0.0 }

Stateless Categoricals

The engine uses deterministic hashing to fixed buckets for all categorical encoding. No global dictionaries to build, version, and synchronize across training and serving pods. The same string hashes to the same bucket everywhere, every time. We’ve tested this at 100M+ items and 500M+ interactions without dictionary sync issues.

Point-in-Time Correctness

Aggregation signals only see data before the current row. This isn’t a flag you remember to set. It’s how the engine works. Time leakage is structurally impossible, not just discouraged.


The Architecture: Compute on Write

Under the hood, the Signal Engine operates across three layers.

Signal Engine ArchitectureCompute on write, not compute on readSegmentKinesisKafka1Stream Ingestion LayerMicro-batches → atomic state updates2Offline Training LayerIncremental datasets, backfill, historical replay3Online Query Layer<5ms signal resolutionPythonTypeScriptSQL

Stream ingestion: A horizontal worker processes micro-batches from your real-time connectors (Segment, Kinesis, Kafka), updating signal state atomically as events arrive.

Offline training: Resolvers incrementally generate training datasets. The engine checks for missing date partitions and only computes what’s needed, backfilling with historical replay when necessary. When you deploy a new signal, the offline engine replays historical data to hydrate state before the stream worker takes over. No cold starts.

Online query: When you execute a query via our Python, TypeScript, or SQL SDKs, the engine resolves all signals in under 5ms, bypassing the heavy read-repair logic that plagues traditional feature serving.

The key shift is from “compute on read” to “compute on write.” Instead of the query service fetching raw user history and counting clicks on the fly at query time, signals are precomputed as events arrive. The query service just reads the result.


From Definition to Evaluation in Hours

This is where the Signal Engine being part of the Shaped platform really pays off. When you define a new signal or change an existing one, the engine backfills the historical data, retrains your ranking model against the new feature set, and produces evaluation metrics. You see the impact directly, without stitching together separate systems.

For agent context and retrieval workloads, signals work as a standalone compute layer through our SDKs. An agent making a retrieval call gets signals resolved at query time: how recently the user interacted, what categories they’ve been browsing, how far they are from the item. The agent doesn’t need to compute any of this. It just gets richer context.

We think this is the real unlock. Not just eliminating skew (though that matters), but making feature iteration fast enough that it becomes a regular part of how you improve your system.


Getting Started

The Signal Engine is available today for all Shaped customers. For GBDT model policies, add a feature_definitions list to your engine config and you’re running. For agent context and retrieval workloads, signals are accessible through our Python, TypeScript, and SQL SDKs. When feature_definitions is omitted on a GBDT model, the engine generates a reasonable default: lookup signals for every numeric user and item column plus interaction count aggregations over 7-day and 30-day windows.

Full documentation is at docs.shaped.ai/docs/v2/engine_reference/signal-engine.

If you’re spending weeks on feature pipelines for ranking, search, or agent retrieval, we’d love to show you what it looks like when that drops to hours. Book a demo or sign up to try it yourself with $100 free credits. No credit card required.

Want a live walkthrough of this feature?

Book time with the team and we'll show you exactly how it works.

Book a demo →

Related Posts

$1.9M Funding Round
Apr 27, 2022
 | 
2

$1.9M Funding Round

10 Best Practices in Data Ingestion: A Scalable Framework for Real-Time, Reliable Pipelines
Jun 11, 2025
 | 
9

10 Best Practices in Data Ingestion: A Scalable Framework for Real-Time, Reliable Pipelines

5 Best APIs for Adding Personalized Recommendations to Your App in 2025
Aug 19, 2025
 | 
4

5 Best APIs for Adding Personalized Recommendations to Your App in 2025


Recommended for You

Recommended for You