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 🙏

© 2026 – Pkg Stats / Ryan Hefner

mikroapm

v1.0.1

Published

Ultralight uptime monitoring with pluggable storage adapters

Readme

MikroAPM

Ultralight uptime monitoring. Checks your sites, stores failures, optionally sends email alerts via Brevo, and serves a dashboard.

MikroAPM dashboard example

Two adapters included: Cloudflare Workers + KV and Hono server + PikoDB.

Quick start

Server (Hono + PikoDB)

Create a mikroapm.config.json:

{
  "sites": [
    { "url": "https://example.com", "timeout": 10000 }
  ]
}

Start the server:

npx mikroapm

Or install globally and run:

npm install -g mikroapm
mikroapm

Open http://localhost:3000 for the dashboard.

Built-in scheduler: Health checks run automatically on startup and every minute by default. Configure the interval with CHECK_INTERVAL_MINUTES:

CHECK_INTERVAL_MINUTES=5 npx mikroapm  # Check every 5 minutes

To disable the built-in scheduler and trigger checks manually:

ENABLE_SCHEDULER=false npx mikroapm

# Then trigger manually
curl -X POST http://localhost:3000/api/check

Cloudflare Workers

Copy the example config and set your KV namespace ID:

cp wrangler.example.toml wrangler.toml
# Edit wrangler.toml and set your KV namespace ID

Deploy and configure sites via the API:

npx wrangler deploy -c wrangler.toml

curl -X POST https://your-worker.workers.dev/api/sites \
  -H "Content-Type: application/json" \
  -d '[{ "url": "https://example.com", "timeout": 10000 }]'

Health checks run on a cron schedule (default: every minute). Configure the schedule in wrangler.toml:

[triggers]
crons = ["*/5 * * * *"]          # Every 5 minutes

[vars]
CHECK_INTERVAL_MINUTES = "5"     # Must match cron frequency!
ENABLE_SUMMARY_WRITES = "false"  # Optional: disable for max efficiency

Important: CHECK_INTERVAL_MINUTES must match your cron frequency for accurate uptime calculations.

Cost optimization: Set ENABLE_SUMMARY_WRITES = "false" to stay within KV free tier with 1-minute intervals (near-zero writes for healthy sites).

Configuration

MikroAPM uses a unified configuration system with precedence: environment variables > config file > defaults. This works consistently across both adapters.

Config file (optional, recommended for server)

Create mikroapm.config.json to define sites and default settings. The config is validated using MikroValid.

{
  "sites": [
    { "url": "https://example.com", "timeout": 10000, "alertEmail": "[email protected]" },
    { "url": "https://api.example.com/health", "timeout": 5000 }
  ],
  "checkIntervalMinutes": 1,
  "enableSummaryWrites": true,
  "alerts": {
    "threshold": 3,
    "fromEmail": "[email protected]",
    "fromName": "MikroAPM",
    "toEmail": "[email protected]"
  }
}

Config options:

  • sites — required, at least one entry. Each site needs a url; timeout (ms) and alertEmail are optional.
  • checkIntervalMinutes — optional, defaults to 1. How often health checks run (in minutes).
    • For the Hono server, this controls the built-in scheduler.
    • For Cloudflare Workers, this must match your cron schedule in wrangler.toml.
  • enableSummaryWrites — optional, defaults to true.
    • Set to false to disable daily summary writes for maximum cost efficiency. Dashboard will show minimal data (only failures), but write operations are drastically reduced.
  • alerts — entirely optional. Omit this section to disable alerting.
    • If present, the Brevo API key must be set as an environment variable: BREVO_API_KEY=your-key.

Environment Variables

All configuration options can be set via environment variables. Environment variables always override config file values.

Core Settings

| Variable | Description | Default | Applies To | |--------------------------|----------------------------------------------|---------|------------| | CHECK_INTERVAL_MINUTES | Health check interval in minutes | 1 | Both | | ENABLE_SUMMARY_WRITES | Enable daily summary writes (true/false) | true | Both | | BREVO_API_KEY | Brevo API key for email alerts | — | Both |

Alert Settings

| Variable | Description | Default | Applies To | |--------------------|----------------------------------------------------------|-------------------------|------------| | ALERT_THRESHOLD | Consecutive failures before alerting | 3 | Both | | ALERT_FROM_EMAIL | Sender email address | [email protected] | Both | | ALERT_FROM_NAME | Sender name | MikroAPM | Both | | ALERT_TO_EMAIL | Default recipient (fallback if site has no alertEmail) | — | Both |

Server-Specific Settings

| Variable | Description | Default | |--------------------|-----------------------------------|--------------------------| | ENABLE_SCHEDULER | Enable built-in scheduler | true | | PORT | Server port | 3000 | | CONFIG_PATH | Path to config file | ./mikroapm.config.json | | DB_PATH | Path to PikoDB database directory | ./data/mikroapm |

Configuration examples:

Server with config file:

BREVO_API_KEY=your-key npx mikroapm

Server with environment variables only:

ALERT_THRESHOLD=5 \
[email protected] \
[email protected] \
BREVO_API_KEY=your-key \
npx mikroapm

Cloudflare Workers (in wrangler.toml):

[vars]
CHECK_INTERVAL_MINUTES = "5"
ALERT_THRESHOLD = "3"
ALERT_FROM_EMAIL = "[email protected]"
ALERT_FROM_NAME = "MikroAPM"
ALERT_TO_EMAIL = "[email protected]"

# Set secret via: npx wrangler secret put BREVO_API_KEY

How check counting works

MikroAPM calculates total checks based on elapsed time rather than storing individual check results. Each check cycle updates a daily summary (not individual check records), minimizing storage usage for cost-sensitive environments like Cloudflare Workers with KV.

The summary writes can be trimmed to near-zero; see below for details.

Calculation method

Check counts are calculated as:

checksToday = floor((now - effectiveStart) / checkInterval)

Where effectiveStart is the most recent of:

  • Start of the current day (00:00 UTC)
  • When monitoring first began for this domain
  • When the service/worker last started (for mid-day restarts)

What gets written per check cycle

When ENABLE_SUMMARY_WRITES=true (default):

Each check cycle (e.g., every minute) writes:

  • 1 update: Daily summary for each monitored site (summary:domain:date) — updates failure count and last-checked timestamp
  • 1 write per failure: Failure record only when a check fails (failure:domain:date:time:timestamp)
  • 1 write on first check: Monitoring start timestamp per domain (one-time, persisted)

When ENABLE_SUMMARY_WRITES=false:

Each check cycle writes:

  • 0 writes for successful checks
  • 1 write per failure only
  • 1 write on first check: Monitoring start timestamp per domain (one-time, persisted)

Key insight: Individual successful check results are NOT stored as separate records. The total check count is derived from time elapsed, not by counting stored records.

Cost implications for Cloudflare Workers

With Cloudflare KV:

  • Free tier: 1,000 writes/day, 100,000 reads/day
  • 1 site @ 1-min interval: ~1,440 writes/day (exceeds free tier by 44%)
  • 1 site @ 3-min interval: ~480 writes/day (well within free tier)
  • 1 site @ 5-min interval: ~288 writes/day (well within free tier)
  • With failures: Additional 1 write per failed check

Recommendation: Use CHECK_INTERVAL_MINUTES of 3 or 5 to stay comfortably within free tier limits. A 5-minute interval still provides useful uptime tracking while allowing you to monitor 3+ sites without exceeding the free tier.

Maximum efficiency: Set ENABLE_SUMMARY_WRITES=false to disable daily summary writes entirely. This reduces writes to near-zero for healthy sites (only failures + one-time monitoring start). Trade-off: Dashboard will show "N/A" for uptime/check counts; only failure history will be visible. Best for alert-focused monitoring where dashboard visibility is not important.

API

| Method | Path | Description | |--------|-------------------------------|-------------------------------------------------------| | GET | / | Dashboard UI | | GET | /mydomain.com | Dashboard UI: For site mydomain.com | | GET | /mydomain.com?days=7 | Dashboard UI: For site mydomain.com (7 day period) | | GET | /mydomain.com?days=30 | Dashboard UI: For site mydomain.com (30 day period) | | GET | /mydomain.com?days=90 | Dashboard UI: For site mydomain.com (90 day period) | | GET | /api/uptime/:domain?days=30 | Uptime stats for a domain | | GET | /api/failures/:domain/:date | Failure details for a specific day | | GET | /api/sites | List monitored sites | | POST | /api/sites | Update monitored sites | | POST | /api/check | Trigger health check (server only) | | POST | /api/cleanup | Clean up expired records (server only) |

Building

npm run build              # Both targets
npm run build:server       # Hono server → dist/server.js
npm run build:workers      # CF Workers → dist/workers.js

Project structure

mikroapm.config.json       # Site + alert configuration (server)
src/
  core/
    ConfigManager.js       # Loads + validates config (file or env)
    HealthCheckService.js  # Runs checks, stores failures, triggers alerts
    AlertService.js        # Email alerts via Brevo (optional)
    DashboardService.js    # Queries uptime data for the dashboard
  storage/
    StorageInterface.js    # Interface (get/put/delete/list)
    KVStorage.js           # Cloudflare KV
    PikoDBStorage.js       # PikoDB (file-based)
  adapters/
    cf-workers/            # Cloudflare Workers (scheduled + fetch)
    hono-server/           # Hono on Node.js
    dashboard-template.js  # Shared dashboard HTML
examples/
  cf-workers/worker.js     # Workers entry point
  server/dev.js            # Dev server
  server/start.js          # Production server

Dependencies

The project uses these bundled dependencies:

The rendered UI has a link to the Inter font family to make the site look pretty. You can remove it from the dashboard template if you want complete runtime isolation. Just remove:

<link rel="preconnect" href="https://rsms.me/">
<link rel="stylesheet" href="https://rsms.me/inter/inter.css">

License

MIT