Skip to main content
@Pipeline defines a server-side aggregation pipeline sent to MongoDB when the Change Stream starts. Only matching events are transmitted over the network, reducing traffic and application load. The pipeline is evaluated once at stream startup — not per event.

Basic Usage

Annotate a method in your @ChangeStream class. At most one @Pipeline method per class. The method must take no parameters.

Supported Return Types

Combining with @Filter

@Pipeline can coexist with @Filter on the same @ChangeStream, forming a double funnel — pre-filter server-side, then refine with Java logic: The following example is from the PipelineFilterCapture sample — it pre-filters by operation type server-side, then checks the order status application-side:
Use @Pipeline to eliminate events you never need (reduce network traffic), then @Filter for logic that requires Spring beans, external service calls, or dynamic conditions.

Checkpoint Interaction

When @Pipeline is combined with @Checkpoint, FlowWarden’s dual-token model keeps restart fast.The pipeline filters events server-side, so only matching events ever reach FlowWarden. Each matching event advances the in-memory lastSeenToken tracker; the heartbeat timer (saveIntervalSeconds) persists it. On restart, the 3-level resume cascade starts at lastProcessedToken and falls back to lastSeenToken if the processed token has aged out of the oplog — which avoids a ChangeStreamHistoryLost failure on streams where the pipeline keeps the matching-event rate low.Keep saveIntervalSeconds > 0 to preserve cascade level 2. With saveIntervalSeconds = 0, only lastProcessedToken is persisted, so a long downtime on a pipeline-heavy stream can force escalation to onHistoryLost.

Oplog Internals and Limitations

Change Streams Cannot Use Indexes

MongoDB does not support creating indexes on the oplog. All Change Stream pipelines perform a sequential scan (COLLSCAN) of the oplog to evaluate your $match filters. This is a fundamental MongoDB limitation, not a FlowWarden one.

Pushdown-Eligible Fields

Not all filters are equal. Through empirical testing by the MongoDB community (this is not officially documented by MongoDB), only a handful of fields allow an optimized evaluation in the oplog scan:
Filtering on fullDocument fields (like fullDocument.status) forces MongoDB to deserialize and evaluate every oplog entry. This matters most during restarts, when MongoDB must scan the oplog forward from the resume token.

Best Practice: Layer Your Filters

Put pushdown-eligible filters first in your pipeline to reduce the number of entries that require full deserialization:

Performance Characteristics

  • Normal operation: No performance concern. MongoDB evaluates the pipeline on each new oplog entry as it arrives — there is no bulk scan of historical data.
  • At restart: MongoDB scans the oplog from the resume token forward. If the pipeline filters out most events, this scan can be slow — this is why FlowWarden’s dual-token checkpoint model exists.
  • Oplog retention: The oplog is a capped collection with a fixed size. If the application is down longer than the oplog retention window, the resume token expires and the stream cannot resume. Use @Checkpoint(onHistoryLost = ...) to handle this case.
MongoDB restricts which aggregation stages can be used in a Change Stream pipeline:Using an unsupported stage causes a MongoDB error at stream startup (fail-fast).

Constraints

See Also

@Filter

Application-side Java predicate filtering

Filtering Events

When to use @Pipeline vs @Filter

Checkpoint & Resume

How dual checkpoint interacts with @Pipeline

How it Works

Full event processing pipeline architecture