I am building a reusable Card component that can render as an a tag, a button tag, or a custom Next.js Link based on an as prop. I am struggling to get the TypeScript typing correct so that standard attributes (like href for links, type for buttons) are auto-completed and typesafe. Can someone show me a clean way to achieve this?
I am building a reusable Card component that can render as an a tag, a button tag, or a custom Next.js Link based on an as prop. I am struggling to get the TypeScript typing correct so that standard attributes (like href for links, type for buttons) are auto-completed and typesafe. Can someone show me a clean way to achieve this?
We are thrilled to roll out our brand new discussion platform built from the ground up with Next.js, Laravel, and WebSockets. This forum is fully optimized for developers, featuring low latency, syntax-highlighted code blocks, accepted answers, markdown integration, and gamified reputation badges. Jump in, ask questions, and share what you are working on!
We are thrilled to roll out our brand new discussion platform built from the ground up with Next.js, Laravel, and WebSockets. This forum is fully optimized for developers, featuring low latency, syntax-highlighted code blocks, accepted answers, markdown integration, and gamified reputation badges. Jump in, ask questions, and share what you are working on!
Context: We're building a multi‑tenant SaaS that ingests ~10k rows/sec per tenant, total 200k rows/sec. Data is time‑series plus tenantid. We need fast inserts, low‑latency recent queries, and easy archiving of old data. Trade‑off 1 – Range partitioning on createdat (daily). Simple to drop old partitions, but each insert must be routed through the parent planner; with many tenants the planner cache grows, and hot partitions can cause lock contention on the partition key. Indexes need to be recreated per partition. Trade‑off 2 – List partitioning on tenantid with sub‑partition on range (monthly). Isolates tenant hot spots, reducing contention, but creates thousands of partitions quickly, hitting planner overhead and default maxparallelworkerspergather. Maintenance scripts become more complex. Trade‑off 3 – Declarative partitioning with a default partition for overflow. Allows fallback for unexpected dates or new tenants, but queries that span the default partition may suffer performance penalties. sql CREATE TABLE events ( id bigint NOT NULL, tenantid uuid NOT NULL, createdat timestamptz NOT NULL, payload jsonb, PRIMARY KEY (tenantid, createdat, id) ) PARTITION BY LIST (tenantid); -- one tenant example CREATE TABLE eventst1 PARTITION OF events FOR VALUES IN ('11111111-1111-1111-1111-111111111111') PARTITION BY RANGE (createdat); CREATE TABLE eventst1202409 PARTITION OF eventst1 FOR VALUES FROM ('2024-09-01') TO ('2024-10-01'); Open questions: 1. In your production workloads, how have you balanced the number of partitions vs planner overhead when using list + range partitioning? 2. What automated VACUUM/ANALYZE strategy do you use to keep insert latency low across thousands of partitions? Related Engineering Guides - [Complete Guide to Architecting a Scalable SaaS Platform](/articles/complete-guide-to-architecting-a-scalable-saas-platform) - [Laravel Eloquent: Why Your Database Index Is Being Ignored](/articles/laravel-eloquent-why-database-index-ignored-leftmost-prefix)
Context: We're building a multi‑tenant SaaS that ingests ~10k rows/sec per tenant, total 200k rows/sec. Data is time‑series plus tenantid. We need fast inserts, low‑latency recent queries, and easy archiving of old data. Trade‑off 1 – Range partitioning on createdat (daily). Simple to drop old partitions, but each insert must be routed through the parent planner; with many tenants the planner cache grows, and hot partitions can cause lock contention on the partition key. Indexes need to be recreated per partition. Trade‑off 2 – List partitioning on tenantid with sub‑partition on range (monthly). Isolates tenant hot spots, reducing contention, but creates thousands of partitions quickly, hitting planner overhead and default maxparallelworkerspergather. Maintenance scripts become more complex. Trade‑off 3 – Declarative partitioning with a default partition for overflow. Allows fallback for unexpected dates or new tenants, but queries that span the default partition may suffer performance penalties. sql CREATE TABLE events ( id bigint NOT NULL, tenantid uuid NOT NULL, createdat timestamptz NOT NULL, payload jsonb, PRIMARY KEY (tenantid, createdat, id) ) PARTITION BY LIST (tenantid); -- one tenant example CREATE TABLE eventst1 PARTITION OF events FOR VALUES IN ('11111111-1111-1111-1111-111111111111') PARTITION BY RANGE (createdat); CREATE TABLE eventst1202409 PARTITION OF eventst1 FOR VALUES FROM ('2024-09-01') TO ('2024-10-01'); Open questions: 1. In your production workloads, how have you balanced the number of partitions vs planner overhead when using list + range partitioning? 2. What automated VACUUM/ANALYZE strategy do you use to keep insert latency low across thousands of partitions? Related Engineering Guides - [Complete Guide to Architecting a Scalable SaaS Platform](/articles/complete-guide-to-architecting-a-scalable-saas-platform) - [Laravel Eloquent: Why Your Database Index Is Being Ignored](/articles/laravel-eloquent-why-database-index-ignored-leftmost-prefix)
Hey everyone, I'm starting a new Next.js 13 project that fully embraces the App Router (server components, async data fetching, optional edge runtime). The data layer will be PostgreSQL, and I'm torn between Prisma and TypeORM. Both work in a classic pages router, but the App Router introduces a few nuances: Edge compatibility – Prisma's client now supports edge, but you need to enable the binaryTargets and set engine: { binary: { ... } }. TypeORM runs on the Node runtime, so deploying to Vercel edge functions forces a fallback to a serverless function. Migrations – Prisma's declarative migrations are fast and generate a clean schema.prisma. TypeORM's migration CLI feels more manual, and I've hit issues with generated SQL ordering when using synchronize: true in dev. Type safety – Prisma generates fully‑typed models out of the box. With TypeORM you can add class-validator and class-transformer, but you still write entity classes yourself, which can drift from the DB schema. Lazy loading – TypeORM's lazy relations rely on proxies that break inside server components (they expect a request‑scoped context). Prisma's explicit include/select works fine. A minimal Prisma client init for an edge function looks like: ts import { PrismaClient } from '@prisma/client'; export const prisma = new PrismaClient({ datasources: { db: { url: process.env.DATABASEURL } }, errorFormat: 'pretty', }); Questions: 1. Have you run Prisma in Vercel edge functions without hitting the Binary not found error? What config saved you time? 2. If you stuck with TypeORM, how did you handle lazy‑loaded relations inside server components or edge routes? Looking forward to hearing your production stories and any gotchas you discovered. Related Engineering Guides - [Complete Guide to Architecting a Scalable SaaS Platform](/articles/complete-guide-to-architecting-a-scalable-saas-platform) - [Building Scalable Microservices with Laravel and Next.js: 2026 Guide](/articles/building-scalable-microservices-with-laravel-and-nextjs-2026-guide)
Hey everyone, I'm starting a new Next.js 13 project that fully embraces the App Router (server components, async data fetching, optional edge runtime). The data layer will be PostgreSQL, and I'm torn between Prisma and TypeORM. Both work in a classic pages router, but the App Router introduces a few nuances: Edge compatibility – Prisma's client now supports edge, but you need to enable the binaryTargets and set engine: { binary: { ... } }. TypeORM runs on the Node runtime, so deploying to Vercel edge functions forces a fallback to a serverless function. Migrations – Prisma's declarative migrations are fast and generate a clean schema.prisma. TypeORM's migration CLI feels more manual, and I've hit issues with generated SQL ordering when using synchronize: true in dev. Type safety – Prisma generates fully‑typed models out of the box. With TypeORM you can add class-validator and class-transformer, but you still write entity classes yourself, which can drift from the DB schema. Lazy loading – TypeORM's lazy relations rely on proxies that break inside server components (they expect a request‑scoped context). Prisma's explicit include/select works fine. A minimal Prisma client init for an edge function looks like: ts import { PrismaClient } from '@prisma/client'; export const prisma = new PrismaClient({ datasources: { db: { url: process.env.DATABASEURL } }, errorFormat: 'pretty', }); Questions: 1. Have you run Prisma in Vercel edge functions without hitting the Binary not found error? What config saved you time? 2. If you stuck with TypeORM, how did you handle lazy‑loaded relations inside server components or edge routes? Looking forward to hearing your production stories and any gotchas you discovered. Related Engineering Guides - [Complete Guide to Architecting a Scalable SaaS Platform](/articles/complete-guide-to-architecting-a-scalable-saas-platform) - [Building Scalable Microservices with Laravel and Next.js: 2026 Guide](/articles/building-scalable-microservices-with-laravel-and-nextjs-2026-guide)
We recently migrated one of our high-traffic content sites from Next.js Page Router (SSR) to Next.js 15 App Router using Server Components (RSC). After 3 weeks of running in production, I gathered some interesting insights regarding core web vitals, server-side memory leaks, and compilation sizes. Here is a breakdown of what improved and what got slightly worse.
We recently migrated one of our high-traffic content sites from Next.js Page Router (SSR) to Next.js 15 App Router using Server Components (RSC). After 3 weeks of running in production, I gathered some interesting insights regarding core web vitals, server-side memory leaks, and compilation sizes. Here is a breakdown of what improved and what got slightly worse.