In this tutorial, you will learn how to create a Cloudflare Workers application and connect it to a MongoDB database using the native Node.js driver. You will start with a direct connection from a Worker, then use a Durable Object to persist connections and reduce latency.
To continue:
- Sign up for a Cloudflare account ↗︎ if you have not already.
- Install
npm↗︎. - Install
Node.js↗︎. Use a Node version manager like Volta ↗︎ or nvm ↗︎ to avoid permission issues and change Node.js versions. - Make sure you have access to a MongoDB database. You can use MongoDB Atlas ↗︎, a self-hosted MongoDB instance, or any other MongoDB-compatible host.
First, use the create-cloudflare CLI ↗︎ to create a new Worker application. To do this, open a terminal window and run the following command:
npm create cloudflare@latest -- mongodb-tutorialyarn create cloudflare mongodb-tutorialpnpm create cloudflare@latest mongodb-tutorialThis will prompt you to install the create-cloudflare ↗︎ package and lead you through a setup wizard.
For setup, select the following options:
- For What would you like to start with?, choose
Hello World example. - For Which template would you like to use?, choose
Worker only. - For Which language do you want to use?, choose
TypeScript. - For Do you want to use git for version control?, choose
Yes. - For Do you want to add an AGENTS.md file to help AI coding tools understand Cloudflare APIs?, choose
Yes. - For Do you want to deploy your application?, choose
No(we will be making some changes before deploying).
If you choose to deploy, you will be asked to authenticate (if not logged in already), and your project will be deployed. If you deploy, you can still modify your Worker code and deploy again at the end of this tutorial.
Now, move into the newly created directory:
cd mongodb-tutorialNode.js compatibility is required for the MongoDB driver, and needs to be configured for your Workers project.
For compatibility dates of 2026-08-04 or later, Workers and Pages projects enable both nodejs_compat and nodejs_compat_v2 by default. Built-in runtime APIs and polyfills are available without additional configuration. These flags are not used for these compatibility dates. Existing projects do not need to remove them when updating their compatibility date.
If your compatibility date is before 2026-08-04, add the nodejs_compat compatibility flag to your Wrangler configuration file to opt in:
{
"compatibility_flags": [
"nodejs_compat"
]
}compatibility_flags = [ "nodejs_compat" ]To turn off Node.js compatibility completely for a compatibility date of 2026-08-04 or later, remove the positive flags if present. Then add both no_nodejs_compat and no_nodejs_compat_v2. For configuration examples, refer to the Node.js compatibility flag.
To connect to a MongoDB database, you will need the mongodb library. In your Worker application directory, run the following command to install the library:
npm i mongodbyarn add mongodbpnpm add mongodbbun add mongodbSet your MongoDB connection string as a secret so that it is not stored as plain text. Use wrangler secret put with the example variable name MONGODB_URI:
npx wrangler secret put MONGODB_URISet your MONGODB_URI secret locally in a .env file as documented in Local Development with Secrets:
MONGODB_URI="<ENTER YOUR MONGODB CONNECTION STRING>"Open your Worker's main file (for example, src/index.ts) and import the MongoClient class from the mongodb library:
import { MongoClient } from "mongodb";In the fetch event handler, create a new MongoClient instance and connect to the MongoDB database.
// create a new MongoClient instance using the connection string
const client = new MongoClient(env.MONGODB_URI);
// connect to the MongoDB database
await client.connect();To demonstrate how to interact with the movies database, you will fetch a document from the movies collection by querying the collection when a request is received.
Replace the existing code in your src/index.ts file with the following code:
import { MongoClient } from "mongodb";
export default {
async fetch(request, env, ctx) {
const client = new MongoClient(env.MONGODB_URI);
await client.connect();
const movie = await client
.db("sample_mflix")
.collection("movies")
.findOne(
{ title: "The Room" },
{ projection: { _id: 0, title: 1, imdb: 1 } },
);
return Response.json({ movie });
},
};import { MongoClient } from "mongodb";
export interface Env {
MONGODB_URI: string;
}
export default {
async fetch(request, env, ctx): Promise<Response> {
const client = new MongoClient(env.MONGODB_URI);
await client.connect();
const movie = await client
.db("sample_mflix")
.collection("movies")
.findOne(
{ title: "The Room" },
{ projection: { _id: 0, title: 1, imdb: 1 } },
);
return Response.json({ movie });
},
} satisfies ExportedHandler<Env>;This code establishes a connection to the MongoDB database within your Worker application and queries the movies collection, returning the result as a JSON response.
Run the following command to deploy your Worker:
npx wrangler deployAfter deploying, you can interact with your MongoDB database using your Cloudflare Worker. Whenever a request is made to your Worker's URL, it will fetch data from the movies collection and return it as a JSON response.
Each Worker invocation creates a new TCP and TLS connection to MongoDB. For low-traffic use cases, this is acceptable. For latency-sensitive applications, place the MongoClient inside a Durable Object to persist the connection between requests.
Create a new file for the Durable Object class:
import { DurableObject } from "cloudflare:workers";
import { MongoClient } from "mongodb";
export class MongoDBConnection extends DurableObject {
client;
constructor(state, env) {
super(state, env);
this.client = new MongoClient(env.MONGODB_URI, {
maxPoolSize: 1,
minPoolSize: 0,
serverSelectionTimeoutMS: 5000,
maxIdleTimeMS: 20_000,
});
}
async getMovie() {
await this.client.connect();
return this.client
.db("sample_mflix")
.collection("movies")
.findOne(
{ title: "The Room" },
{ projection: { _id: 0, title: 1, imdb: 1 } },
);
}
}import { DurableObject } from "cloudflare:workers";
import { MongoClient } from "mongodb";
interface Env {
MONGODB_URI: string;
}
export class MongoDBConnection extends DurableObject<Env> {
private client: MongoClient;
constructor(state: DurableObjectState, env: Env) {
super(state, env);
this.client = new MongoClient(env.MONGODB_URI, {
maxPoolSize: 1,
minPoolSize: 0,
serverSelectionTimeoutMS: 5000,
maxIdleTimeMS: 20_000,
});
}
async getMovie() {
await this.client.connect();
return this.client
.db("sample_mflix")
.collection("movies")
.findOne(
{ title: "The Room" },
{ projection: { _id: 0, title: 1, imdb: 1 } },
);
}
}Update your Worker entry point to route requests to the Durable Object:
import { MongoDBConnection } from "./MongoDBConnection";
export default {
async fetch(request, env) {
const id = env.MONGODB_CONNECTION.idFromName("mongodb-connection");
const stub = env.MONGODB_CONNECTION.get(id, { locationHint: "enam" });
const movie = await stub.getMovie();
return Response.json({ movie });
},
};
export { MongoDBConnection };import { MongoDBConnection } from "./MongoDBConnection";
interface Env {
MONGODB_URI: string;
MONGODB_CONNECTION: DurableObjectNamespace<MongoDBConnection>;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const id = env.MONGODB_CONNECTION.idFromName("mongodb-connection");
const stub = env.MONGODB_CONNECTION.get(id, { locationHint: "enam" });
const movie = await stub.getMovie();
return Response.json({ movie });
},
} satisfies ExportedHandler<Env>;
export { MongoDBConnection };Use the locationHint option to place the Durable Object close to your MongoDB cluster.
Configure the Durable Object binding and migration in your Wrangler file:
{
"$schema": "./node_modules/wrangler/config-schema.json",
"name": "mongodb-tutorial",
"main": "src/index.ts",
// Set this to today's date
"compatibility_date": "2026-10-17",
"compatibility_flags": [
"nodejs_compat"
],
"durable_objects": {
"bindings": [
{
"name": "MONGODB_CONNECTION",
"class_name": "MongoDBConnection"
}
]
},
"migrations": [
{
"tag": "v1",
"new_classes": [
"MongoDBConnection"
]
}
]
}name = "mongodb-tutorial"
main = "src/index.ts"
# Set this to today's date
compatibility_date = "2026-10-17"
compatibility_flags = ["nodejs_compat"]
[[durable_objects.bindings]]
name = "MONGODB_CONNECTION"
class_name = "MongoDBConnection"
[[migrations]]
tag = "v1"
new_classes = ["MongoDBConnection"]Run the following command to deploy your Worker:
npx wrangler deployYour Worker application is now live and accessible at <YOUR_WORKER>.<YOUR_SUBDOMAIN>.workers.dev, using a Durable Object to persist MongoDB connections. This reduces query latency from ~300 ms on cold requests to ~35 ms on warm requests.
To build more with databases and Workers, refer to Tutorials and explore the Databases documentation.
If you have any questions, need assistance, or would like to share your project, join the Cloudflare Developer community on Discord ↗︎ to connect with fellow developers and the Cloudflare team.