Claude Code Plugins

Community-maintained marketplace

Feedback

moai-platform-neon

@modu-ai/moai-adk
391
0

Neon serverless PostgreSQL specialist covering auto-scaling, database branching, PITR, and connection pooling. Use when building serverless apps needing PostgreSQL.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name moai-platform-neon
description Neon serverless PostgreSQL specialist covering auto-scaling, database branching, PITR, and connection pooling. Use when building serverless apps needing PostgreSQL.
version 1.0.0
category platform
tags neon, postgresql, serverless, branching, auto-scaling
context7-libraries /neondatabase/neon
related-skills moai-platform-supabase, moai-lang-typescript
allowed-tools Read, Write, Bash, Grep, Glob

moai-platform-neon: Neon Serverless PostgreSQL Specialist

Quick Reference (30 seconds)

Neon Serverless PostgreSQL Expertise: Specialized knowledge for Neon serverless PostgreSQL covering auto-scaling, scale-to-zero compute, database branching, Point-in-Time Recovery, and modern ORM integration.

Core Capabilities

Serverless Compute: Auto-scaling PostgreSQL with scale-to-zero for cost optimization Database Branching: Instant copy-on-write branches for dev, staging, and preview environments Point-in-Time Recovery: 30-day PITR with instant restore to any timestamp Connection Pooling: Built-in connection pooler for serverless and edge compatibility PostgreSQL 16: Full PostgreSQL 16 compatibility with extensions support

Quick Decision Guide

  • Need serverless PostgreSQL with auto-scaling? Neon
  • Need database branching for CI/CD? Neon branching
  • Need edge-compatible database? Neon with connection pooling
  • Need instant preview environments? Neon branch per PR

Context7 Library Mapping

Neon: /neondatabase/neon


Implementation Guide

Setup and Configuration

Package Installation:

npm install @neondatabase/serverless
npm install drizzle-orm  # Optional: Drizzle ORM
npm install @prisma/client prisma  # Optional: Prisma ORM

Environment Configuration:

# Direct connection (for migrations)
DATABASE_URL=postgresql://user:pass@ep-xxx.region.neon.tech/dbname?sslmode=require

# Pooled connection (for serverless/edge)
DATABASE_URL_POOLED=postgresql://user:pass@ep-xxx-pooler.region.neon.tech/dbname?sslmode=require

# Neon API for branching
NEON_API_KEY=neon_api_key_xxx
NEON_PROJECT_ID=project-xxx

Serverless Driver Usage

Basic Query Execution:

import { neon } from '@neondatabase/serverless'

const sql = neon(process.env.DATABASE_URL!)

// Simple query
const users = await sql`SELECT * FROM users WHERE active = true`

// Parameterized query (SQL injection safe)
const userId = 'user-123'
const user = await sql`SELECT * FROM users WHERE id = ${userId}`

// Transaction support
const result = await sql.transaction([
  sql`UPDATE accounts SET balance = balance - 100 WHERE id = ${fromId}`,
  sql`UPDATE accounts SET balance = balance + 100 WHERE id = ${toId}`
])

WebSocket Connection for Session Persistence:

import { Pool, neonConfig } from '@neondatabase/serverless'
import ws from 'ws'

// Required for Node.js environments
neonConfig.webSocketConstructor = ws

const pool = new Pool({ connectionString: process.env.DATABASE_URL })

// Use pool for session-based operations
const client = await pool.connect()
try {
  await client.query('BEGIN')
  await client.query('INSERT INTO logs (message) VALUES ($1)', ['Action'])
  await client.query('COMMIT')
} finally {
  client.release()
}

Database Branching

Branch Management API:

class NeonBranchManager {
  private apiKey: string
  private projectId: string
  private baseUrl = 'https://console.neon.tech/api/v2'

  constructor(apiKey: string, projectId: string) {
    this.apiKey = apiKey
    this.projectId = projectId
  }

  private async request(path: string, options: RequestInit = {}) {
    const response = await fetch(`${this.baseUrl}${path}`, {
      ...options,
      headers: {
        'Authorization': `Bearer ${this.apiKey}`,
        'Content-Type': 'application/json',
        ...options.headers
      }
    })
    if (!response.ok) throw new Error(`Neon API error: ${response.statusText}`)
    return response.json()
  }

  async createBranch(name: string, parentId: string = 'main') {
    return this.request(`/projects/${this.projectId}/branches`, {
      method: 'POST',
      body: JSON.stringify({
        branch: { name, parent_id: parentId }
      })
    })
  }

  async deleteBranch(branchId: string) {
    return this.request(`/projects/${this.projectId}/branches/${branchId}`, {
      method: 'DELETE'
    })
  }

  async listBranches() {
    return this.request(`/projects/${this.projectId}/branches`)
  }

  async getBranchConnectionString(branchId: string) {
    const endpoints = await this.request(
      `/projects/${this.projectId}/branches/${branchId}/endpoints`
    )
    return endpoints.endpoints[0]?.connection_uri
  }
}

Preview Branch for Pull Requests:

async function createPreviewEnvironment(prNumber: number) {
  const branchManager = new NeonBranchManager(
    process.env.NEON_API_KEY!,
    process.env.NEON_PROJECT_ID!
  )

  // Create branch from main
  const branch = await branchManager.createBranch(`pr-${prNumber}`, 'main')

  // Get connection string
  const connectionString = await branchManager.getBranchConnectionString(branch.branch.id)

  return {
    branchId: branch.branch.id,
    branchName: branch.branch.name,
    connectionString
  }
}

async function cleanupPreviewEnvironment(branchId: string) {
  const branchManager = new NeonBranchManager(
    process.env.NEON_API_KEY!,
    process.env.NEON_PROJECT_ID!
  )
  await branchManager.deleteBranch(branchId)
}

Point-in-Time Recovery

Restore to Specific Timestamp:

async function restoreToPoint(timestamp: Date) {
  const branchManager = new NeonBranchManager(
    process.env.NEON_API_KEY!,
    process.env.NEON_PROJECT_ID!
  )

  const response = await fetch(
    `https://console.neon.tech/api/v2/projects/${process.env.NEON_PROJECT_ID}/branches`,
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${process.env.NEON_API_KEY}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        branch: {
          name: `restore-${timestamp.toISOString().replace(/[:.]/g, '-')}`,
          parent_id: 'main',
          parent_timestamp: timestamp.toISOString()
        }
      })
    }
  )

  return response.json()
}

// Usage: Restore to 1 hour ago
const oneHourAgo = new Date(Date.now() - 60 * 60 * 1000)
const restoredBranch = await restoreToPoint(oneHourAgo)

Drizzle ORM Integration

Schema Definition:

// schema.ts
import { pgTable, uuid, text, timestamp, boolean, jsonb } from 'drizzle-orm/pg-core'

export const users = pgTable('users', {
  id: uuid('id').primaryKey().defaultRandom(),
  email: text('email').notNull().unique(),
  name: text('name'),
  createdAt: timestamp('created_at').defaultNow(),
  metadata: jsonb('metadata')
})

export const projects = pgTable('projects', {
  id: uuid('id').primaryKey().defaultRandom(),
  name: text('name').notNull(),
  ownerId: uuid('owner_id').references(() => users.id),
  isPublic: boolean('is_public').default(false),
  createdAt: timestamp('created_at').defaultNow()
})

Drizzle Client Setup:

// db.ts
import { neon } from '@neondatabase/serverless'
import { drizzle } from 'drizzle-orm/neon-http'
import * as schema from './schema'

const sql = neon(process.env.DATABASE_URL!)
export const db = drizzle(sql, { schema })

// Query examples
const allUsers = await db.select().from(schema.users)

const userProjects = await db
  .select()
  .from(schema.projects)
  .where(eq(schema.projects.ownerId, userId))
  .orderBy(desc(schema.projects.createdAt))

Prisma ORM Integration

Prisma Schema:

// schema.prisma
generator client {
  provider = "prisma-client-js"
  previewFeatures = ["driverAdapters"]
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model User {
  id        String    @id @default(uuid())
  email     String    @unique
  name      String?
  projects  Project[]
  createdAt DateTime  @default(now())
}

model Project {
  id        String   @id @default(uuid())
  name      String
  owner     User     @relation(fields: [ownerId], references: [id])
  ownerId   String
  isPublic  Boolean  @default(false)
  createdAt DateTime @default(now())
}

Prisma with Neon Serverless Driver:

// db.ts
import { Pool, neonConfig } from '@neondatabase/serverless'
import { PrismaNeon } from '@prisma/adapter-neon'
import { PrismaClient } from '@prisma/client'

neonConfig.webSocketConstructor = require('ws')

const pool = new Pool({ connectionString: process.env.DATABASE_URL })
const adapter = new PrismaNeon(pool)
export const prisma = new PrismaClient({ adapter })

// Query examples
const users = await prisma.user.findMany({
  include: { projects: true }
})

Advanced Patterns

Connection Pooling for Edge

Edge Function Configuration:

import { neon } from '@neondatabase/serverless'

// Use pooled connection for edge environments
const sql = neon(process.env.DATABASE_URL_POOLED!)

export const config = {
  runtime: 'edge'
}

export default async function handler(request: Request) {
  const users = await sql`SELECT id, name FROM users LIMIT 10`
  return Response.json(users)
}

CI/CD Branch Automation

GitHub Actions Integration:

name: Preview Environment

on:
  pull_request:
    types: [opened, synchronize, closed]

jobs:
  create-preview:
    if: github.event.action != 'closed'
    runs-on: ubuntu-latest
    steps:
      - name: Create Neon Branch
        id: create-branch
        run: |
          BRANCH=$(curl -s -X POST \
            -H "Authorization: Bearer ${{ secrets.NEON_API_KEY }}" \
            -H "Content-Type: application/json" \
            -d '{"branch":{"name":"pr-${{ github.event.number }}"}}' \
            "https://console.neon.tech/api/v2/projects/${{ secrets.NEON_PROJECT_ID }}/branches")
          echo "branch_id=$(echo $BRANCH | jq -r '.branch.id')" >> $GITHUB_OUTPUT

  cleanup-preview:
    if: github.event.action == 'closed'
    runs-on: ubuntu-latest
    steps:
      - name: Delete Neon Branch
        run: |
          curl -X DELETE \
            -H "Authorization: Bearer ${{ secrets.NEON_API_KEY }}" \
            "https://console.neon.tech/api/v2/projects/${{ secrets.NEON_PROJECT_ID }}/branches/pr-${{ github.event.number }}"

Auto-Scaling Configuration

Compute Settings via API:

async function configureAutoScaling(endpointId: string) {
  const response = await fetch(
    `https://console.neon.tech/api/v2/projects/${process.env.NEON_PROJECT_ID}/endpoints/${endpointId}`,
    {
      method: 'PATCH',
      headers: {
        'Authorization': `Bearer ${process.env.NEON_API_KEY}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        endpoint: {
          autoscaling_limit_min_cu: 0.25,  // Scale to zero
          autoscaling_limit_max_cu: 4,     // Max 4 compute units
          suspend_timeout_seconds: 300     // Suspend after 5 min idle
        }
      })
    }
  )
  return response.json()
}

Migration Workflow

Development to Production:

// Run migrations on direct connection (not pooled)
import { migrate } from 'drizzle-orm/neon-http/migrator'
import { neon } from '@neondatabase/serverless'
import { drizzle } from 'drizzle-orm/neon-http'

async function runMigrations() {
  // Use direct connection for migrations
  const sql = neon(process.env.DATABASE_URL!)
  const db = drizzle(sql)

  await migrate(db, { migrationsFolder: './drizzle' })
  console.log('Migrations completed')
}

Provider Decision Guide

When to Use Neon

Serverless Applications: Auto-scaling and scale-to-zero reduce costs Preview Environments: Instant branching enables per-PR databases Edge Deployment: Connection pooling works with edge runtimes Development Workflow: Branch from production for realistic dev data Cost Optimization: Pay only for active compute time

When to Consider Alternatives

Need Vector Search: Consider Supabase with pgvector Need Real-time Subscriptions: Consider Supabase or Convex Need NoSQL Flexibility: Consider Firestore or Convex Need Built-in Auth: Consider Supabase

Pricing Reference (2024)

Free Tier: 3GB storage, 100 compute hours per month Pro Tier: Usage-based pricing, additional storage and compute Scale-to-Zero: No charges during idle periods


Works Well With

  • moai-platform-supabase - Alternative when RLS or pgvector needed
  • moai-lang-typescript - TypeScript patterns for Drizzle and Prisma
  • moai-domain-backend - Backend architecture with database integration
  • moai-workflow-cicd - CI/CD pipeline integration patterns
  • moai-context7-integration - Latest Neon documentation access

Status: Production Ready Generated with: MoAI-ADK Skill Factory v2.0 Last Updated: 2025-12-07 Technology: Neon Serverless PostgreSQL