Using CounterAPI in Node.js
This guide demonstrates how to use CounterAPI in Node.js applications for tracking various metrics server-side.
Installation
To use CounterAPI in your Node.js project, first install the package:
Or with Yarn:
Basic Setup
Import the CounterAPI module and create a client:
// ES Modules (recommended)
import { Counter } from 'counterapi';
// Or using CommonJS
const { Counter } = require('counterapi');
// Create a client
const counter = new Counter({
workspace: 'my-nodejs-app', // Replace with your workspace name
debug: false, // Optional: Enable debug logging
timeout: 5000, // Optional: Request timeout in ms (default: 10000)
accessToken: 'your-token' // Optional: Authentication token for API requests (V2 API only)
});
Important: As of August 7, 2026, the V2 API is the only available version — the legacy V1 API has been deprecated and no longer accepts requests.
Simple Counter Operations
Get Current Count
async function getCurrentCount() {
try {
const result = await counter.get('api-usage');
console.log(`Current count: ${result.value}`);
return result;
} catch (error) {
console.error('Error getting count:', error.message);
throw error;
}
}
Increment Counter
async function incrementCounter() {
try {
const result = await counter.up('api-usage');
console.log(`Count after increment: ${result.value}`);
return result;
} catch (error) {
console.error('Error incrementing counter:', error.message);
throw error;
}
}
Decrement Counter
async function decrementCounter() {
try {
const result = await counter.down('api-usage');
console.log(`Count after decrement: ${result.value}`);
return result;
} catch (error) {
console.error('Error decrementing counter:', error.message);
throw error;
}
}
Integration with Express.js
Here's how to integrate CounterAPI with an Express.js application to track API endpoints usage:
import express from 'express';
import { Counter } from 'counterapi';
const app = express();
const port = process.env.PORT || 3000;
// Create CounterAPI client
const counter = new Counter({ workspace: 'my-express-app' });
// Middleware to track API usage
app.use(async (req, res, next) => {
const path = req.path.replace(/\//g, '-') || 'root';
try {
// Track endpoint usage
await counter.up(`endpoint${path}`);
} catch (error) {
// Just log error but don't block the request
console.error(`Counter error for ${path}:`, error.message);
}
next();
});
// Example routes
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.get('/api/data', (req, res) => {
res.json({ message: 'This is data' });
});
// Route to show endpoint statistics
app.get('/stats', async (req, res) => {
try {
const rootStats = await counter.get('endpoint-root');
const apiDataStats = await counter.get('endpoint-api-data');
res.json({
home: rootStats.value,
apiData: apiDataStats.value
});
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
Scheduled Tasks with Node.js
Use CounterAPI to track scheduled job executions:
import { Counter } from 'counterapi';
import cron from 'node-cron';
const counter = new Counter({ workspace: 'scheduled-tasks' });
// Function to run and track a scheduled task
async function runBackup() {
try {
console.log('Starting backup process...');
// Track that backup was started
await counter.up('backup-started');
// Simulate backup process
await someBackupFunction();
// Track successful completion
await counter.up('backup-completed');
console.log('Backup completed successfully');
} catch (error) {
// Track failures
await counter.up('backup-failed');
console.error('Backup failed:', error);
}
}
// Schedule backup to run every day at midnight
cron.schedule('0 0 * * *', runBackup);
Using with API Rate Limiting
Track and manage API rate limits:
import { Counter } from 'counterapi';
const counter = new Counter({ workspace: 'api-rate-limits' });
async function checkRateLimit(userId) {
try {
// Get current usage count
const usage = await counter.get(`user-${userId}-api-calls`);
// Check if user has exceeded limit
if (usage.value >= 100) { // 100 calls per day limit
return {
allowed: false,
current: usage.value,
message: 'Rate limit exceeded'
};
}
// Increment the usage counter
await counter.up(`user-${userId}-api-calls`);
return {
allowed: true,
current: usage.value + 1,
message: 'Request allowed'
};
} catch (error) {
console.error('Rate limit check error:', error);
// In case of error, allow the request but log the issue
return { allowed: true, message: 'Rate limit check failed' };
}
}
// Reset counters daily
async function resetDailyCounters() {
try {
// Get all user IDs (in a real app, you'd get this from your database)
const userIds = ['user1', 'user2', 'user3'];
// Reset rate limit counter for each user
for (const userId of userIds) {
// For v2 API, use reset method
await counter.reset(`user-${userId}-api-calls`);
}
console.log('Daily rate limits reset successfully');
} catch (error) {
console.error('Error resetting rate limits:', error);
}
}
Error Handling Best Practices
Implement robust error handling for production applications:
async function safeCounterOperation(operation, counterName) {
try {
const result = await operation(counterName);
return { success: true, data: result };
} catch (error) {
// Log the error with details
console.error(`Counter operation failed for '${counterName}':`, {
message: error.message,
status: error.status,
code: error.code
});
// Handle specific error scenarios
if (error.status === 429) {
// Rate limit exceeded
console.warn(`Rate limit exceeded for counter '${counterName}'`);
// Implement retry logic with exponential backoff
} else if (error.status === 404) {
// Counter doesn't exist
console.warn(`Counter '${counterName}' not found`);
// Maybe create the counter?
} else if (error.status >= 500) {
// Server error
console.error(`Server error when accessing counter '${counterName}'`);
}
return { success: false, error: error.message };
}
}
// Usage example
async function trackUserAction(userId, action) {
const counterName = `user-${userId}-${action}`;
const result = await safeCounterOperation(
name => counter.up(name),
counterName
);
if (!result.success) {
// Handle the error appropriately
// Maybe use a fallback tracking method or queue for retry
}
return result;
}
Deprecated: V1 API (no longer available)
V1 has been retired
As of August 7, 2026, the V1 API is deprecated and no longer available. The snippet below is kept for migration reference only — it will no longer work.
import { Counter } from 'counterapi';
// This client configuration is no longer functional.
const counterV1 = new Counter({
version: 'v1', // V1 API — deprecated
namespace: 'my-app', // Your namespace
debug: false,
timeout: 5000
});
async function setCounterValue(name, value) {
try {
// V1 API provided the 'set' method; use counter.reset(name, value) on V2 instead
const result = await counterV1.set(name, value);
console.log(`Counter ${name} set to ${result.value}`);
return result;
} catch (error) {
console.error(`Failed to set counter ${name}:`, error);
throw error;
}
}
Best Practices for Node.js Implementation
-
Use environment variables for configuration:
-
Implement retries for network failures:
async function counterWithRetry(operation, maxRetries = 3) { let lastError; for (let attempt = 1; attempt <= maxRetries; attempt++) { try { return await operation(); } catch (error) { lastError = error; // Only retry network-related errors if (!isNetworkError(error)) throw error; const delay = 2 ** attempt * 100; console.log(`Retry attempt ${attempt} after ${delay}ms`); await new Promise(resolve => setTimeout(resolve, delay)); } } throw lastError; } -
Batch counter operations when possible:
-
Implement graceful shutdown: