Build a URL Shortener with Node.js and MongoDB: Simple Implementation with Code

Coding ProjectsBuild a URL Shortener with Node.js and MongoDB: Simple Implementation with Code

Think URL shorteners are just toys? They’re actually one of the best small projects to learn real backend skills.
In this post you’ll build a working URL shortener with Node.js and MongoDB, step by step.
We’ll set up the project, design a MongoDB schema for original URLs and short codes, generate unique slugs, create Express routes to shorten and redirect, and add click tracking.
Follow along in your editor and terminal, and by the end you’ll have a testable API you can run locally or deploy.

Understanding the Goal of Building a URL Shortener with Node.js and MongoDB

9jVOT8bgVDulQnjP2XEE2A

A URL shortener grabs a long web address and turns it into something compact that still redirects users to the right place. When someone clicks the short link, your backend looks up the original URL in a database and sends them there. It’s simple, but you need to store URL pairs, generate unique identifiers, and handle those redirects.

Building a URL shortener with Node.js and MongoDB step by step means you’re creating a backend that receives long URLs, generates short codes, saves everything to a database, and serves redirect requests. Node.js handles server logic and routing. MongoDB stores each URL pair along with stuff like click counts and when it was created. You don’t need a fancy frontend. Just API endpoints that take URLs and spit out shortened versions.

The workflow’s pretty straightforward. Initialize a Node.js project, install what you need, connect to MongoDB, design a database schema, write controller functions for shortening and redirecting, and tie it all together with API routes. Each step builds on what came before. When you’re done, you’ve got a working backend you can test locally and push live.

Core build steps:

  • Initialize Node.js and install Express, Mongoose, and something for slug generation
  • Connect to MongoDB and define a schema for original URLs, short codes, click counts, timestamps
  • Write logic to generate unique short identifiers and save new mappings
  • Create API routes for shortening URLs and redirecting based on short codes
  • Add click tracking so you know how many times each link gets used

Why URL Shortener Implementations Require Node.js Logic and MongoDB Storage

BNvvyTruUqC1f-aSNbw0zQ

You need a backend to generate unique identifiers, save URL mappings, and handle redirects. Without server logic, there’s no way to store the connection between a short code and the original URL. No mechanism to look that up when someone clicks. Node.js gives you a runtime to build this fast using JavaScript, and Express makes routing and request handling simple.

MongoDB fits because each URL record is just a self-contained document with a few fields. Original URL, short code, click count, creation date. The database has to support fast lookups by short code and allow atomic updates when incrementing clicks. MongoDB’s indexing and flexible schema make it easy to add fields later. Mongoose gives you a clean way to define models and talk to the database using JavaScript.

Problems show up when pieces are missing or badly designed:

Weak schema design means missing fields, slow queries, or you can’t track analytics and expiration dates properly.

Poor unique ID generation causes slug collisions where two URLs share the same short code and overwrite each other.

Missing or broken routing logic stops redirects from working or throws errors instead of sending users where they need to go.

Setting Up the Node.js Project for the URL Shortener

5Tc2IVquVrSbMnUGbFXNRg

Create a new directory for the project and navigate there in your terminal. Run npm init to start a Node.js project. You’ll get asked about project name, version, entry point. Press Enter for defaults or type custom values. When it’s done, npm creates a package.json that tracks dependencies and scripts.

Install what you need: npm install express mongoose nanoid dotenv. Express handles routing and HTTP requests. Mongoose connects to MongoDB and gives you schema-based models. Nanoid generates short, unique identifiers for slugs. Dotenv loads environment variables from a .env file so database credentials stay out of your code. For development, also run npm install --save-dev nodemon. Nodemon restarts the server automatically when you save changes.

Set up a folder structure that separates things cleanly. Common pattern for backend projects uses something MVC-ish (Model, Controller, Routes) without the View layer since this is API-only. The structure should keep database models, business logic, and route definitions separate.

Files and folders you need:

  • index.js for the main server file that starts Express and connects to MongoDB
  • package.json listing dependencies and a start script for nodemon
  • models/ folder with urlModel.js defining the Mongoose schema
  • controllers/ folder with urlController.js for shortening and redirect logic
  • routes/ folder with urlRoutes.js mapping endpoints to controller functions
  • .env file in root storing environment variables like MongoDB connection string and port

NzTz0O9XXDCCwxA7hlUy1w

Set up MongoDB connection in a file called database/db.js. Import Mongoose and use mongoose.connect() to connect to your MongoDB instance. If you’re using MongoDB Atlas, copy the connection string from the dashboard and paste it into .env as MONGO_URI=your_connection_string_here. In db.js, load it using process.env.MONGO_URI and add error handling for connection failures. Once connected, Mongoose logs a success message.

Define the URL schema in models/urlModel.js. Import Mongoose and create a new schema with mongoose.Schema(). The schema defines structure for each URL document and sets data types and constraints. Each shortened URL needs a unique identifier (the short code), the original long URL, a counter for tracking clicks, and a timestamp for when it was created.

Add a unique index to the short code field so two URLs can’t accidentally share the same identifier. Mongoose lets you set unique: true in the schema, which tells MongoDB to enforce uniqueness at database level. This prevents collisions before they happen and throws an error if duplicate slugs are attempted.

Field Purpose
originalUrl Stores the full-length URL that the short link redirects to
shortCode A unique identifier used in the shortened URL path
clickCount Tracks how many times the shortened URL has been accessed
createdAt Timestamp showing when the URL was shortened

Why unique indexes prevent collisions:

MongoDB checks the index before inserting a new document and rejects duplicates. Indexing the shortCode field makes lookups fast when users visit the shortened URL. Unique constraints catch programming errors where slug generation accidentally produces the same code twice.

Implementing Slug Generation and URL Shortening Logic with Node.js

JtounDM1WQGsYkD5nWTB8g

Slug generation creates a short, unique identifier representing the original URL. The slug becomes part of the shortened link, like yourdomain.com/abc123. Different strategies exist depending on how short you want links, how many URLs you expect to handle, and whether you want readable or random codes.

Nanoid’s popular for generating random, URL-safe strings. It produces compact identifiers much shorter than UUIDs with very low collision probability. In controllers/urlController.js, import Nanoid and call it to generate a slug each time a new URL gets shortened. Before saving to the database, check if the slug already exists. If it does, generate a new one and check again. This retry logic ensures uniqueness even in rare collision cases.

Common slug generation methods:

Nanoid generates random, compact strings with customizable length and low collision risk.

Base62 encoding converts a numeric ID (like auto-incremented counter) into short alphanumeric string.

Hashing creates a hash of the original URL and truncates it to fixed length (collision risk exists).

Custom dictionary builds slugs from predefined list of words or characters for readable short links.

Sequential IDs uses incremental numbers converted to short format, predictable but compact.

The controller function for shortening URLs should accept the original URL as input, validate it’s a proper web address, generate a unique slug, create a new document in MongoDB with original URL and slug, and return the full shortened URL. If validation fails, return an error. If the slug exists, regenerate until you find a free one. When the document saves successfully, respond with the shortened link as yourdomain.com/[slug].

Building Express Routes to Shorten and Redirect URLs

zHPfEFB-Ws266wEg1KLlyw

Define API routes in routes/urlRoutes.js to handle incoming requests. Import Express and create a router using express.Router(). Map each endpoint to a controller function with the business logic. The two essential routes are a POST endpoint to shorten URLs and a GET endpoint to redirect users based on short code.

The POST route accepts the original URL in request body, calls the controller to generate a slug and save the mapping, and returns the shortened URL. The GET route takes the short code as URL parameter, looks up the original URL in database, increments click count, and redirects using HTTP 301 or 302 status. 301 redirect is permanent and tells browsers and search engines the URL moved for good. 302 is temporary and doesn’t affect caching or SEO.

Some implementations add an analytics endpoint returning data about a specific short link. This route accepts the short code as parameter, queries database for the URL document, and returns click count and other metadata. It doesn’t redirect, just provides information.

Key endpoints:

POST /shorten receives the original URL, generates a short code, saves the mapping, returns the shortened link.

GET /:shortCode looks up the original URL by short code, increments the click counter, redirects the user.

GET /analytics/:shortCode returns usage statistics like click count and creation date without redirecting.

Optional: DELETE /:shortCode removes a shortened URL from database if users want to revoke links.

Adding Analytics and Click Tracking to the URL Shortener

MOajkvSgV8WOF3JLfdhy_Q

Click tracking shows how often each shortened link gets used. Every time a user visits a short URL and gets redirected, the backend should increment a counter in the database. MongoDB’s atomic update operations make this easy and safe, even if multiple users click the same link simultaneously.

In the redirect controller function, after looking up the URL document by short code, use Mongoose’s findOneAndUpdate() method to increment the clickCount field by one. This operation combines lookup and update in a single atomic step, so you don’t worry about race conditions or lost increments. After the update, perform the redirect. Some implementations also store an array of timestamps for each click, allowing more detailed analytics like clicks per day or clicks from specific countries, but this needs additional logic and more storage.

Metric Description
Total Clicks The number of times the shortened URL has been accessed since creation
Created At The timestamp when the URL was first shortened, useful for calculating link age
Last Clicked Optional field that records the most recent time someone used the short link

Testing the URL Shortener API with Postman and Local Tools

ck6fJJeCU7eQUCQ2_153tw

Start the development server by running npm run dev if you added a script in package.json that launches nodemon. The server should connect to MongoDB and start listening on the port in your .env file (usually 3000 or 5000). If connection succeeds, you’ll see a log message in the terminal.

Open Postman and create a new request to test the shortening endpoint. Set method to POST and URL to http://localhost:3000/shorten. In request body, select “raw” and “JSON” format, then add a JSON object with the original URL, like { "url": "https://example.com/very-long-url" }. Click Send. Server should respond with the shortened URL. Copy the short code from the response.

Test actions to verify everything works:

Send a POST request to /shorten with a valid URL and confirm you receive a shortened link in response.

Open a browser and go to http://localhost:3000/[shortCode] to verify the redirect sends you to the original URL.

Send a GET request to /analytics/[shortCode] in Postman to check the click count incremented after the redirect.

Try shortening the same URL twice and confirm each request creates a new short code (or returns the existing one if you added deduplication logic).

Deploying the URL Shortener Built with Node.js and MongoDB

l0F_vzQXWfC1quVjAKKC_g

Deploying to Heroku’s common for Node.js apps because it handles server setup, scaling, and environment variables automatically. Create a free account on Heroku and install the Heroku CLI. Log in by running heroku login in your terminal, which opens a browser for authentication. Once logged in, create a new Heroku app by running heroku create your-app-name. Heroku generates a unique URL for your app.

Initialize a Git repository in your project folder if you haven’t already. Run git init, then add all files with git add . and commit with git commit -m "Initial commit". Heroku needs a Procfile in root directory to know how to start your app. Create a file named Procfile (no extension) and add the line web: node index.js. This tells Heroku to run your server using Node.js. Push code to Heroku by running git push heroku main. Heroku builds the app, installs dependencies, and starts the server. Watch the terminal for build logs.

Set environment variables on Heroku using heroku config:set MONGO_URI=your_mongodb_atlas_connection_string. You can add other variables the same way, like heroku config:set PORT=3000. Heroku automatically uses the PORT variable, so your code should listen on process.env.PORT instead of a hardcoded number. Once build finishes, run heroku open to launch the app in your browser. Test the endpoints using the live Heroku URL instead of localhost.

Heroku deployment steps:

Install Heroku CLI and log in with heroku login.

Create a new Heroku app using heroku create.

Initialize a Git repository, commit your code, add the Heroku remote.

Create a Procfile with the command web: node index.js.

Push code to Heroku with git push heroku main and monitor build logs.

Platform Deployment Notes
Heroku Free tier available, automatic builds from Git, supports environment variables via CLI or dashboard
MongoDB Atlas Managed cloud database, free tier includes 512MB storage, connection string added to .env file
Docker Package the app in a container for consistent deployment across platforms, requires Dockerfile and image registry

Preventing Issues When Building URL Shorteners with Node.js and MongoDB

ZxLSpSPyVMaZgrF8uh8GZA

Validate incoming URLs before generating short codes. A simple regex pattern can check if the input looks like a valid web address. If validation fails, return a clear error instead of saving broken data to the database. This prevents busted redirects and keeps the database clean. Some developers use libraries like validator.js to handle URL validation and other input checks.

Rate limiting protects your API from abuse. Without it, someone could flood the server with shortening requests and overwhelm the database or exhaust storage. Install express-rate-limit and configure it to allow a reasonable number of requests per IP address per minute. If a user exceeds the limit, the middleware returns an error before the request reaches the controller.

Best practices to reduce errors and improve security:

Validate all incoming URLs using a regex pattern or validation library before saving to database.

Implement rate limiting with express-rate-limit to prevent abuse and excessive database writes.

Use environment variables for sensitive data like MongoDB connection strings and never commit .env files to Git.

Add optional authentication so only authorized users can create shortened URLs.

Enable CORS configuration if you plan to build a frontend on a different domain and need to allow cross-origin requests.

When to Seek Further Help for Your URL Shortener Project

If the basic implementation works but you want to add features like custom aliases, user authentication, or a dashboard for managing links, you’ll need to expand beyond the core backend. Custom aliases let users choose their own short codes instead of random strings, which means checking if the alias is available and handling conflicts. User authentication adds login functionality and associates each shortened URL with a specific account, so you can track who created each link and let users delete or edit their URLs.

Exploring GitHub repositories for URL shortener projects can show examples of these advanced features. Lots of open-source implementations include frontend interfaces, authentication systems, and analytics dashboards. If you get stuck on deployment, database configuration, or adding new functionality, the Node.js and MongoDB communities offer active forums, Stack Overflow questions, and documentation addressing common roadblocks.

Final Words

You set up a Node.js project, connected MongoDB, designed the URL schema, added slug generation, and wired Express routes for shortening and redirects. You also learned about analytics, testing with Postman, deployment tips, and common pitfalls like collisions and missing validation.

If something breaks, check env vars, database connections, and route handlers. Follow the steps and you can build a URL shortener with Node.js and MongoDB step by step. Try it now—each small win stacks into a real, useful tool.

FAQ

Q: How to build a URL shortener? / How to create a URL shortener in JavaScript?

A: Building a URL shortener in JavaScript involves creating a Node.js API (Express), storing mappings in MongoDB (Mongoose), generating short slugs (Nanoid or base62), adding shorten/redirect routes, tracking clicks, and testing then deploying.

Q: How to create a node.js project with MongoDB?

A: Creating a Node.js project with MongoDB involves npm init, installing Express and Mongoose, setting your Atlas URI in a .env file, defining models and routes, then running with nodemon for development.

Q: Why NoSQL for URL shortener?

A: Using NoSQL for a URL shortener is recommended because MongoDB gives flexible schemas, fast key-value lookups, easy scaling, and unique indexes to prevent slug collisions while storing click counts and metadata.

Check out our other content

Check out other tags: