Aller au contenu principal
Retour au blog

Lancer son SaaS Symfony — Partie 3 : Déploiement et premiers clients

Flavien Métivier7 avril 20268 min

Ton MVP est prêt, tes tests passent, ton code est propre. Il est temps de franchir le cap le plus excitant : mettre ton SaaS entre les mains de vrais utilisateurs. Dans cette troisième et dernière partie de notre série, on couvre le déploiement, le monitoring et l'acquisition de tes premiers clients.

Infrastructure : VPS, PaaS ou Cloud ?

Le choix de l'infrastructure dépend de ton budget et de ton ambition. Voici les trois options principales, avec leurs trade-offs pour un SaaS Symfony en phase de lancement.

  • VPS (Hetzner, OVH, DigitalOcean) — 10-40 EUR/mois. Tu gères tout : OS, reverse proxy, SSL, backups. Maximum de contrôle, mais aussi maximum de maintenance. Idéal si tu es à l'aise en DevOps.
  • PaaS (Platform.sh, Railway, Render) — 25-100 EUR/mois. Déploiement en un push git. Moins de contrôle, mais tu peux te concentrer sur le produit. Recommandé pour un solo founder.
  • Cloud managé (AWS, GCP) — Variable. Scalabilité infinie, mais complexité et coût qui explosent vite. À réserver quand tu as des problèmes de scale (beau problème à avoir).

Pour un lancement, le VPS avec Docker reste le meilleur rapport coût/contrôle. Voici un docker-compose.yml de production minimal.

# docker-compose.prod.yml
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
      target: production
    environment:
      APP_ENV: prod
      DATABASE_URL: postgresql://app:${DB_PASSWORD}@postgres:5432/saas
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    restart: unless-stopped

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
      - ./public:/app/public:ro
    depends_on:
      - app

  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: saas
      POSTGRES_USER: app
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - pg_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s

volumes:
  pg_data:

Pipeline CI/CD : du commit à la production

Un pipeline CI/CD fiable est non négociable, même en solo. Il te protège de toi-même à 2h du matin. Voici le workflow GitHub Actions que nous utilisons sur nos projets SaaS.

# .github/workflows/deploy.yml
name: Deploy

on:
  push:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:16-alpine
        env:
          POSTGRES_DB: test_db
          POSTGRES_USER: test
          POSTGRES_PASSWORD: test
        ports: ["5432:5432"]
    steps:
      - uses: actions/checkout@v4
      - uses: shivammathur/setup-php@v2
        with:
          php-version: "8.3"
          coverage: xdebug
      - run: composer install --no-interaction
      - run: composer cs-check
      - run: composer phpstan
      - run: composer test-coverage
        env:
          DATABASE_URL: postgresql://test:test@127.0.0.1:5432/test_db

  deploy:
    needs: test
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v4
      - name: Deploy via SSH
        run: |
          ssh deploy@${{ secrets.SERVER_IP }} \
            "cd /app && git pull && docker compose -f docker-compose.prod.yml up -d --build"

Monitoring : ne pas voler à l'aveugle

Un SaaS en production sans monitoring, c'est comme conduire de nuit sans phares. Trois outils essentiels dès le jour 1 :

  • Sentry — Error tracking en temps réel. Le bundle sentry/sentry-symfony s'installe en 2 minutes. Tu seras notifié de chaque exception avant que tes clients ne la voient.
  • Logs structurés — Configure Monolog pour écrire en JSON. Un grep sur des logs structurés vaut 100 fois un tail -f sur du texte brut.
  • Health check endpoint — Un /health qui vérifie la BDD, Redis et le filesystem. Couple-le à un service de monitoring externe (UptimeRobot, gratuit).

Besoin d'un expert Symfony ?

Réserver un appel
<?php
// src/Controller/HealthController.php
declare(strict_types=1);

namespace App\Controller;

use Doctrine\DBAL\Connection;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Attribute\Route;

#[Route('/health', methods: ['GET'])]
final class HealthController
{
    public function __construct(
        private readonly Connection $connection,
    ) {}

    public function __invoke(): JsonResponse
    {
        try {
            $this->connection->executeQuery('SELECT 1');
            $dbOk = true;
        } catch (\Throwable) {
            $dbOk = false;
        }

        $status = $dbOk ? 'ok' : 'degraded';

        return new JsonResponse(
            ['status' => $status, 'database' => $dbOk],
            $dbOk ? 200 : 503,
        );
    }
}

Premiers clients : le programme beta

Tes premiers clients sont les plus importants de toute l'histoire de ton produit. Ils vont te dire ce qui fonctionne, ce qui est confus et ce qui manque. Voici comment structurer ton lancement.

  • Cible 10-20 beta testeurs — Pas plus. Tu veux du feedback de qualité, pas du volume. Recrute dans ton réseau, sur Twitter/X, dans les communautés Slack de ta niche.
  • Onboarding personnel — Appelle chaque beta testeur. 15 minutes pour comprendre son besoin et l'aider à démarrer. Tu apprendras plus en 10 appels qu'en 1 000 analytics.
  • Feedback loop court — Un canal Slack ou Discord dédié. Réponds en moins de 24h. Chaque bug reporté est un cadeau.
  • Pricing beta — Offre 50% de réduction ou 3 mois gratuits, mais ne donne pas le produit gratuitement. Un utilisateur qui ne paie rien ne te donnera jamais de feedback honnête.

Pricing : freemium ou paid-only ?

Le freemium a un coût caché énorme : support, infrastructure et distraction. Pour un SaaS B2B bootstrappé, le paid-only avec essai gratuit de 14 jours est presque toujours le meilleur choix. Tu filtres les curieux et tu attires des utilisateurs qui ont un vrai problème à résoudre.

Métriques à suivre dès le jour 1

  • MRR (Monthly Recurring Revenue) — La seule métrique qui compte vraiment. Objectif : atteindre 1 000 EUR MRR le plus vite possible.
  • Taux d'activation — Quel % des inscrits réalise l'action clé (ex : créer leur premier projet) ? Cible : > 40%.
  • Churn mensuel — Quel % des clients annule chaque mois ? En dessous de 5%, tu es dans le vert.
  • NPS (Net Promoter Score) — Demande à tes utilisateurs s'ils recommanderaient ton produit. Un NPS > 50, c'est excellent.

Growth : les canaux qui marchent

Pas besoin de budget marketing au lancement. Les trois canaux les plus efficaces pour un SaaS technique sont le SEO (articles de blog ciblés sur les problèmes que tu résous), le content marketing (partage ta méthodologie, tes outils, ta roadmap) et le product-led growth (rends ton produit tellement bon que tes utilisateurs en parlent). Le bouche-à-oreille technique est le meilleur canal d'acquisition qui existe.

Tu as maintenant tous les éléments pour passer de l'idée au premier euro de MRR. Si tu veux accélérer le développement de ton MVP Symfony, Bear MVP te livre un produit fonctionnel, testé et déployé en quelques semaines. Tu te concentres sur tes clients, on s'occupe du code.

Cet article vous a plu ? Partagez-le !

Besoin d'un expert Symfony ?

20 ans d'expérience sur l'écosystème PHP/Symfony.