How to Upload Images to Cloudinary Using MERN Stack (Step-by-Step Beginner Guide)

If you are building a MERN stack application and wondering how to upload images to Cloudinary properly, this guide will explain everything in a simple and practical way.

In this article, you will learn:

  • Why we should not store images inside MongoDB
  • Why local server storage fails after deployment
  • How to upload images to Cloudinary using MERN stack step-by-step
  • The role of Multer, routes, controller, and service layer
  • How React frontend sends images to backend
  • How to design a clean and scalable image upload architecture

By the end, you will understand not just the code — but the full architecture behind professional image uploads.

Why Storing Images Inside MERN Stack Is a Bad Idea

Many beginners try to store images directly inside MongoDB. Technically, it works. But practically, it creates problems.

MongoDB is designed for structured data like:

  • User information
  • Product details
  • Orders
  • Messages

It is not optimized for large binary files like images.

When you store images inside MongoDB:

  • Database size increases rapidly
  • Backups become heavy
  • Performance decreases

Some developers save images in a local uploads folder. That works in development, but in production many hosting platforms reset storage during deployment.

So what is the correct solution?

Upload images to Cloudinary. Store only the image URL in MongoDB.

Let’s understand this with a simple example.

When you take admission in school, the office collects your full details — name, address, and photo. All these are stored safely in school records.

But inside the classroom, the teacher does not bring your full admission file every day. Instead, they call your ID number for attendance.

Your ID number represents all your stored information.

Now relate this to how we upload images to Cloudinary using MERN stack:

  • Cloudinary = School office (stores actual image)
  • MongoDB = Classroom register
  • Image URL = Student ID number

Cloudinary stores the actual image. MongoDB stores only the reference link.

Cloudinary stores the image. MongoDB stores the image URL.

This is the professional way to upload images in modern applications.

How the Image Upload Flow Works

  1. User selects image in React frontend
  2. React sends image to Express backend
  3. Multer processes the file
  4. Backend uploads image to Cloudinary
  5. Cloudinary returns a secure URL
  6. MongoDB stores that URL

Frontend: How React Uploads Images

The image upload process starts from the frontend.

In React, we capture the file from an input field and send it using FormData.

const formData = new FormData();
formData.append("image", file);

await axios.post("/api/images/upload", formData);

Why use FormData?

Because images cannot be sent as normal JSON. They must be sent as multipart/form-data.

The key name "image" must match the backend field name.

This request goes to your Express backend.

Backend Step 1: Multer Middleware

Express cannot handle file uploads by default. Multer reads file data and attaches it to req.file.

const multer = require("multer");

const upload = multer({
  storage: multer.memoryStorage(),
  limits: { fileSize: 5 * 1024 * 1024 }
});

We use memory storage because we do not want to store files locally. We immediately send them to Cloudinary.

Backend Step 2: Cloudinary Service Layer

Instead of writing Cloudinary logic inside the controller, we separate it into a service.

cloudinary.config({
  cloud_name: process.env.CLOUD_NAME,
  api_key: process.env.API_KEY,
  api_secret: process.env.API_SECRET
});

This keeps our architecture clean and professional.

Backend Step 3: Controller

const uploadImage = async (req, res) => {
  if (!req.file) return res.status(400).json({ error: "No file" });

  const imageUrl = await uploadToCloudinary(req.file.buffer);
  await Image.create({ imageUrl });

  res.status(201).json({ success: true });
};

The controller connects Multer, Cloudinary service, and MongoDB.

Backend Step 4: Route

router.post("/upload", upload.single("image"), uploadImage);

The complete flow becomes:

Route → Multer → Controller → Service → Cloudinary → MongoDB

Frequently Asked Questions

1. Can I upload images directly from React to Cloudinary?

Yes, but it is safer to upload through backend so your API_SECRET remains hidden.

2. Why should I not store images inside MongoDB?

MongoDB is optimized for structured data, not large binary files like images.

3. Is Cloudinary free?

Yes, Cloudinary offers a generous free tier suitable for learning and small projects.

4. What does Multer do?

Multer processes file uploads and makes image data available in req.file.

5. Is this method production-ready?

Yes. This is the industry-standard way to upload images to Cloudinary using MERN stack.

Final Thoughts

Uploading images correctly is not just about making it work — it’s about making it scalable.

  • Do not store images inside MongoDB.
  • Do not depend on local storage for production.
  • Upload images to Cloudinary.
  • Store only the image URL in MongoDB.

When you upload images to Cloudinary using MERN stack properly, your application becomes secure, scalable, and production-ready.

Understand the architecture first. Code becomes easy after that.

Related Articles

If you are improving your development skills, these guides will help you.

Comments

Popular posts from this blog

What Is This Keyword in JavaScript? Explained With Real Examples

How to Navigate a Large Codebase (Frontend & Backend Guide for New Developers)

How JavaScript Objects Work (Prototype Chain, Inheritance & Property Descriptors Explained)