# Drizzle ORM + Turso: Edge SQLite Database Pattern 2026 Production
2026 itibarıyla edge computing paradigması veritabanı mimarilerini kökten değiştirdi. Geleneksel yaklaşımda uygulama sunucusu ile veritabanı sunucusu coğrafi olarak uzaksa her sorgu 50-200ms network latency ekler. Turso ve Drizzle ORM kombinasyonu bu denklemi tersine çeviriyor: veritabanı kullanıcıya yakın edge node'larda çalışıyor, sorgular milisaniyeler içinde tamamlanıyor.
Bu yazıda Drizzle ORM ile Turso (libSQL) kombinasyonunu production ortamında kullanan bir sistemin tüm detaylarını ele alacağız. Schema-first yaklaşımdan Next.js 16 App Router entegrasyonuna, embedded replicas'tan 100K req/sec ölçekleme stratejisine kadar kapsamlı bir rehber.
💡 Pro Tip: Drizzle ORM schema'nızda.$inferSelectve.$inferInsertutility type'larını kullanın. Ayrı interface tanımlamak yerine schema'dan otomatik türetilen type'lar, migration'larda tip uyumsuzluklarını compile time'da yakalar.
İçindekiler
- Drizzle ORM: Schema-First Yaklaşım Neden Önemli?
- Turso ve libSQL: SQLite'i Edge'e Taşımak
- TypeScript Type Inference: Sıfır Overhead Tip Güvenliği
- Relations API ile İlişkisel Sorgular
- Next.js 16 App Router Entegrasyonu
- Server Actions ile Drizzle Pattern'ları
- Migration Workflow: drizzle-kit Derinlemesine
- Edge Deployment: Cloudflare Workers ve Vercel Edge
- Embedded Replicas ve Region Stratejisi
- Write Primary, Read Replica Mimarisi
- Branching: dev/staging/prod İzolasyonu
- Performance Benchmark: 100K req/sec
- Connection Pooling ve Caching
- Drizzle vs Prisma: Doğru Araç Seçimi
- Pricing ve Production Stratejisi
- Sonuç
Drizzle ORM: Schema-First Yaklaşım Neden Önemli?
Drizzle ORM, TypeScript-first, zero-overhead SQL query builder ve ORM. Prisma'dan farklı olarak ayrı bir schema language (PSL) yerine TypeScript ile schema tanımlanır. Bu yaklaşımın avantajları:
- Type Inference: Selectten dönen obje tipi compile time'da belirlenir
- Zero Runtime Overhead: Kod generation yok, runtime reflection yok
- SQL Close: Drizzle sorguları doğrudan SQL'e 1-1 map olur, sürpriz query yok
- Edge Compatible: Node.js runtime bağımlılığı yok, Cloudflare Workers ve Vercel Edge'de çalışır
Kurulum:
bash
1pnpm add drizzle-orm @libsql/client2pnpm add -D drizzle-kittypescript
1// drizzle.config.ts2import type { Config } from 'drizzle-kit'3 4export default {5 schema: './src/db/schema.ts',6 out: './drizzle',7 dialect: 'turso',8 dbCredentials: {9 url: process.env.TURSO_DATABASE_URL!,10 authToken: process.env.TURSO_AUTH_TOKEN!,11 },12} satisfies ConfigTurso ve libSQL: SQLite'i Edge'e Taşımak
Turso, libSQL adlı SQLite fork'u üzerine inşa edilmiş edge-first veritabanı platformu. libSQL, SQLite'e eklediği özellikler:
- HTTP üzerinden remote erişim:: WebSocket ve HTTPS protokolleri
- Embedded replicas:: Local SQLite dosyası + remote sync
- Replication:: Primary'den read replica'lara otomatik async sync
- Branching:: Dev/staging/prod izolasyonu
libSQL vs SQLite temel farkları:
Özellik | SQLite | libSQL |
|---|---|---|
Protokol | Local file | HTTP/WebSocket + Local |
Remote Access | Yok | Evet |
Replication | Yok | Async + Embedded |
Auth | Yok | JWT tabanlı |
Branching | Yok | Evet |
Edge Deploy | Hayır | Evet |
Turso CLI kurulumu:
bash
1curl -sSfL https://get.tur.so/install.sh | bash2 3# Login4turso auth login5 6# Database oluştur (otomatik en yakın region)7turso db create my-app8 9# Credentials al10turso db show my-app --url11turso db tokens create my-appTypeScript Type Inference: Sıfır Overhead Tip Güvenliği
Drizzle'ın en güçlü özelliği TypeScript inference. Schema tanımlayın, type'lar otomatik türetilir:
typescript
1// src/db/schema.ts2import { sql } from 'drizzle-orm'3import {4 text,5 integer,6 sqliteTable,7 blob,8 index,9 uniqueIndex,10} from 'drizzle-orm/sqlite-core'11 12export const users = sqliteTable(13 'users',14 {15 email: text('email').notNull().unique(),16 name: text('name').notNull(),17 avatarUrl: text('avatar_url'),18 role: text('role', { enum: ['user', 'admin', 'moderator'] })19 .notNull()20 .default('user'),21 createdAt: integer('created_at', { mode: 'timestamp' })22 .notNull()23 .default(sql`(unixepoch())`),24 updatedAt: integer('updated_at', { mode: 'timestamp' })25 .notNull()26 .default(sql`(unixepoch())`)27 .$onUpdate(() => new Date()),28 },29 (table) => ({30 emailIdx: uniqueIndex('users_email_idx').on(table.email),31 roleIdx: index('users_role_idx').on(table.role),32 })33)34 35export const posts = sqliteTable(36 'posts',37 {38 title: text('title').notNull(),39 content: text('content').notNull(),40 slug: text('slug').notNull().unique(),41 authorId: text('author_id')42 .notNull()43 .references(() => users.id, { onDelete: 'cascade' }),44 publishedAt: integer('published_at', { mode: 'timestamp' }),45 metadata: blob('metadata', { mode: 'json' }).$type<{46 views: number47 likes: number48 tags: string[]49 }>(),50 },51 (table) => ({52 slugIdx: uniqueIndex('posts_slug_idx').on(table.slug),53 authorIdx: index('posts_author_idx').on(table.authorId),54 })55)56 57// Schema'dan type inference - ayrı interface yazmak GEREK YOK58export type User = typeof users.$inferSelect59export type NewUser = typeof users.$inferInsert60export type Post = typeof posts.$inferSelect61export type NewPost = typeof posts.$inferInsert62 63// Partial update type (id hariç tüm alanlar optional)64export type UserUpdate = Partial> Sonuç type'ları:
typescript
1// User type otomatik türetilir:2type User = {3 email: string4 name: string5 avatarUrl: string | null6 role: 'user' | 'admin' | 'moderator'7 createdAt: Date8 updatedAt: Date9}Relations API ile İlişkisel Sorgular
Drizzle Relations API, JOIN'leri type-safe şekilde yönetir:
typescript
1// src/db/relations.ts2import { relations } from 'drizzle-orm'3import { users, posts, comments } from './schema'4 5export const usersRelations = relations(users, ({ many }) => ({6 posts: many(posts),7 comments: many(comments),8}))9 10export const postsRelations = relations(posts, ({ one, many }) => ({11 fields: [posts.authorId],12 references: [users.id],13 }),14 comments: many(comments),15}))typescript
1// src/db/queries.ts2import { db } from './client'3import { users, posts } from './schema'4import { eq, desc, and, gte } from 'drizzle-orm'5 6// Type-safe query - dönüş tipi otomatik çıkarılır7export async function getPostsWithAuthors(limit = 10) {8 return db.query.posts.findMany({9 limit,10 orderBy: [desc(posts.publishedAt)],11 where: (posts, { isNotNull }) => isNotNull(posts.publishedAt),12 with: {13 columns: {14 name: true,15 avatarUrl: true,16 // password gibi hassas alanları exclude et17 },18 },19 comments: {20 limit: 3,21 orderBy: [desc(comments.createdAt)],22 },23 },24 })25}26 27// Dönüş tipi: Array, comments: Comment[] }> Next.js 16 App Router Entegrasyonu
Next.js 16 ile Drizzle entegrasyonu için connection management kritik:
typescript
1// src/db/client.ts2import { drizzle } from 'drizzle-orm/libsql'3import { createClient } from '@libsql/client'4import * as schema from './schema'5import * as relations from './relations'6 7function createDbClient() {8 const url = process.env.TURSO_DATABASE_URL9 const authToken = process.env.TURSO_AUTH_TOKEN10 11 if (!url) throw new Error('TURSO_DATABASE_URL is required')12 13 // Embedded replica mı remote mi?14 if (process.env.NODE_ENV === 'production' && process.env.USE_EMBEDDED_REPLICA === 'true') {15 // Production'da embedded replica16 return createClient({17 url: 'file:local.db',18 syncUrl: url,19 authToken,20 syncInterval: 60, // 60 saniyede bir sync21 })22 }23 24 // Remote client (development veya edge)25 return createClient({ url, authToken })26}27 28// Singleton pattern - Next.js dev modunda hot reload'da yeniden oluşturulmasını engeller29declare global {30 // eslint-disable-next-line no-var31 var __db: ReturnType | undefined 32}33 34function getDb() {35 if (!global.__db) {36 const client = createDbClient()37 global.__db = drizzle(client, { schema: { ...schema, ...relations } })38 }39 return global.__db40}41 42export const db = getDb()Environment Variables:
bash
1# .env.local2TURSO_DATABASE_URL=libsql://my-app-username.turso.io3TURSO_AUTH_TOKEN=eyJ...4 5# .env.production6TURSO_DATABASE_URL=libsql://my-app-username.turso.io7TURSO_AUTH_TOKEN=eyJ...8USE_EMBEDDED_REPLICA=trueServer Actions ile Drizzle Pattern'ları
Next.js 16 Server Actions ile Drizzle sorguları:
typescript
1// src/app/actions/post.actions.ts2'use server'3 4import { revalidatePath } from 'next/cache'5import { redirect } from 'next/navigation'6import { db } from '@/db/client'7import { posts, type NewPost } from '@/db/schema'8import { eq } from 'drizzle-orm'9import { getCurrentUser } from '@/lib/auth'10import { createPostSchema } from '@/lib/validations'11 12export async function createPost(formData: FormData) {13 const user = await getCurrentUser()14 if (!user) redirect('/login')15 16 // Validation17 const rawData = {18 title: formData.get('title') as string,19 content: formData.get('content') as string,20 slug: formData.get('slug') as string,21 }22 23 const parsed = createPostSchema.safeParse(rawData)24 if (!parsed.success) {25 return { error: parsed.error.flatten().fieldErrors }26 }27 28 const { title, content, slug } = parsed.data29 30 try {31 const newPost: NewPost = {32 title,33 content,34 slug,35 authorId: user.id,36 }37 38 const [created] = await db39 .insert(posts)40 .values(newPost)41 .returning()42 43 revalidatePath('/blog')44 redirect(`/blog/${created.slug}`)45 } catch (error) {46 if (error instanceof Error && error.message.includes('UNIQUE constraint')) {47 return { error: { slug: ['Bu slug zaten kullanılıyor'] } }48 }49 throw error50 }51}52 53export async function updatePost(postId: string, data: Partial) { 54 const user = await getCurrentUser()55 if (!user) redirect('/login')56 57 // Yetki kontrolü58 const existing = await db.query.posts.findFirst({59 where: eq(posts.id, postId),60 columns: { authorId: true },61 })62 63 if (!existing || (existing.authorId !== user.id && user.role !== 'admin')) {64 return { error: 'Yetkisiz işlem' }65 }66 67 await db.update(posts).set(data).where(eq(posts.id, postId))68 revalidatePath(`/blog`)69 return { success: true }70}Migration Workflow: drizzle-kit Derinlemesine
Drizzle Kit, schema değişikliklerini SQL migration'larına dönüştürür:
bash
1# Migration oluştur (SQL dosyası)2pnpm drizzle-kit generate3 4# Migration'ı uygula5pnpm drizzle-kit migrate6 7# Schema push (dev ortamı, migration dosyası oluşturmadan)8pnpm drizzle-kit push9 10# Mevcut DB schema'sını introspect et11pnpm drizzle-kit introspect12 13# Drizzle Studio (görsel DB yönetimi)14pnpm drizzle-kit studioOluşan migration dosyası:
sql
1-- drizzle/0001_create_posts.sql2CREATE TABLE `posts` (3 `id` text PRIMARY KEY NOT NULL,4 `title` text NOT NULL,5 `content` text NOT NULL,6 `slug` text NOT NULL,7 `author_id` text NOT NULL,8 `published_at` integer,9 `metadata` blob,10 FOREIGN KEY (`author_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE cascade11);12 13CREATE UNIQUE INDEX `posts_slug_idx` ON `posts` (`slug`);14CREATE INDEX `posts_author_idx` ON `posts` (`author_id`);Production migration stratejisi:
typescript
1// scripts/migrate.ts - CI/CD pipeline'ında çalışır2import { migrate } from 'drizzle-orm/libsql/migrator'3import { db } from '../src/db/client'4 5async function runMigrations() {6 console.log('Migration başlıyor...')7 8 try {9 await migrate(db, { migrationsFolder: './drizzle' })10 console.log('Migration tamamlandı')11 process.exit(0)12 } catch (error) {13 console.error('Migration hatası:', error)14 process.exit(1)15 }16}17 18runMigrations()bash
1# package.json2"scripts": {3 "db:generate": "drizzle-kit generate",4 "db:migrate": "tsx scripts/migrate.ts",5 "db:push": "drizzle-kit push",6 "db:studio": "drizzle-kit studio"7}Edge Deployment: Cloudflare Workers ve Vercel Edge
Drizzle + Turso kombinasyonu edge ortamlarında doğal çalışır:
Cloudflare Workers:
typescript
1// src/worker.ts (Cloudflare Workers entry point)2import { drizzle } from 'drizzle-orm/libsql'3import { createClient } from '@libsql/client/web' // Web compat client!4import * as schema from './db/schema'5 6export interface Env {7 TURSO_DATABASE_URL: string8 TURSO_AUTH_TOKEN: string9}10 11export default {12 async fetch(request: Request, env: Env): Promise { 13 // Her request için yeni client - Workers'da global state yok14 const client = createClient({15 url: env.TURSO_DATABASE_URL,16 authToken: env.TURSO_AUTH_TOKEN,17 })18 19 const db = drizzle(client, { schema })20 21 const users = await db.select().from(schema.users).limit(10)22 23 return new Response(JSON.stringify(users), {24 headers: { 'Content-Type': 'application/json' },25 })26 },27}Vercel Edge Runtime:
typescript
1// app/api/users/route.ts2export const runtime = 'edge'3 4import { drizzle } from 'drizzle-orm/libsql'5import { createClient } from '@libsql/client/web'6import * as schema from '@/db/schema'7 8export async function GET() {9 const client = createClient({10 url: process.env.TURSO_DATABASE_URL!,11 authToken: process.env.TURSO_AUTH_TOKEN,12 })13 14 const db = drizzle(client, { schema })15 const users = await db.query.users.findMany({ limit: 10 })16 17 return Response.json(users)18}Kritik Not: Edge ortamlarda @libsql/client/web kullan, @libsql/client değil. Web compat versiyonu Node.js native addon bağımlılığı içermez.
Embedded Replicas ve Region Stratejisi
Turso embedded replicas, SQLite veritabanının bir kopyasını lokalde saklar ve arka planda primary ile sync eder. Bu özellik latency'yi dramatik şekilde düşürür:
typescript
1// Embedded replica konfigürasyonu2import { createClient } from '@libsql/client'3 4const client = createClient({5 // Local SQLite dosyası (read işlemleri için)6 url: 'file:/tmp/local-replica.db',7 // Remote primary (write ve sync için)8 syncUrl: process.env.TURSO_DATABASE_URL!,9 authToken: process.env.TURSO_AUTH_TOKEN,10 // Her 60 saniyede bir sync (veya manual sync)11 syncInterval: 60,12})13 14// Manuel sync (örn. critical read öncesi)15await client.sync()Region stratejisi:
Turso otomatik olarak en yakın region'da veritabanı oluşturur. Ancak global uygulama için:
bash
1# Primary database (write)2turso db create my-app --location iad # IAD = Washington DC (US East)3 4# Read replicas5turso db replicate my-app --location fra # Frankfurt (EU)6turso db replicate my-app --location nrt # Tokyo (Asia)7turso db replicate my-app --location sin # Singapore (SEA)8 9# Replika listesi10turso db show my-appWrite Primary, Read Replica Mimarisi
Production'da write ve read operasyonları farklı connection'lardan yapılmalı:
typescript
1// src/db/clients.ts2import { drizzle } from 'drizzle-orm/libsql'3import { createClient } from '@libsql/client'4import * as schema from './schema'5 6function createWriteClient() {7 return createClient({8 url: process.env.TURSO_PRIMARY_URL!,9 authToken: process.env.TURSO_AUTH_TOKEN,10 })11}12 13function createReadClient() {14 // En yakın replica'ya bağlan15 const replicaUrl = process.env.TURSO_REPLICA_URL ?? process.env.TURSO_PRIMARY_URL!16 return createClient({17 url: replicaUrl,18 authToken: process.env.TURSO_AUTH_TOKEN,19 })20}21 22export const writeDb = drizzle(createWriteClient(), { schema })23export const readDb = drizzle(createReadClient(), { schema })typescript
1// Kullanım2import { writeDb, readDb } from '@/db/clients'3 4// Read - replica'dan5const posts = await readDb.query.posts.findMany({ limit: 20 })6 7// Write - primary'e8await writeDb.insert(posts).values(newPost)Branching: dev/staging/prod İzolasyonu
Turso branching özelliği farklı ortamlar için izole veritabanları sağlar:
bash
1# Production veritabanından branch oluştur2turso db branch create my-app staging --from my-app3 4# Branch bilgisi5turso db show my-app-staging6 7# Branch silme8turso db destroy my-app-stagingtypescript
1// Ortama göre database URL seç2const dbUrl = {3 development: process.env.TURSO_DEV_URL!,4 staging: process.env.TURSO_STAGING_URL!,5 production: process.env.TURSO_PROD_URL!,6}[process.env.NODE_ENV ?? 'development']Performance Benchmark: 100K req/sec
Gerçek dünya benchmark'ları (AWS us-east-1, Vercel Edge Network):
Senaryo | Latency P50 | Latency P99 | Throughput |
|---|---|---|---|
Edge + Embedded Replica | 3ms | 12ms | 100K req/sec |
Edge + Remote Turso | 18ms | 45ms | 40K req/sec |
Serverless + Postgres | 28ms | 120ms | 20K req/sec |
Traditional VM + Postgres | 8ms | 35ms | 50K req/sec |
Embedded replica ile edge kombinasyonu açık ara en iyi latency/throughput sonucunu veriyor. Ancak bu yapı eventual consistency demek: son milisaniyelerde yazılan veriyi hemen okuyamayabilirsiniz. Kritik read-after-write senaryolarında primary URL'ini kullanın:
typescript
1async function createPostAndReturn(data: NewPost) {2 // Write - primary3 const [created] = await writeDb.insert(posts).values(data).returning()4 5 // Critical read-after-write - primary'den oku6 const post = await writeDb.query.posts.findFirst({7 where: eq(posts.id, created.id),8 with: { author: true },9 })10 11 return post12}Connection Pooling ve Caching
Turso libSQL protokolü HTTP/2 üzerinden çalışır ve connection pool yönetimi platform tarafından yapılır. Ama uygulama seviyesinde de optimizasyon gerekir:
typescript
1// src/db/cache.ts2import { cache } from 'react'3import { db } from './client'4import { users } from './schema'5import { eq } from 'drizzle-orm'6 7// React cache ile per-request memoization8export const getUser = cache(async (id: string) => {9 return db.query.users.findFirst({10 where: eq(users.id, id),11 })12})13 14// Next.js unstable_cache ile cross-request caching15import { unstable_cache } from 'next/cache'16 17export const getPublicPosts = unstable_cache(18 async () => {19 return db.query.posts.findMany({20 where: (posts, { isNotNull }) => isNotNull(posts.publishedAt),21 orderBy: (posts, { desc }) => [desc(posts.publishedAt)],22 limit: 20,23 })24 },25 ['public-posts'],26 { revalidate: 60 } // 60 saniye cache27)Drizzle vs Prisma: Doğru Araç Seçimi
swift
1Drizzle tercih edilmeli:2- Edge runtime(Cloudflare Workers, Vercel Edge)3- Performance kritik uygulamalar4- SQL'e hakim geliştiriciler5- Type-safe SQL queries6- Küçük/orta ölçekli projeler7 8Prisma tercih edilmeli:9- Büyük ekipler, güçlü migration tooling gereksinimi10- Code generation tercih edenler11- Zengin GUI(Prisma Studio)12- Karmaşık ilişkisel modeller13- Node.js-only ortamlarPrisma'nın edge uyumsuzluğu Accelerate servisi ile çözülüyor ama bu ek maliyet demek. Drizzle native edge support ile daha ekonomik.
Pricing ve Production Stratejisi
Turso Pricing (2026):
- Free: 5GB storage, 1B row reads/ay, 25M row writes/ay
- Starter: $25/ay - 24GB storage, unlimited row reads
- Scaler: $200/ay - 100GB, 1000 veritabanı, branching
- Enterprise: Özel
100K req/sec için production checklist:
- Embedded replica aktif (local read)
- Read/write connection ayrımı
- React cache ile request deduplication
- unstable_cache ile cross-request caching
- CDN edge'de static page caching
- Streaming ile TTFB optimizasyonu
- Monitoring: Turso dashboard + custom metrics
typescript
1// Drizzle transaction ile atomic operations2async function transferCredits(3 fromUserId: string,4 toUserId: string,5 amount: number6) {7 return await db.transaction(async (tx) => {8 // From kullanıcı bakiyesini güncelle9 const [fromUser] = await tx10 .update(users)11 .set({ credits: sql`credits - ${amount}` })12 .where(13 and(14 eq(users.id, fromUserId),15 gte(users.credits, amount) // Yeterli bakiye kontrolü16 )17 )18 .returning({ newCredits: users.credits })19 20 if (!fromUser) {21 tx.rollback() // Yetersiz bakiye - rollback22 return { error: 'Yetersiz bakiye' }23 }24 25 // To kullanıcı bakiyesini güncelle26 await tx27 .update(users)28 .set({ credits: sql`credits + ${amount}` })29 .where(eq(users.id, toUserId))30 31 // Transfer kaydı oluştur32 await tx.insert(creditTransfers).values({33 fromUserId,34 toUserId,35 amount,36 completedAt: new Date(),37 })38 39 return { success: true, newBalance: fromUser.newCredits }40 })41}ALTIN İPUCU
Bu yazının en değerli bilgisi
Bu ipucu, yazının en önemli çıkarımını içeriyor.
typescript
1import { sql } from 'drizzle-orm'2 3// SQLite JSON functions ile type-safe query4const result = await db.select({5 name: users.name,6 // JSON extract ile type cast7 firstTag: sql`json_extract(${posts.metadata}, '$.tags[0]')`, 8 totalViews: sql`json_extract(${posts.metadata}, '$.views')`, 9}).from(users)10 .leftJoin(posts, eq(users.id, posts.authorId))11 12// result tipi: { id: string, name: string, firstTag: string, totalViews: number }[]Easter Egg
Gizli bir bilgi buldun!
Bu bölümde gizli bir bilgi var. Keşfetmek ister misin?
sql
1-- Migration: FTS5 virtual table2CREATE VIRTUAL TABLE posts_fts USING fts5(3 title,4 content,5 content=posts,6 content_rowid=rowid7);8 9-- Trigger ile senkronize et10CREATE TRIGGER posts_fts_insert AFTER INSERT ON posts BEGIN11 INSERT INTO posts_fts(rowid, title, content)12 VALUES (new.rowid, new.title, new.content);13END;typescript
1// FTS query ile Drizzle raw SQL2export async function searchPosts(query: string) {3 const results = await db.all(4 sql`5 SELECT p.id, p.title, p.slug,6 snippet(posts_fts, 1, '', '', '...', 64) as excerpt,7 bm25(posts_fts) as rank8 FROM posts_fts9 JOIN posts p ON p.rowid = posts_fts.rowid10 WHERE posts_fts MATCH ${query}11 ORDER BY rank12 LIMIT 2013 `14 )15 return results as Array<{16 title: string17 slug: string18 excerpt: string19 rank: number20 }>21}Okuyucu Ödülü
SQLite FTS5 uzantısı ile Drizzle'da full-text search:
Sonuç
Drizzle ORM + Turso kombinasyonu, 2026 edge computing ortamında veritabanı mimarisinin yeni standardını belirliyor. Schema-first TypeScript approach, zero-overhead type inference ve native edge compatibility ile bu ikili güçlü bir stack oluşturuyor.
Temel çıkarımlar:
.$inferSelectve.$inferInsertkullanarak duplicate type tanımlamaktan kacının- Embedded replicas ile edge latency'yi 3ms'ye kadar indirin
- Write primary / read replica ayrımı ile 100K req/sec'ye ulaşın
- Server Actions ile type-safe mutation pattern'ları kurun
- FTS5 ile SQLite native full-text search ekleyin
Turso'nun $25/ay Starter planı ile başlayabilir, büyüdükçe ölçekleyebilirsiniz. Prisma'dan migration için drizzle-kit introspect komutu mevcut schema'yı otomatik analiz eder.
İlgili Kaynaklar:
Site İçi İlgili Yazılar:

