npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@abstraks-dev/mongodb-connection

v1.0.1

Published

MongoDB connection manager with caching and middleware for Lambda functions

Downloads

224

Readme

@abstraks-dev/mongodb-connection

MongoDB connection management for AWS Lambda functions with automatic caching, Secrets Manager integration, and middleware support.

Features

  • 🔄 Automatic Connection Caching - Reuses connections across Lambda invocations
  • 🔐 AWS Secrets Manager Integration - Securely fetch MongoDB URI from Secrets Manager
  • 🛡️ Environment-aware - Supports dev/prod environments
  • 🎯 Lambda Middleware - Easy-to-use middleware pattern for Lambda handlers
  • 📊 Connection Statistics - Monitor connection health and status
  • Performance Optimized - Minimizes cold starts with efficient caching

Installation

npm install @abstraks-dev/mongodb-connection mongoose

Required Peer Dependencies:

  • mongoose - MongoDB ODM

Quick Start

Basic Usage

import { createMongoDBConnection } from '@abstraks-dev/mongodb-connection';
import { getSecret } from './secrets.js'; // Your Secrets Manager helper

// Create connection instance
const { connection, connectDB, withDBConnection } = createMongoDBConnection(
	'auth', // service name
	getSecret // secret retrieval function
);

// Connect manually
await connectDB();

// Use in Lambda handler with middleware
const myHandler = async (event, context, callback) => {
	// MongoDB is already connected by middleware
	const users = await User.find();
	return { statusCode: 200, body: JSON.stringify(users) };
};

export const handler = withDBConnection(myHandler);

Direct URI Usage

import { createSimpleConnection } from '@abstraks-dev/mongodb-connection';

const { connection, connectDB } = createSimpleConnection(
	'mongodb://localhost:27017/mydb'
);

await connectDB();

API Reference

createMongoDBConnection(serviceName, getSecret, options)

Factory function that creates a MongoDB connection with helpers.

Parameters:

  • serviceName (string, required) - Service name for Secrets Manager lookup
  • getSecret (function, required) - Async function to retrieve secrets: (secretName, key) => Promise<string>
  • options (object, optional):
    • mongoURI - Direct MongoDB URI (bypasses Secrets Manager)
    • environment - Environment name (default: process.env.ENVIRONMENT || 'dev')

Returns:

{
  connection: MongoDBConnection,
  connectDB: () => Promise<MongooseClient>,
  withDBConnection: (handler) => WrappedHandler
}

Example:

// auth/service/helpers/connectDB.js
import { createMongoDBConnection } from '@abstraks-dev/mongodb-connection';
import { getSecret } from './secrets.js';

export const { connection, connectDB, withDBConnection } =
	createMongoDBConnection('auth', getSecret);

createSimpleConnection(mongoURI)

Factory function for simple connections with direct URI.

Parameters:

  • mongoURI (string, required) - MongoDB connection string

Returns:

{
  connection: MongoDBConnection,
  connectDB: () => Promise<MongooseClient>
}

Example:

import { createSimpleConnection } from '@abstraks-dev/mongodb-connection';

const { connectDB } = createSimpleConnection(
	process.env.MONGO_URI || 'mongodb://localhost:27017/dev'
);

await connectDB();

MongoDBConnection Class

Core connection manager class.

Constructor

new MongoDBConnection(options);

Options:

  • serviceName (string, required) - Service name
  • getSecret (function, optional) - Secret retrieval function
  • mongoURI (string, optional) - Direct MongoDB URI
  • environment (string, optional) - Environment name (default: 'dev')

Methods

connect(): Promise<MongooseClient>

Connects to MongoDB. Automatically caches connection across Lambda invocations.

const client = await connection.connect();

Connection Priority:

  1. Direct mongoURI option
  2. process.env.MONGO_URI
  3. Secrets Manager lookup using serviceName and environment

Throws:

  • Error if no MongoDB URI found
  • Error if connection fails
disconnect(): Promise<void>

Disconnects from MongoDB and clears cache.

await connection.disconnect();
isConnected(): boolean

Checks if connection is active.

if (connection.isConnected()) {
	console.log('Connected!');
}
getConnection(): MongooseClient | null

Returns cached Mongoose client or null.

const client = connection.getConnection();
getConnectionState(): number

Returns Mongoose connection state:

  • 0 = disconnected
  • 1 = connected
  • 2 = connecting
  • 3 = disconnecting
const state = connection.getConnectionState();
getStats(): object

Returns connection statistics.

const stats = connection.getStats();
// {
//   serviceName: 'auth',
//   environment: 'dev',
//   isConnected: true,
//   readyState: 1,
//   hasCache: true
// }

Usage Patterns

Pattern 1: Lambda Middleware (Recommended)

The easiest way to use with Lambda functions:

// helpers/connectDB.js
import { createMongoDBConnection } from '@abstraks-dev/mongodb-connection';
import { getSecret } from './secrets.js';

export const { withDBConnection } = createMongoDBConnection('auth', getSecret);

// lambdas/getUser.js
import { withDBConnection } from '../helpers/connectDB.js';
import User from '../models/User.js';

const getUserHandler = async (event, context, callback) => {
	// MongoDB connected automatically
	const user = await User.findById(event.pathParameters.id);

	callback(null, {
		statusCode: 200,
		body: JSON.stringify(user),
	});
};

export const handler = withDBConnection(getUserHandler);

Benefits:

  • Automatic connection before handler runs
  • Proper error handling with Lambda responses
  • Works with both callback and return patterns

Pattern 2: Manual Connection

For more control over connection timing:

import { createMongoDBConnection } from '@abstraks-dev/mongodb-connection';
import { getSecret } from './secrets.js';

const { connectDB } = createMongoDBConnection('social', getSecret);

export const handler = async (event, context) => {
	try {
		// Connect when needed
		await connectDB();

		// Your logic here
		const posts = await Post.find();

		return {
			statusCode: 200,
			body: JSON.stringify(posts),
		};
	} catch (error) {
		return {
			statusCode: 500,
			body: JSON.stringify({ error: error.message }),
		};
	}
};

Pattern 3: Shared Instance

Share connection across multiple files:

// helpers/db.js
import { createMongoDBConnection } from '@abstraks-dev/mongodb-connection';
import { getSecret } from './secrets.js';

export const { connection, connectDB, withDBConnection } =
	createMongoDBConnection('media', getSecret);

// controllers/media.controllers.js
import { connection } from '../helpers/db.js';

export async function getMediaStats() {
	// Check connection state
	if (!connection.isConnected()) {
		await connection.connect();
	}

	return await Media.countDocuments();
}

// lambdas/getMedia.js
import { withDBConnection } from '../helpers/db.js';

const handler = async (event) => {
	// Connection managed by middleware
	const media = await Media.find();
	return { statusCode: 200, body: JSON.stringify(media) };
};

export default withDBConnection(handler);

Environment Configuration

Development

// Use local MongoDB or environment variable
process.env.MONGO_URI = 'mongodb://localhost:27017/auth-dev';

const { connectDB } = createMongoDBConnection('auth', getSecret, {
	environment: 'dev',
});

Production

// Use AWS Secrets Manager
// Creates connection that will fetch from:
// Secret: "auth-prod"
// Key: "MONGO_URI"

const { connectDB } = createMongoDBConnection('auth', getSecret, {
	environment: 'prod',
});

Direct URI

// Bypass Secrets Manager entirely
const { connectDB } = createMongoDBConnection('auth', getSecret, {
	mongoURI: 'mongodb://your-cluster.mongodb.net/production',
});

Error Handling

The library throws descriptive errors for common issues:

try {
	await connectDB();
} catch (error) {
	if (error.message.includes('MONGO_URI not found')) {
		console.error('MongoDB URI not configured');
	} else if (error.message.includes('Error connecting')) {
		console.error('Connection failed:', error);
	}
}

Migration from Service-Specific Code

Before (Duplicated in each service)

// auth/service/helpers/connectDB.js
import mongoose from 'mongoose';
import { getSecret } from './secrets.js';

mongoose.set('strictQuery', false);
let cachedClient = null;

export const connectDB = async () => {
	if (cachedClient && mongoose.connection.readyState === 1) {
		return cachedClient;
	}

	const environment = process.env.ENVIRONMENT || 'dev';
	const mongoURI =
		process.env.MONGO_URI ||
		(await getSecret(`auth-${environment}`, 'MONGO_URI'));

	if (!mongoURI) {
		throw new Error(`MONGO_URI not found`);
	}

	const client = await mongoose.connect(mongoURI);
	cachedClient = client;
	return client;
};

After (Using shared module)

// auth/service/helpers/connectDB.js
import { createMongoDBConnection } from '@abstraks-dev/mongodb-connection';
import { getSecret } from './secrets.js';

export const { connection, connectDB, withDBConnection } =
	createMongoDBConnection('auth', getSecret);

Savings: ~30 lines of code → 3 lines

Best Practices

1. Reuse Connection Instances

// ✅ Good - Create once, reuse everywhere
// helpers/db.js
export const { connectDB, withDBConnection } = createMongoDBConnection(...);

// ❌ Bad - Creates new instance each time
export function getConnection() {
  return createMongoDBConnection(...);
}

2. Use Middleware for Lambda Handlers

// ✅ Good - Automatic connection management
export const handler = withDBConnection(async (event) => {
	// Connection guaranteed
});

// ❌ Okay but more verbose
export const handler = async (event) => {
	await connectDB();
	// Connection manual
};

3. Check Connection State for Background Jobs

// ✅ Good - Verify before long-running operations
async function processQueue() {
	if (!connection.isConnected()) {
		await connection.connect();
	}

	// Process items
}

4. Handle Secrets Manager Errors

// ✅ Good - Graceful error handling
try {
	await connectDB();
} catch (error) {
	console.error('Failed to connect:', error);
	// Fallback or alert
}

Testing

Mocking in Tests

import { jest } from '@jest/globals';

// Mock mongoose
const mockMongoose = {
	set: jest.fn(),
	connect: jest.fn(),
	disconnect: jest.fn(),
	connection: { readyState: 0 },
};

jest.unstable_mockModule('mongoose', () => ({ default: mockMongoose }));

// Mock secret retrieval
const mockGetSecret = jest
	.fn()
	.mockResolvedValue('mongodb://localhost:27017/test');

// Import and test
const { connectDB } = await import('@abstraks-dev/mongodb-connection');
const connection = createMongoDBConnection('test', mockGetSecret);

Troubleshooting

"MONGO_URI not found" Error

Cause: No MongoDB URI found in any source

Solutions:

  1. Set process.env.MONGO_URI
  2. Ensure Secrets Manager has correct secret name format: {serviceName}-{environment}
  3. Pass direct URI via options: { mongoURI: '...' }

Connection Cached from Previous Lambda

Cause: Connection reuse across invocations (this is intentional for performance)

Solution: This is expected behavior. Connection is automatically reused. If you need to force reconnect:

await connection.disconnect();
await connection.connect();

Mongoose StrictQuery Warnings

Cause: Mongoose version differences

Solution: The library automatically sets mongoose.set('strictQuery', false). No action needed.

Performance Considerations

  • Cold Start: First connection takes ~500ms
  • Warm Start: Cached connection is instant (<1ms)
  • Memory: ~10MB per connection (Mongoose overhead)
  • Invocations: Connection persists across Lambda invocations in same container

License

MIT

Related Packages

Support

For issues and questions: