Back to Skills

database-best-practices

verified

Prisma ORM best practices for Shopify apps including multi-tenant data isolation, query optimization, transaction patterns, and migration strategies. Auto-invoked when working with database operations.

View on GitHub

Marketplace

shopify-development-toolkit

sarojpunde/shopify-dev-toolkit-claude-plugins

Plugin

shopify-pattern-enforcer

Repository

sarojpunde/shopify-dev-toolkit-claude-plugins
4stars

shopify-app-development/skills/database-best-practices/SKILL.md

Last Verified

January 21, 2026

Install Skill

Select agents to install to:

Scope:
npx add-skill https://github.com/sarojpunde/shopify-dev-toolkit-claude-plugins/blob/main/shopify-app-development/skills/database-best-practices/SKILL.md -a claude-code --skill database-best-practices

Installation paths:

Claude
.claude/skills/database-best-practices/
Powered by add-skill CLI

Instructions

# Database Best Practices Skill

## Purpose
Provides best practices and patterns for database operations in Shopify apps using Prisma ORM, focusing on data isolation, query optimization, and safe migrations.

## When This Skill Activates
- Working with Prisma schema or queries
- Creating database migrations
- Optimizing database performance
- Implementing multi-tenant data isolation
- Handling transactions

## Critical: Multi-Tenant Data Isolation

**ALWAYS filter by shopId** - This prevents data leaks between shops.

```typescript
// ✅ CORRECT - Always include shopId
const products = await db.product.findMany({
  where: {
    shopId: shop.id,
    status: "active",
  },
});

// ❌ WRONG - Missing shopId (data leak!)
const products = await db.product.findMany({
  where: { status: "active" },
});
```

## Core Patterns

### 1. Safe Query Pattern

```typescript
// Always filter by shopId for shop-specific data
async function getShopProducts(shopId: string) {
  return db.product.findMany({
    where: { shopId },
    select: {
      id: true,
      title: true,
      vendor: true,
      // Only select needed fields
    },
    take: 50,
    orderBy: { createdAt: "desc" },
  });
}
```

### 2. Pagination Pattern

```typescript
async function getPaginatedProducts(shopId: string, page: number = 1) {
  const pageSize = 50;
  const skip = (page - 1) * pageSize;

  const [products, totalCount] = await Promise.all([
    db.product.findMany({
      where: { shopId },
      skip,
      take: pageSize,
      orderBy: { createdAt: "desc" },
    }),
    db.product.count({
      where: { shopId },
    }),
  ]);

  return {
    products,
    totalCount,
    totalPages: Math.ceil(totalCount / pageSize),
    currentPage: page,
  };
}
```

### 3. Transaction Pattern

```typescript
// Use transactions for operations that must succeed/fail together
await db.$transaction(async (tx) => {
  // Update product
  await tx.product.update({
    where: { id: productId },
    data: { status: "synced" },

Validation Details

Front Matter
Required Fields
Valid Name Format
Valid Description
Has Sections
Allowed Tools
Instruction Length:
7736 chars