Hi Next.js team 👋
While following the Next.js App Router tutorial and implementing the /seed/route.ts file, I noticed a few issues in the seed script that can cause confusion or subtle bugs for learners. I wanted to document them here in case it’s helpful to improve the tutorial.
Below is a summary of the findings and suggested fixes.
Issues identified
1. Transaction is not actually used
The seed script uses:
sql.begin((sql) => [
seedUsers(),
seedCustomers(),
seedRevenue(),
seedInvoices(),
]);
However, the seed* functions use the outer sql client, not the transactional client passed into begin. As a result, the queries do not run inside the transaction, despite appearing to do so.
Suggested fix
- Pass the transaction client into each seed function and use that client for queries.
await sql.begin(async (tx) => {
await seedUsers(tx);
await seedCustomers(tx);
await seedInvoices(tx);
await seedRevenue(tx);
});
2. ON CONFLICT (id) used without inserting id (invoices)
In the invoices seed:
INSERT INTO invoices (customer_id, amount, status, date)
VALUES (...)
ON CONFLICT (id) DO NOTHING;
Since id is auto-generated and never inserted, this conflict clause will never trigger and is effectively a no-op.
Suggested fix
- Remove the
ON CONFLICT clause
3. Missing foreign key constraint on invoices.customer_id
The invoices table defines:
customer_id UUID NOT NULL
but does not reference the customers table. This allows invoices to exist without a valid customer.
Suggested fix
customer_id UUID NOT NULL REFERENCES customers(id)
This aligns with how invoices are queried later in the tutorial.
4. Repeated CREATE EXTENSION calls
CREATE EXTENSION IF NOT EXISTS "uuid-ossp" is executed in multiple seed functions. Extensions are database-wide, so this is redundant (though harmless).
Suggested fix
- Run the extension creation once before the transaction begins.
export async function GET() {
try {
// Create extension once for the whole database
await sql`CREATE EXTENSION IF NOT EXISTS "uuid-ossp"`;
await sql.begin(async (tx) => {
await seedUsers(tx);
await seedCustomers(tx);
await seedInvoices(tx);
await seedRevenue(tx);
});
return Response.json({ message: 'Database seeded successfully' });
} catch {
return Response.json(
{ error: 'Failed to seed database' },
{ status: 500 }
);
}
}
Other than that, thanks for the excellent tutorial content overall, it’s been a great learning experience!
Hi Next.js team 👋
While following the Next.js App Router tutorial and implementing the
/seed/route.tsfile, I noticed a few issues in the seed script that can cause confusion or subtle bugs for learners. I wanted to document them here in case it’s helpful to improve the tutorial.Below is a summary of the findings and suggested fixes.
Issues identified
1. Transaction is not actually used
The seed script uses:
However, the
seed*functions use the outersqlclient, not the transactional client passed intobegin. As a result, the queries do not run inside the transaction, despite appearing to do so.Suggested fix
2.
ON CONFLICT (id)used without insertingid(invoices)In the invoices seed:
Since
idis auto-generated and never inserted, this conflict clause will never trigger and is effectively a no-op.Suggested fix
ON CONFLICTclause3. Missing foreign key constraint on
invoices.customer_idThe invoices table defines:
customer_id UUID NOT NULLbut does not reference the
customerstable. This allows invoices to exist without a valid customer.Suggested fix
customer_id UUID NOT NULL REFERENCES customers(id)This aligns with how invoices are queried later in the tutorial.
4. Repeated
CREATE EXTENSIONcallsCREATE EXTENSION IF NOT EXISTS "uuid-ossp"is executed in multiple seed functions. Extensions are database-wide, so this is redundant (though harmless).Suggested fix
Other than that, thanks for the excellent tutorial content overall, it’s been a great learning experience!