Migration Guide: Feature Flag Changes

This guide helps you migrate from Paladin versions before the feature flag reorganization (pre-v0.1.0) to the current version.

Table of Contents

Breaking Change Summary

The Change

Old Default Features (pre-v0.1.0):

default = ["redis-queue", "s3-storage", "openai-embeddings"]

New Default Features (v0.1.0+):

default = ["llm-openai"]

Impact

If you were relying on default features to provide:

  • ❌ Redis queue adapter (redis-queue)
  • ❌ S3/MinIO storage adapter (s3-storage)
  • ❌ OpenAI embeddings (openai-embeddings)

These are no longer enabled by default and must be explicitly added to your Cargo.toml.

Who Is Affected?

You are affected if:

  1. You use Redis queues in your code
  2. You use S3/MinIO file storage in your code
  3. You use OpenAI embeddings in your code
  4. Your Cargo.toml does NOT explicitly list features, relying only on:
    [dependencies]
    paladin = "0.x"  # No features = default features
    

You are NOT affected if:

  • ✅ You already explicitly list all required features in Cargo.toml
  • ✅ You only use core Paladin orchestration (agents, battalions)
  • ✅ You use features = ["full"] for development

Quick Fix

Add the old default features explicitly:

[dependencies]
paladin = { version = "0.1", features = ["llm-openai", "redis-queue", "s3-storage", "openai-embeddings"] }

This maintains exact functionality while being explicit about requirements.

Option 2: Use the full Feature (Development/Testing)

Enable all features:

[dependencies]
paladin = { version = "0.1", features = ["full"] }

Warning: This includes ALL optional features. For production, explicitly list only what you need.

Add only the features you actually use:

[dependencies]
# Example: Only need Redis queue
paladin = { version = "0.1", features = ["redis-queue"] }

# Example: Only need S3 storage
paladin = { version = "0.1", features = ["s3-storage"] }

# Example: Need both
paladin = { version = "0.1", features = ["redis-queue", "s3-storage"] }

Migration Scenarios

Scenario 1: Production API Server with Storage

Before:

[dependencies]
paladin = "0.x"  # Implicitly got redis-queue, s3-storage, openai-embeddings

After:

[dependencies]
paladin = { version = "0.1", features = ["llm-openai", "redis-queue", "s3-storage", "web-server"] }

Why: Explicitly declares infrastructure dependencies. Adds web-server if you use REST APIs.

Scenario 2: Content Processing Pipeline

Before:

[dependencies]
paladin = "0.x"

Your code uses:

  • PDF extraction
  • Web scraping
  • S3 storage
  • Redis queues

After:

[dependencies]
paladin = { version = "0.1", features = [
    "llm-openai",           # Default LLM provider
    "content-processing",   # PDF, scraping, RSS, tokenization
    "redis-queue",          # Async job queue
    "s3-storage"            # File storage
] }

Scenario 3: Multi-Provider Agent Orchestration

Before:

[dependencies]
paladin = "0.x"

Your code uses:

  • Multiple LLM providers (OpenAI, Anthropic, DeepSeek)
  • No storage or queues

After:

[dependencies]
paladin = { version = "0.1", default-features = false, features = ["llm-all"] }

Why: default-features = false removes the default llm-openai, then llm-all adds all providers.

Scenario 4: Microservice with Notifications

Before:

[dependencies]
paladin = "0.x"

Your code uses:

  • Email notifications
  • Web API
  • S3 storage

After:

[dependencies]
paladin = { version = "0.1", features = [
    "llm-openai",      # LLM provider
    "web-server",      # REST API
    "notifications",   # Email with templates
    "s3-storage"       # File storage
] }

Scenario 5: Development Environment

Before:

[dependencies]
paladin = "0.x"

[dev-dependencies]
# Additional test deps...

After:

[dependencies]
# Production - minimal features
paladin = { version = "0.1", features = ["llm-openai", "redis-queue"] }

[dev-dependencies]
# Development - all features for testing
paladin = { version = "0.1", features = ["full"] }

What Changed

Feature Flag Reorganization

CategoryOld BehaviorNew Behavior
Default Featuresredis-queue, s3-storage, openai-embeddingsllm-openai only
LLM ProvidersImplicit (always included)Explicit flags: llm-openai, llm-anthropic, llm-deepseek
Content ProcessingAlways includedcontent-processing flag gates pdf-extract, scraper, etc.
Web ServerAlways includedweb-server flag gates actix-web, axum
NotificationsAlways includednotifications flag gates lettre, handlebars
VisionImplicitvision flag for multimodal capabilities

New Convenience Flags

FlagEquivalent ToPurpose
llm-allllm-openai + llm-anthropic + llm-deepseekAll LLM providers
fullAll optional featuresDevelopment/testing

Why This Change

Benefits

  1. Smaller Binaries - Default build is ~40% smaller (10-14 MB vs 25-35 MB)
  2. Faster Compile Times - Default build compiles ~60% faster (40-60s vs 3-5 min)
  3. Clearer Dependencies - Explicit about what your application actually uses
  4. Better Modularity - Pick only the LLM providers you need
  5. Security - Smaller attack surface by excluding unused dependencies

Philosophy

Old Approach: "Include everything by default, users opt-out if needed"

  • ❌ Slow compilation for simple use cases
  • ❌ Large binaries even for minimal deployments
  • ❌ Unclear what features are actually required

New Approach: "Start minimal, opt-in to what you need"

  • ✅ Fast iteration for core orchestration development
  • ✅ Explicit about infrastructure dependencies
  • ✅ Production builds include only necessary code

Testing Your Migration

Step 1: Update Cargo.toml

Apply one of the migration scenarios above.

Step 2: Verify Compilation

# Clean build to ensure no cached artifacts
cargo clean

# Build with your new features
cargo build

# Check for missing features (look for errors like):
# error[E0433]: failed to resolve: use of undeclared crate or module `redis`

Step 3: Run Tests

# Run all tests with your feature set
cargo test

# If you have integration tests requiring services:
cargo test --features integration-tests

Step 4: Check for Warnings

# Ensure no clippy warnings about unused dependencies
cargo clippy --all-targets -- -D warnings

Step 5: Verify Runtime Behavior

Test critical paths that use:

  • Redis queues (if using redis-queue)
  • S3 storage (if using s3-storage)
  • Email notifications (if using notifications)
  • Web APIs (if using web-server)

Common Migration Errors

Error 1: Unresolved Import

error[E0432]: unresolved import `paladin::infrastructure::adapters::queue::redis`

Cause: Missing redis-queue feature

Fix:

paladin = { version = "0.1", features = ["redis-queue"] }

Error 2: Missing Adapter Struct

error[E0433]: failed to resolve: use of undeclared type `MinioAdapter`

Cause: Missing s3-storage feature

Fix:

paladin = { version = "0.1", features = ["s3-storage"] }

Error 3: Content Type Detection Missing

error[E0425]: cannot find function `detect_content_type` in this scope

Cause: Missing s3-storage feature (function is feature-gated)

Fix:

paladin = { version = "0.1", features = ["s3-storage"] }

Error 4: PDF Extraction Failed

error[E0433]: failed to resolve: use of undeclared crate `pdf_extract`

Cause: Missing content-processing feature

Fix:

paladin = { version = "0.1", features = ["content-processing"] }

Rollback Plan

If you need to temporarily revert to old behavior while planning migration:

Option 1: Pin to Old Version

[dependencies]
paladin = "0.0.x"  # Use specific pre-v0.1.0 version

Check available versions:

cargo search paladin

Option 2: Use Full Features

[dependencies]
paladin = { version = "0.1", features = ["full"] }

This includes everything and more, allowing time for proper migration planning.

Getting Help

Documentation

Support Channels

Example Migration PRs

See these example PRs for migration patterns:

Checklist

Use this checklist to track your migration:

  • Read this migration guide
  • Identify which features your code uses
  • Update Cargo.toml with explicit features
  • Run cargo clean && cargo build
  • Run cargo test
  • Run cargo clippy --all-targets -- -D warnings
  • Test critical runtime paths
  • Update CI/CD workflows if needed
  • Document feature requirements in your README
  • Deploy to staging and verify
  • Deploy to production

Timeline

VersionStatusDefault Features
< 0.1.0Oldredis-queue, s3-storage, openai-embeddings
0.1.0Currentllm-openai only
FuturePlannedMay add more granular LLM provider features

Feedback

This migration guide is a living document. If you encounter migration scenarios not covered here, please:

  1. Open a GitHub issue describing your use case
  2. Submit a PR to add your scenario to this guide
  3. Share your experience in GitHub Discussions

Your feedback helps improve Paladin for everyone! 🛡️


CLI Feature Isolation (Milestone 4 — Epic 3)

What Changed

The application::cli module and the paladin-cli binary are now gated behind the cli feature flag. The following dependencies are now optional and only compiled when cli is enabled:

  • clap (CLI argument parsing)
  • dialoguer (interactive prompts)
  • indicatif (progress bars)
  • console (terminal styling)
  • serde_yaml (YAML config parsing)

Who Is Affected?

Library consumers: No impact. The cli feature was never part of the default feature set. Library builds are unaffected.

paladin-cli binary users: The binary now requires --features cli to compile:

# Before (always compiled):
cargo build --bin paladin-cli

# After (requires cli feature):
cargo build --bin paladin-cli --features cli

full feature users: No change — full already includes cli.

Migration

If you directly import from paladin::application::cli (uncommon — internal use only):

# Cargo.toml — add the cli feature
[dependencies]
paladin = { version = "0.1", features = ["cli"] }

Or add cli to your own feature re-export:

[features]
my-cli = ["paladin/cli"]