Skip to content

feat: open-source global ProjectionV2 with sync/async event-driven execution#656

Open
dgafka wants to merge 4 commits intomainfrom
feat-open-source-globally-tracked-projection
Open

feat: open-source global ProjectionV2 with sync/async event-driven execution#656
dgafka wants to merge 4 commits intomainfrom
feat-open-source-globally-tracked-projection

Conversation

@dgafka
Copy link
Copy Markdown
Member

@dgafka dgafka commented Apr 5, 2026

Why is this change proposed?

ProjectionV2 is currently entirely gated behind an enterprise licence. Users who want globally-tracked projection that follows event store position cannot use it without purchasing a licence. This change makes the core projection capability available in open-source — giving users production-ready globally-tracked projections — while keeping scaling, operational, and deployment features as enterprise value-adds.

This will allow current Ecotone users to migrates from Projection(v1) to ProjectionV2 - which will allow in Ecotone 2.0 for complete removal of old projecting system.

Description of Changes

Open-source features (no licence required)

#[ProjectionV2('in_progress_tickets')]
#[FromStream(Ticket::class)]
class InProgressTicketList
{
    #[EventHandler]
    public function onTicketCreated(TicketCreated $event): void
    {
        // Write to read model
    }

    #[ProjectionInitialization]
    public function init(): void { /* CREATE TABLE ... */ }

    #[ProjectionDelete]
    public function delete(): void { /* DROP TABLE ... */ }

    #[ProjectionReset]
    public function reset(): void { /* DELETE FROM ... */ }
}

Also supported without licence:

  • Async event-driven via #[Asynchronous('channel')]
  • Multiple #[FromStream] / #[FromAggregateStream] on same projection
  • #[ProjectionExecution(eventLoadingBatchSize: 500)]
  • #[ProjectionBackfill] (sync only, no asyncChannelName)
  • #[ProjectionState] for stateful handlers
  • Event emission via EventStreamEmitter
  • Gap detection, locking, batch loading

Enterprise-only features (require licence)

// These attributes require enterprise licence:
#[Partitioned]           // Partition-based scaling
#[Streaming('channel')]  // Streaming channel consumption
#[Polling('endpoint')]   // Polling execution mode
#[ProjectionRebuild]     // Rebuild capability
#[ProjectionDeployment(manualKickOff: true, live: false)]  // Blue-green
#[ProjectionBackfill(asyncChannelName: 'backfill')]  // Async backfill

Custom implementations of #[StreamSource], #[StateStorage], #[PartitionProvider] also require enterprise licence.

Use case scenarios

  1. Read model projection — A team building a CQRS app needs a projection that maintains a denormalized read model from event-sourced aggregates. With this change, they can use #[ProjectionV2] + #[FromStream] out of the box.

  2. Multi-stream aggregation — A dashboard projection consuming events from multiple aggregate streams (e.g., Orders + Payments) works without licence using multiple #[FromStream] attributes.

  3. Scaling to production — When the team needs partition-based parallel processing, async rebuild, or blue-green deployment, they upgrade to enterprise.

Feature split diagram

flowchart TD
    PV2["#[ProjectionV2]"] --> OSCheck{Open-source eligible?}
    
    OSCheck -->|Global + sync/async event-driven| OS["Open Source ✓"]
    OSCheck -->|Partitioned / Streaming / Polling| ENT["Enterprise Required"]
    OSCheck -->|ProjectionRebuild / Deployment| ENT
    OSCheck -->|Async backfill| ENT
    OSCheck -->|Custom StreamSource / StateStorage| ENT
    
    OS --> Features["Lifecycle • Multi-stream • Backfill (sync)\nGap detection • Locking • Batch loading\nEvent emission • ProjectionState"]
Loading

Pull Request Contribution Terms

  • I have read and agree to the contribution terms outlined in CONTRIBUTING.

dgafka added 4 commits April 5, 2026 19:32
…ecution

Make globally-tracked (non-partitioned) projections available without
enterprise licence while keeping advanced features enterprise-only.
Do not pass ProjectingHeaders::PROJECTION_NAME to projection handler
methods without enterprise licence. This header enables blue-green
deployment scenarios and should remain enterprise-only.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant