Storage Backends
ducto abstracts storage behind the CreditStore interface. Three built-in implementations plus custom adapters.
Comparison
| Store | Dependencies | Use Case |
|---|---|---|
MemoryStore | None | Testing, development |
HttpxSupabaseStore | httpx (Python) / native fetch (JS) | Production (Supabase) |
PostgresStore | psycopg (Python) / pg (JS) | Production (direct PostgreSQL) |
CreditStore Interface
The CreditStore ABC/interface defines all operations. Implementations exist for Memory, Postgres, and Supabase.
| Category | Methods |
|---|---|
| Balances | get_balance, add_credits, reserve_credits, deduct_credits |
| Pricing | get_active_pricing, set_active_pricing |
| Plans | get_user_plan, set_user_plan, check_allowance, increment_usage_window |
| Spend caps | check_spend_cap |
| Refunds | refund_credits |
| Expiry | sweep_expired_credits |
| Analytics | spend_by_user, spend_by_model, top_users, daily_spend, aggregate_stats |
| Teams | create_team, get_team_balance, add_team_member, get_team_members, deduct_team |
| Setup | setup |
SQL Migrations
Ten bundled SQL files create the required schema:
| File | Creates |
|---|---|
001_credit_tables.sql | user_credits, credit_transactions, credit_reservations tables, RLS policies, signup bonus trigger |
002_credit_rpcs.sql | Core RPCs: credits_add, reserve_credits, deduct_credits, get_credits_balance |
003_pricing_config.sql | credit_pricing_config table, get/set RPCs |
004_user_plans.sql | credit_plans, credit_usage_window tables, plan RPCs |
005_credit_refunds.sql | refund_credits RPC with duplicate detection and partial refunds |
006_credit_expiry.sql | expire_credits RPC with dry-run support |
007_usage_analytics.sql | spend_by_user, spend_by_model, top_users, daily_spend RPCs |
008_team_balances.sql | credit_teams, credit_team_members tables, team RPCs |
009_spend_caps.sql | credit_spend_caps table, check_spend_cap RPC |
010_aggregate_stats.sql | aggregate_stats RPC returning JSON |
All DDL is idempotent (IF NOT EXISTS / CREATE OR REPLACE).
Run via CLI:
ducto migrate "postgresql://user:pass@host:5432/db"
Or from code:
from ducto.interface.supabase import run_migrations
result = run_migrations("postgresql://user:pass@host:5432/db")