Skip to main content

Introduction

Deck by PromptPHP includes an optional database tracking system that logs prompt versions and execution data. This enables:
  • Performance monitoring — Track token usage, latency, and cost per prompt version.
  • A/B testing — Compare performance metrics across different prompt versions.
  • Audit trails — Record what was sent to and received from AI providers.
  • Cost analysis — Monitor API spending per prompt, model, and provider.
  • User feedback — Attach ratings and comments to individual executions.
Tracking is entirely optional and off by default. Deck works fully without it.
Prompt rendering never depends on tracking. If you enable it without running the migrations, or the database becomes unreachable, Deck falls back to metadata.json and logs a warning once rather than failing. Deck::track() never throws under any circumstances — it runs after a completed, paid-for AI call.

Setup

Publish and run the migrations before enabling the flag, or tracking has no tables to write to.

Publish and run the migrations

Enable tracking

Or set it directly in config/deck.php:

Database connection

By default, tracking uses your application’s default database connection. To store tracking data on a separate database:
The connection name must match a connection defined in config/database.php. If it does not, Deck logs a warning and falls back to metadata.json rather than failing.

Database schema

prompt_versions table

Stores prompt version records and tracks which version is active. Indexes:
  • Unique index on (name, version) — ensures no duplicate versions per prompt.
  • Index on (name, is_active) — fast lookups for the active version.

prompt_executions table

Logs individual prompt executions with performance data. Indexes:
  • Index on (prompt_name, prompt_version, created_at) — fast filtering by prompt and time range.
The prompt_executions table does not have an updated_at column. Records are insert-only.

Recording executions

Manual tracking

Use the Deck::track() method to record an execution manually:
All fields in the data array are optional. You can track as little or as much as you need:
If tracking is disabled in configuration, the track() method is a safe no-op — you can call it without checking configuration first.

Automatic tracking via middleware

When using the Laravel AI SDK integration, the TrackPromptMiddleware handles tracking automatically. See AI SDK — Performance Tracking Middleware for setup details.

Tracked fields

Eloquent models

Deck provides two Eloquent models for interacting with tracking data.

PromptVersion

PromptPHP\Deck\Models\PromptVersion Represents a prompt version record in the prompt_versions table.
Fillable attributes: name, version, system_prompt, user_prompt, metadata, is_active Casts:

PromptExecution

PromptPHP\Deck\Models\PromptExecution Represents an execution record in the prompt_executions table.
Fillable attributes: prompt_name, prompt_version, input, output, tokens, latency_ms, cost, model, provider, feedback Casts:
PromptExecution sets UPDATED_AT = null since execution records are insert-only and never updated.

Factories

Both models include factories for testing.

PromptVersionFactory

Available states:

PromptExecutionFactory

Available states:

Querying execution data

Basic queries

Performance analysis

A/B testing

Compare metrics across prompt versions:

Cost analysis

Version management via database

When tracking is enabled, Deck::activate() and prompt:activate record the active version in the prompt_versions table in addition to metadata.json, giving you a centralised, queryable record of version history.

Activation precedence

Once a version has been activated with tracking enabled, the database wins. metadata.json is consulted only when the table holds no record for that prompt. The practical consequence: editing active_version in metadata.json, committing it, and deploying will not change which version is served. Activation is environment state — it is how you promote a version in staging without touching production, and how you roll back without a deploy. The file is the bootstrap default, used until the first activation in that environment. To go back to file-based control for a prompt, delete its rows from prompt_versions.
The table only ever holds versions that have been activated. It is not a mirror of your prompt library — a version you have created but never activated has no row. The system_prompt and user_prompt columns are nullable and are written as NULL: Deck is file-based, and content lives on disk.