askill
create-snapshot

create-snapshotSafety 100Repository

Generates Snapshot pattern for PHP 8.4. Creates aggregate snapshot infrastructure for event sourcing performance optimization with configurable strategies and version tracking. Includes unit tests.

28 stars
1.2k downloads
Updated 2/21/2026

Package Files

Loading files...
SKILL.md

Snapshot Generator

Creates Snapshot infrastructure for optimizing event sourcing aggregate rebuilds.

When to Use

ScenarioExample
Long event streamsAggregates with 100+ events in their history
Slow aggregate rebuildEvent replay taking too long for read operations
Frequent readsAggregates loaded many times per second
Large aggregatesComplex state requiring many events to reconstruct

Component Characteristics

Snapshot

  • Immutable state capture of an aggregate at a point in time
  • Properties: aggregateId, aggregateType, version, state (JSON), createdAt
  • Supports fromArray() / toArray() for serialization
  • Version must be >= 1

SnapshotStoreInterface

  • save(Snapshot $snapshot): void — persist snapshot (upsert)
  • load(string $aggregateId): ?Snapshot — retrieve latest snapshot
  • delete(string $aggregateId): void — remove all snapshots for aggregate

SnapshotStrategy

  • Configurable event threshold (default: 100)
  • shouldTakeSnapshot(int $eventsSinceLastSnapshot): bool
  • Determines when a new snapshot should be captured

AggregateSnapshotter

  • Application service coordinating snapshot operations
  • Loads aggregate from snapshot + remaining events
  • Takes snapshots when strategy threshold is met

Generation Process

Step 1: Generate Domain Components

Path: src/Domain/{BC}/Snapshot/

  1. Snapshot.php — Immutable snapshot value object
  2. SnapshotStoreInterface.php — Repository interface for snapshot persistence

Step 2: Generate Application Components

Path: src/Application/{BC}/Snapshot/

  1. SnapshotStrategy.php — Configurable threshold strategy
  2. AggregateSnapshotter.php — Application service for snapshot operations

Step 3: Generate Infrastructure Components

Path: src/Infrastructure/{BC}/Snapshot/

  1. DoctrineSnapshotStore.php — Doctrine DBAL implementation of SnapshotStoreInterface
  2. Database migration SQL for snapshots table

Step 4: Generate Tests

  1. SnapshotTest.php — Construction, serialization, validation tests
  2. SnapshotStrategyTest.php — Threshold behavior tests
  3. AggregateSnapshotterTest.php — Load and take snapshot tests

File Placement

ComponentPath
Snapshot, SnapshotStoreInterfacesrc/Domain/{BC}/Snapshot/
SnapshotStrategy, AggregateSnapshottersrc/Application/{BC}/Snapshot/
DoctrineSnapshotStoresrc/Infrastructure/{BC}/Snapshot/
Unit Teststests/Unit/Domain/{BC}/Snapshot/, tests/Unit/Application/{BC}/Snapshot/

Naming Conventions

ComponentPatternExample
Value ObjectSnapshotSnapshot
Store InterfaceSnapshotStoreInterfaceSnapshotStoreInterface
StrategySnapshotStrategySnapshotStrategy
Application ServiceAggregateSnapshotterAggregateSnapshotter
Infrastructure StoreDoctrineSnapshotStoreDoctrineSnapshotStore
Test{ClassName}TestSnapshotTest

Quick Template Reference

Snapshot

final readonly class Snapshot
{
    public function __construct(
        public string $aggregateId,
        public string $aggregateType,
        public int $version,
        public string $state,
        public \DateTimeImmutable $createdAt
    ) {
        // version >= 1 validation
    }

    public static function fromArray(array $data): self;
    public function toArray(): array;
}

SnapshotStoreInterface

interface SnapshotStoreInterface
{
    public function save(Snapshot $snapshot): void;
    public function load(string $aggregateId): ?Snapshot;
    public function delete(string $aggregateId): void;
}

SnapshotStrategy

final readonly class SnapshotStrategy
{
    public function __construct(
        private int $eventThreshold = 100
    ) {}

    public function shouldTakeSnapshot(int $eventsSinceLastSnapshot): bool;
}

Usage Example

$snapshotter = new AggregateSnapshotter($snapshotStore, $strategy);

// Load aggregate from snapshot + remaining events
$result = $snapshotter->loadWithSnapshot($aggregateId, $eventStore);
$snapshot = $result['snapshot'];
$remainingEvents = $result['remainingEvents'];

$aggregate = $snapshot !== null
    ? Order::fromSnapshot($snapshot)
    : new Order($aggregateId);

foreach ($remainingEvents as $event) {
    $aggregate->apply($event);
}

// Take snapshot if threshold reached
$snapshotter->takeSnapshotIfNeeded(
    aggregateId: $aggregateId,
    aggregateType: 'Order',
    version: $aggregate->getVersion(),
    state: $aggregate->toSnapshot(),
    eventsSinceSnapshot: count($remainingEvents)
);

Database Schema

CREATE TABLE snapshots (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    aggregate_id VARCHAR(36) NOT NULL,
    aggregate_type VARCHAR(255) NOT NULL,
    version INT UNSIGNED NOT NULL,
    state JSON NOT NULL,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    UNIQUE INDEX idx_snapshots_aggregate_id (aggregate_id),
    INDEX idx_snapshots_aggregate_type (aggregate_type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

Anti-patterns to Avoid

Anti-patternProblemSolution
Snapshot Every EventStorage bloat, no performance gainUse threshold strategy (e.g., every 100 events)
Mutable SnapshotsState corruption, debugging nightmaresMake Snapshot immutable (final readonly)
Missing VersionCannot determine event replay start pointAlways track version in snapshot
No CleanupUnbounded storage growthImplement retention policy, keep only latest
Tight CouplingSnapshot tied to infrastructureDomain interface, infrastructure implementation
Skipping ValidationInvalid snapshots persistedValidate version >= 1, non-empty state

References

For complete PHP templates and examples, see:

  • references/templates.md — Snapshot, SnapshotStoreInterface, SnapshotStrategy, AggregateSnapshotter, DoctrineSnapshotStore templates
  • references/examples.md — OrderAggregate integration, event sourcing examples and tests

Install

Download ZIP
Requires askill CLI v1.0+

AI Quality Score

94/100Analyzed 2/24/2026

Comprehensive skill document for generating PHP 8.4 Snapshot pattern for event sourcing. Excellent structure with clear when-to-use scenarios, step-by-step generation process, code templates, naming conventions, database schema, and anti-patterns guidance. Well-organized with tables and code examples throughout. Located in dedicated skills folder, suggesting good reusability for PHP DDD projects.

100
95
85
95
95

Metadata

Licenseunknown
Version-
Updated2/21/2026
Publisherdykyi-roman

Tags

databasetesting