If you're reading this, you're probably running a Meteor app in production with montiapm:agent wired in, and something has nudged you to look at alternatives. This guide walks through exactly how to move to SkySignal without losing visibility, double-counting metrics, or breaking production.
Why developers are switching
Let's be honest up front: MontiAPM has been a workhorse for the Meteor community for nearly a decade. It's stable, widely deployed, and reasonably priced. For a lot of teams it's fine. If it's fine for you, you don't need this article.
Most teams who switch to SkySignal cite a combination of the following:
- The MontiAPM UI has aged. Drill-down from a slow method into the underlying pipeline is still a multi-tab dance.
- Meteor 3 support is surface-level. The removal of Fibers reshaped the internals substantially and MontiAPM's instrumentation was built around a Fibers-era world.
- Observer/publication leak detection doesn't exist. If your server memory climbs over 48 hours, MontiAPM can't tell you which subscription is leaking.
- No AI-assisted remediation. You see the problem, you go fix it alone.
- No dependency or vulnerability visibility. Your APM knows nothing about
npm auditfindings.
What stays the same
SkySignal covers the core territory you depend on MontiAPM for:
- Method tracing — every
Meteor.methodscall with timing, arguments, DB time, HTTP time, and error stacks. - Subscription metrics — per-pub response time, document counts, and throughput.
- Error tracking — server and client errors with source maps.
- System metrics — CPU, memory, event loop lag, GC pauses.
- Host topology — one container per process, visible in the dashboard with per-host metrics.
If your day-to-day use of MontiAPM is checking the methods dashboard for slow calls, you'll be at home in SkySignal in about five minutes.
What changes
New capabilities you don't have today
- Observer leak detection with a 7-signal confidence score (lifespan, updates/min, doc count, collection write frequency, DDP liveness, pub context, growth rate) rather than crude age thresholds.
- Publication efficiency — the agent wraps
Meteor.publishto detect publications that send more fields than the client actually needs (missing projections). - Deprecated API tracking — for Meteor 3 migrations, surfaces every call site still using sync APIs like
collection.find().fetch()instead offetchAsync(). - Vulnerability scanning — hourly
npm auditresults surfaced alongside performance data, so your APM is also part of your supply-chain posture. - Aggregation query support —
collection.aggregate()pipelines are traced end-to-end, with slow-pipeline capture and stage-level visibility that MontiAPM's method-only instrumentation misses entirely. - Astra AI — one-click remediation that drafts a GitHub PR for N+1 queries, missing indexes, deprecated APIs, vulnerability fixes, and more.
Step-by-step migration
1. Sign up and create a site
Create an account at dash.skysignal.app/signup. Create a "site" for your Meteor app. The dashboard will give you two keys:
- An
apiKey(server key, starts withsk_) used to authenticate agent ingest. - A
publicKey(client key, starts withpk_) used by the browser bundle for RUM and client-side error tracking.
2. Install the agent
From your Meteor project root:
meteor add skysignal:agentThen configure it in your settings-production.json:
{
"skysignal": {
"apiKey": "sk_your_server_key",
"enabled": true,
"appVersion": "1.0.0"
},
"public": {
"skysignal": {
"publicKey": "pk_your_public_key",
"rum": { "enabled": true, "sampleRate": 1.0 },
"errorTracking": {
"enabled": true
}
}
}
}The agent reads settings on boot and starts pushing metrics immediately. There is no separate init call. The public.skysignal block is only required if you want browser RUM and client-side error tracking; server-only monitoring needs just the top-level skysignal block.
3. Dual-run both agents
This is the critical step. Do not remove montiapm:agent yet. Leave both agents installed and push a production release with SkySignal enabled alongside MontiAPM.
SkySignal is designed to coexist. On startup, it detects whether montiapm:agent is loaded and automatically adjusts:
- Its
DDPQueueCollectoris auto-disabled so it doesn't compete with MontiAPM for the DDP protocol handlers object (which, by the way, is shared across sessions on the Session prototype — this is the exact place wrap-chaining bugs come from). - Its
MethodTracerskips wrappingunblockto avoid wrap-on-wrap stack growth. - System metrics, DB timing, subscription metrics, and errors continue to be collected normally — those paths don't collide.
4. Validation checklist
Run both agents side by side for at least one full week. During that window, verify:
- Method throughput in SkySignal matches MontiAPM within ~5%. Small differences are normal due to different sampling policies and slightly different start/end boundaries on async calls.
- Subscription response times track each other. If one tool shows a publication as slow and the other doesn't, dig in before cutting over.
- Error counts are in the same ballpark. SkySignal may report more errors because it catches Promise rejections from Meteor 3 async handlers that MontiAPM doesn't instrument.
- Host count matches your actual container count. Each process reports as its own host.
- Observer count looks sane. If SkySignal is showing 10,000 observers on a site that serves 500 users, that's real — MontiAPM just wasn't surfacing it. Leave it for now.
5. Cut over and remove MontiAPM
Once the numbers line up and your team trusts SkySignal's dashboard, remove MontiAPM:
meteor remove montiapm:agentShip a release, then verify that SkySignal's DDP queue metrics start appearing (they'll have been suppressed until now). Keep your MontiAPM account active but read-only for historical reference; cancel it once you've accumulated enough SkySignal history to cover your retention needs.
6. Reconfigure alerts and notifications
Alerts don't auto-migrate. Rebuild them in the SkySignal dashboard. Use this as an excuse to audit: alerts that were "noisy but important" in MontiAPM are a good candidate to re-scope or route to a different channel in SkySignal. While you're in there, enable the new alerts that MontiAPM never had:
- Observer leak confidence >= 80 (critical tier).
- Publication efficiency below your team's threshold.
- High/critical vulnerability detected by the hourly npm audit.
- Deprecated sync API usage crosses a threshold (useful when you're mid-Meteor-3-migration).
Common gotchas
Double-counted metrics during dual-run
You will briefly see two copies of "method called once": one in MontiAPM, one in SkySignal. That's expected — they are two independent observers, not a shared counter. Neither is double-counting; they're two parallel sources of truth. The work each agent does to collect its data is minimal overhead (a few microseconds of wrap-time), so dual-running for a week is safe.
settings.json shape differs
MontiAPM accepts its config either at the top level of settings or under a monti key. SkySignal always reads under Meteor.settings.skysignal (server key) and Meteor.settings.public.skysignal (browser key for RUM and client error tracking). If you deploy with environment variables instead, the agent also accepts SKYSIGNAL_API_KEY.
DDP queue collision
If you somehow manage to enable both MontiAPM's DDP tracker and SkySignal's DDPQueueCollector at the same time on Meteor 3, you can end up with a wrap chain on session.protocol_handlers that grows with each new session and eventually stack-overflows. SkySignal ships with auto-detection exactly because this used to bite dual-run customers. If you're on skysignal-agent v1.0.25 or later, you're immune by default.
CPU overhead perception
Running two agents does cost slightly more CPU than running one. It's typically under 2% on a mid-size app and is dwarfed by the cost of whatever else your methods are doing. Don't let fear of overhead make you skip the dual-run step — the migration confidence it buys you is worth much more than the CPU cost.
Galaxy-specific notes
If you deploy on Meteor Galaxy, both agents work out of the box without any host configuration — Galaxy provides the container hostname. On self-hosted deployments behind a reverse proxy, set the hostname field in settings explicitly so each container has a stable identity across restarts.
FAQ
Can I run MontiAPM and SkySignal at the same time?
Yes. That's the recommended migration path. SkySignal detects MontiAPM on startup and backs off the places where handler wrapping would collide.
Will my historical data transfer?
No. There is no supported export from MontiAPM into SkySignal. Keep your MontiAPM account read-only for as long as you need historical context, then cancel.
Does SkySignal support Meteor 2?
No. SkySignal supports Meteor 3.x only. If you're still on Meteor 2, finish the upgrade to Meteor 3 first — SkySignal's deprecated-API tracking can help you find the remaining sync call sites along the way.
How is SkySignal priced?
Per container (host). AI credits for Astra are billed separately from ingestion so your monitoring bill doesn't swing with AI usage.
What about my alerts?
Rebuild them manually. Budget 30 minutes. Use the opportunity to enable the new alert types MontiAPM doesn't have.