Should I reconnect to the DB in every handler when I use next.js for API? Or is there a better way to do that?
And isn't that a bad thing if it was the regular approach?
I tried to create a nextjs project with typeorm or MongoDB and all the examples and resources look like they are waiting for the connection with each call.
The attached image is for typeorm example. I got it from this repo
And here is the Mongo articles that I found that they instruct to add the DB connection in middleware and recall it in every handler.
https://developer.mongodb.com/how-to/nextjs-building-modern-applications https://hoangvvo.com/blog/full-fledged-app-with-next-js-and-mongodb-part-1/
and here is the repos middleware to check it too if you like
https://github.com/kukicado/building-modern-app-with-nextjs-and-mongodb/blob/master/mct/middleware/database.js
https://github.com/hoangvvo/nextjs-mongodb-app/blob/master/middlewares/database.js
For me am trying to create nextjs with typeorm but I searched for the Mongo because I couldn't find a lot of resources for typeorm + nextjs so I searched for the connection concept for the Monog since it's kinda similar
Not only is Next. js great for creating serverless API routes, it's also a framework for React. This means that you can create your frontend site and backend logic within the same project.
Next. js has support for API Routes, which let you easily create an API endpoint as a Node. js serverless function.
I usually create a simple wrapper function for Next API Handlers and use it like
export default withDb((req, res) => {
// ...
})
withDb
function checks if there is an active connection and if not it creates one and uses it for the current and next requests. If there are multiple requests concurrently, it attaches them to the same promise object and waits for the db connection only once. It's like this:
import '@/types';
import mongoose from 'mongoose';
import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next';
import { Maybe } from '@/types';
import models from '../models';
declare module 'http' {
interface IncomingMessage {
models: Maybe<typeof models>;
}
}
const readyStates = {
disconnected: 0,
connected: 1,
connecting: 2,
disconnecting: 3,
};
let pendingPromise: Maybe<Promise<typeof mongoose>> = null;
// https://hoangvvo.com/blog/migrate-from-express-js-to-next-js-api-routes/
const withDb = (fn: NextApiHandler) => async (
req: NextApiRequest,
res: NextApiResponse,
) => {
const next = () => {
req.models = models;
return fn(req, res);
};
const { readyState } = mongoose.connection;
// TODO: May need to handle concurrent requests
// with a little bit more details (disconnecting, disconnected etc).
if (readyState === readyStates.connected) {
return next();
} else if (pendingPromise) {
// Wait for the already pending promise if there is one.
await pendingPromise;
return next();
}
pendingPromise = mongoose.connect(process.env.DB, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
useFindAndModify: true,
});
try {
await pendingPromise;
} finally {
pendingPromise = null;
}
// We need to return "next" from "withDb". Otherwise, if it wraps an async function,
// the wrapper function of "withDb" (like "handleErrors" etc)
// can't wait and catch errors inside it the function wrapped by "withDb".
// It just waits for "withDb" to complete and continues.
// As an alternative, we can "await" this "next" too of course.
// Main point is, waiting it to be completed.
return next();
};
export default withDb;
As you can see, this example is for mongoose
. I've tried using TypeORM
with Next.js a couple of times but it creates a lot of problems. I just think I'm gonna try prisma
for the next time. TypeORM
is cool and a lot more popular. But there are some problems and when you can't solve them, you get stuck at one point.
I usually connect and disconnect to the database for each API call.
Here are my reasons:
When many people will use the site, the number of database connections increases and remains (connection pooling).
Reusing database connections removes the need to create a connection for each handler but places a strain on the Node.js server and database server.
Unless you have a specific reason, it may be better to recreate the instance.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With