Pour un SaaS B2B, l'observabilité = différence entre 4.7 NPS et 3.2 NPS. Une erreur non détectée pendant 6h = clients qui annulent. Ce guide pose la stack monitoring 2026 testée sur kolonell.com et 12 SaaS clients.
TL;DR
- Sentry : erreurs front + back, performance monitoring.
- BetterStack (anciennement Better Uptime) : uptime + log management.
- Plausible / PostHog : analytics privacy-friendly.
- Alerting : Slack + WhatsApp critical only.
Stack monitoring complète
`
[App Next.js]
├── @sentry/nextjs (errors + performance)
├── @vercel/analytics (web vitals)
└── PostHog ou Plausible (product analytics)
[Backend]
├── @sentry/node (errors)
├── pino + Better Stack Logs (logs)
└── Prometheus + Grafana (metrics avancés)
[Infrastructure]
├── BetterStack (uptime monitoring)
├── Cloudflare Analytics (edge metrics)
└── Datadog (advanced enterprise)
[Alerting]
├── Slack (notifications standard)
├── WhatsApp (critical only via Twilio)
└── PagerDuty (Enterprise SLA)
`
Étape 1 — installer Sentry
`bash
pnpm add @sentry/nextjs
npx @sentry/wizard@latest -i nextjs
`
`ts
// sentry.client.config.ts
import * as Sentry from '@sentry/nextjs';
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
environment: process.env.NODE_ENV,
tracesSampleRate: 1.0, // 100% en dev, 10% en prod
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0,
integrations: [
Sentry.replayIntegration({ maskAllText: false, blockAllMedia: false }),
],
});
`
`ts
// sentry.server.config.ts
import * as Sentry from '@sentry/nextjs';
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.NODE_ENV,
tracesSampleRate: process.env.NODE_ENV === 'production' ? 0.1 : 1.0,
beforeSend(event, hint) {
// Redact sensitive data
if (event.request?.headers) {
delete event.request.headers['authorization'];
delete event.request.headers['cookie'];
}
return event;
},
});
`
Étape 2 — context utilisateur + tenant
Critique pour SaaS B2B : associer chaque erreur au tenant impacté.
`ts
// middleware.ts ou layout
import * as Sentry from '@sentry/nextjs';
export async function middleware(req: NextRequest) {
const session = await getSession(req);
if (session) {
Sentry.setUser({
id: session.user.id,
email: session.user.email,
});
Sentry.setTag('organization_id', session.organizationId);
Sentry.setTag('plan', session.organization.plan);
}
}
`
Avec ce contexte, vous pouvez voir : "L'erreur X impacte 14 tenants Pro et 3 Enterprise".
Étape 3 — capture custom
`ts
// API route avec capture custom
export async function POST(req: Request) {
try {
const data = await processOrder(req);
return Response.json(data);
} catch (error) {
Sentry.withScope(scope => {
scope.setTag('feature', 'order_processing');
scope.setExtra('orderId', data.orderId);
scope.setLevel('error');
Sentry.captureException(error);
});
return Response.json({ error: 'Failed' }, { status: 500 });
}
}
`
Étape 4 — performance monitoring
`ts
import { withSentryConfig } from '@sentry/nextjs';
export default withSentryConfig({
// Next config
}, {
silent: true,
org: 'kolonell',
project: 'app',
widenClientFileUpload: true,
reactComponentAnnotation: { enabled: true },
hideSourceMaps: true,
disableLogger: true,
});
`
Auto-instrumented :
Besoin d'un site web professionnel ?
Kolonell crée des sites web qui attirent des clients, optimisés pour le marché sénégalais. Devis gratuit en 2 minutes.
- API route latency
- DB queries (avec @sentry/profiling-node)
- React component render time
- Web Vitals (LCP, INP, CLS)
Étape 5 — uptime monitoring (BetterStack)
- Aller sur betterstack.com
- Créer monitor : URL = https://app.kolonell.com/api/health
- Frequency : 30 sec
- Régions : Frankfurt, Singapore, US East
- Alerts : Slack + WhatsApp critical
- Status page publique (optionnel)
`ts
// app/api/health/route.ts
export async function GET() {
// Vérifier dépendances critiques
const checks = await Promise.allSettled([
prisma.$queryRawSELECT 1,
redis.ping(),
fetch('https://api.stripe.com/healthcheck'),
]);
const allOk = checks.every(c => c.status === 'fulfilled');
return Response.json({
status: allOk ? 'healthy' : 'degraded',
timestamp: new Date().toISOString(),
checks: checks.map((c, i) => ({
service: ['db', 'redis', 'stripe'][i],
ok: c.status === 'fulfilled',
})),
}, {
status: allOk ? 200 : 503,
});
}
`
Étape 6 — logs structurés (Pino + BetterStack)
`ts
// lib/logger.ts
import pino from 'pino';
export const logger = pino({
level: process.env.LOG_LEVEL ?? 'info',
transport: process.env.NODE_ENV === 'development'
? { target: 'pino-pretty' }
: undefined,
base: {
env: process.env.NODE_ENV,
service: 'kolonell-app',
},
});
// Usage
logger.info({ orderId, userId }, 'Order created');
logger.error({ err, orderId }, 'Order processing failed');
`
Configuration BetterStack Logs : forward production logs vers leur SaaS pour search + alerting.
Étape 7 — analytics produit (PostHog)
`tsx
// app/posthog-provider.tsx
'use client';
import posthog from 'posthog-js';
import { PostHogProvider } from 'posthog-js/react';
import { useEffect } from 'react';
if (typeof window !== 'undefined') {
posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {
api_host: process.env.NEXT_PUBLIC_POSTHOG_HOST,
person_profiles: 'identified_only',
});
}
export function PHProvider({ children }) {
return
}
`
`tsx
// Dans composants
import { usePostHog } from 'posthog-js/react';
const posthog = usePostHog();
posthog.capture('subscription_started', {
plan: 'pro',
amount: 25000,
currency: 'XOF',
});
`
PostHog gratuit jusqu'à 1M events/mois. Au-delà $0.0003/event.
Étape 8 — alerting WhatsApp critical
`ts
// lib/alerts.ts
async function alertCritical(message: string, context: any) {
// Slack always
await sendSlack({ channel: '#critical', message, context });
// WhatsApp seulement si vraiment critique
if (context.severity === 'critical') {
await sendWhatsApp({
to: process.env.ONCALL_PHONE!,
template: 'critical_alert',
params: [message, context.timestamp],
});
}
}
// Triggers
// - Site down > 2 min
// - Database unreachable
// - Stripe webhook failed > 5 min
// - Error rate > 5 % sur 5 min
`
Coûts mensuels typiques
| Outil | Free tier | Plan PME | Plan startup scale |
|---|---|---|---|
| Sentry | 5K errors/mois | $26/mo (50K errors) | $80/mo (250K) |
| BetterStack | 10 monitors | $25/mo | $80/mo |
| PostHog | 1M events | $0 | $50-200/mo (10M+) |
| Plausible | 30j trial | $9/mo (10K) | $69/mo (1M) |
| Slack | Free | $7/mo/user | $7/mo/user |
| Total mensuel | $0 | $50-100 | $200-400 |
Cas réel — SaaS Dakar (350 tenants)
| Avant monitoring | Après 6 mois | |
|---|---|---|
| MTTR (mean time to resolve) | 4-8 heures | 25 min |
| Bugs non-reportés / mois | 12-15 | 1-2 |
| Customer-reported issues | 22 % | 3 % |
| Uptime | 99.2 % | 99.95 % |
| NPS | 38 | 67 |
ROI monitoring : ~+15K MRR/mois grâce à churn baissé.
Pièges fréquents
- Tracer trop = noise — sample 10 % en prod, 100 % en dev.
- Pas de masking PII — emails, IDs en logs = leak data RGPD.
- Alertes alarmistes — un simple 500 réveille pas l'équipe à 3h. Critical = real critical.
- Pas de lien Sentry → ticket — automatiser création Linear/Notion sur erreurs récurrentes.
- Monitoring jamais review — semainement passer en revue dashboards.
FAQ
Q : Datadog vs Sentry ?
R : Sentry = errors-first, Datadog = ops-first. Pour SaaS B2B startup, Sentry suffit. Datadog dès Enterprise + infrastructure complexe.
Q : Self-host Sentry ?
R : Sentry self-hosted gratuit mais 4-8 GB RAM serveur dédié. À l'échelle d'un solo SaaS : SaaS Sentry rentable.
Q : Quelles métriques au minimum ?
R : Error rate, P95 latency, Uptime, Stripe webhook success rate, DB connection pool.
Conclusion
Stack monitoring SaaS B2B 2026 = $50-200/mois mais évite 10-100x plus de churn. Setup initial 1-2 semaines. Maintenance continue 1-2h/sem. Standard 2026 incontournable pour SaaS sérieux.
Mohamed Bah
Fondateur, Kolonell
Passionné par le digital et l'entrepreneuriat en Afrique, Mohamed accompagne les entreprises sénégalaises dans leur transformation digitale depuis 2020. Fondateur de Kolonell, il croit que chaque PME mérite une présence en ligne professionnelle et accessible.