How to securely implement dynamic QR Code redirection with expiration in Node.js and MongoDB?
15:04 05 Dec 2025

How to securely implement dynamic QR Code redirection with expiration in Node.js and MongoDB?

I’m building a SaaS similar to dynamic QR Code platforms (e.g. Code2Scan), where users create a short URL that points to a final destination (landing page, WhatsApp link, event page, etc.).

The flow I’m trying to implement in Node.js + Express + MongoDB is:

1. User creates a “dynamic QR Code”:

  • I generate a short URL like: `https://example.com/r/abc123%5C%60
  • I save metadata in MongoDB with:
    • `targetUrl` (final destination, must be HTTPS)
    • `expiresAt` (date when the redirect stops working)
    • `createdAt`
    • `status` (active / expired / blocked)
    • maybe some tracking fields like `scanCount`, `lastScanAt`

2. When someone scans the QR code:

  • They hit `GET /r/:slug`
  • I look up `slug` in MongoDB
  • If it’s valid and not expired, I redirect to `targetUrl`
  • If it’s expired or blocked, I want to show a custom page instead of redirecting

What I’m unsure about is the best architecture and patterns for:

- Enforcing HTTPS-only `targetUrl` (avoid http and unsafe URLs).
- Preventing open redirect / unsafe redirect issues (e.g. someone saving a malicious URL).
- Handling expiration efficiently:

  • Is it better to check `expiresAt` on every request,
  • or run a background job to mark documents as expired?
    - Designing the MongoDB schema and indexes for this use case.
    - A clean way to log scans (IP, user-agent, datetime) without slowing down the redirect too much.

Currently I have something like this (simplified):

// Schema (Mongoose)

const DynamicLinkSchema = new mongoose.Schema({
slug: { type: String, unique: true, index: true },
targetUrl: String,
status: { type: String, default: 'active' }, // 'active', 'expired', 'blocked'
createdAt: { type: Date, default: Date.now },
expiresAt: Date,
scanCount: { type: Number, default: 0 },
lastScanAt: Date
});

// Route
app.get('/r/:slug', async (req, res) => {
const { slug } = req.params;

const link = await DynamicLink.findOne({ slug });

if (!link) {
return res.status(404).send('Not found');
}

// TODO: validate HTTPS, expiration, logging, etc.
return res.redirect(link.targetUrl);
});

Questions:

1. How would you improve this schema for a dynamic QR Code / short URL service with expiration?
2. What is the best practice to validate `targetUrl` (HTTPS only, and avoid open redirect vulnerabilities)?
3. Is there a recommended way to handle expiration (only by checking `expiresAt` on each request, or also with a background job/TTL index)?
4. How can I log scans in a performant way without blocking the redirect?

Any patterns, examples, or best practices for this kind of URL redirection service would be very helpful.

node.js mongodb