Use when deciding which pgdbm pattern to use (standalone, dual-mode library, or shared pool) - provides decision tree based on deployment context without requiring doc exploration
Selects the optimal pgdbm pattern (standalone, dual-mode, or shared pool) based on your deployment context.
/plugin marketplace add juanre/pgdbm/plugin install pgdbm@juanre-ai-toolsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
Core Principle: Choose pattern based on deployment context and reusability needs.
pgdbm supports three main patterns. This skill helps you choose the right one in <30 seconds without reading multiple docs.
What are you building?
│
├─ Reusable library/package for PyPI?
│ └─ → DUAL-MODE LIBRARY pattern
│ • Accept connection_string OR db_manager
│ • Works standalone AND embedded
│
├─ Single application with multiple services/modules?
│ └─ → SHARED POOL pattern
│ • ONE pool, many schema-isolated managers
│ • Most efficient for production
│
└─ Simple standalone service/microservice?
└─ → STANDALONE pattern
• AsyncDatabaseManager(DatabaseConfig(...))
• Simplest setup
| If you have... | Use this pattern | Key indicator |
|---|---|---|
| Library published to PyPI | Dual-Mode | Code needs to work in someone else's app |
| FastAPI monolith with routers | Shared Pool | Multiple services, same process |
| Multiple services, same app | Shared Pool | Need connection efficiency |
| Background worker (separate process) | Standalone | Different OS process |
| Simple microservice | Standalone | One service, own database |
| Multi-tenant SaaS | Shared Pool | Many tenants, schema isolation |
Triggers:
Key characteristics:
{{tables.}}Red flags you need this:
import mylib in your READMEExample minimal setup:
class MyLibrary:
def __init__(
self,
connection_string: Optional[str] = None,
db_manager: Optional[AsyncDatabaseManager] = None,
):
if not connection_string and not db_manager:
raise ValueError("Provide one or the other")
self._external_db = db_manager is not None
self.db = db_manager
self._connection_string = connection_string
async def initialize(self):
if not self._external_db:
config = DatabaseConfig(connection_string=self._connection_string)
self.db = AsyncDatabaseManager(config)
await self.db.connect()
# ALWAYS run migrations
migrations = AsyncMigrationManager(
self.db, "migrations", module_name="mylib"
)
await migrations.apply_pending_migrations()
For complete implementation: See pgdbm:dual-mode-library skill
Triggers:
Key characteristics:
Red flags you need this:
AsyncDatabaseManager(DatabaseConfig(...)) in same appExample minimal setup:
# In lifespan
config = DatabaseConfig(connection_string="postgresql://...")
shared_pool = await AsyncDatabaseManager.create_shared_pool(config)
# Each service gets schema-isolated manager
users_db = AsyncDatabaseManager(pool=shared_pool, schema="users")
orders_db = AsyncDatabaseManager(pool=shared_pool, schema="orders")
# Run migrations for each
for db, path, name in [(users_db, "migrations/users", "users"), ...]:
migrations = AsyncMigrationManager(db, path, name)
await migrations.apply_pending_migrations()
For complete implementation: See pgdbm:shared-pool-pattern skill
Triggers:
Key characteristics:
Red flags you need this:
Example minimal setup:
config = DatabaseConfig(connection_string="postgresql://...")
db = AsyncDatabaseManager(config)
await db.connect()
migrations = AsyncMigrationManager(db, "migrations", module_name="myservice")
await migrations.apply_pending_migrations()
# Use db
user_id = await db.fetch_value(
"INSERT INTO {{tables.users}} (email) VALUES ($1) RETURNING id",
email
)
await db.disconnect()
For complete implementation: See pgdbm:standalone-service skill
Using Standalone but should use Shared Pool:
AsyncDatabaseManager(DatabaseConfig(...)) to same databasemax_connections limitUsing Shared Pool but should use Dual-Mode:
Using Dual-Mode but should use Standalone:
Question to ask: Same process or different process?
Answer: Each container = Standalone pattern
AsyncDatabaseManager(DatabaseConfig(...))Answer: Still use Dual-Mode if used by multiple apps
| Aspect | Standalone | Dual-Mode | Shared Pool |
|---|---|---|---|
| Complexity | Low | Medium | Medium |
| Flexibility | Low | High | Medium |
| Connection Efficiency | Low | Varies | High |
| Use Case | Simple services | Reusable libraries | Multi-service apps |
| Pool Creation | Creates own | Conditional | Uses provided |
| Migration Management | Owns | Always runs own | Each service runs own |
| Best For | Microservices, workers | PyPI packages | Monoliths, multi-tenant |
Scenario: "I'm building a FastAPI app with user authentication, blog posts, and comments"
Decision process:
Answer: Shared Pool Pattern
Why:
Before implementing, ask:
Who creates the database manager?
How many services need database access?
Will my code be imported by other projects?
Once you've chosen:
pgdbm:dual-mode-library for full implementationpgdbm:shared-pool-pattern for full implementationpgdbm:standalone-service for full implementationAll patterns use:
{{tables.}} syntax (mandatory)module_name in migrations (mandatory)Whatever pattern you choose, NEVER:
module_name in AsyncMigrationManagerdb.schema at runtimeThese violations break pgdbm's core assumptions.
Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
This skill should be used when the user asks to "create a hookify rule", "write a hook rule", "configure hookify", "add a hookify rule", or needs guidance on hookify rule syntax and patterns.