🏢

1人では保守できない複雑さに自動化で挑む:マルチテナントSaaS開発記【第1回】

に公開
2025/12/26

この記事で得られること

  • 「1人で作れる規模」を超えたシステムに挑む際の考え方
  • 複雑なマルチテナントシステムの設計概要
  • 手動テストゼロを実現する自動化戦略

はじめに

「1人で保守できないものは作るな」

ソロ開発の鉄則だと思う。でも、あえてその限界に挑戦してみたくなった。

AIコーディングエージェント(Claude Code、GitHub Copilot等)を数カ月実務で使ってきて、「これなら1人でも複雑なものを作れるかもしれない」と思い始めた。ただし条件がある。徹底的な自動化だ。

このブログでは、マルチテナント型サブスクリプション管理システム「Saru」の開発記録を残していく。複雑なシステムを1人で作り切るために、何を自動化し、どう設計したかを共有する。

なぜ「保守できない複雑さ」に挑むのか

  • AIコーディングエージェントで「ちょっとしたもの」ではなく「本格的なもの」を作ってみたい
  • 1人では普通作れない規模のシステムに、自動化でどこまで対抗できるか試したい
  • 失敗しても学びになる。成功すれば再現可能なノウハウになる

Saruの複雑さ

4階層のアカウント構造

一般的なSaaSは「管理者 → ユーザー」の2階層。Saruは4階層ある。

階層 役割 説明
System プラットフォーム管理 全体を統括
Provider サービス提供 SaaSや商品を提供
Reseller 販売代理 Providerのサービスを販売
Consumer 購入・利用 サブスクリプションを購入

さらに:

  • ResellerがPROVIDE権限を持つと独自サービスも提供可能
  • ConsumerがPROVIDE権限を持つとCreator(個人事業者)になれる

この柔軟性が複雑さの源泉であり、差別化ポイントでもある。

4ポータル × 4API

各階層に専用のフロントエンドとAPIがある。

ポータル API ポート
System Portal system-api 3001 / 8080
Provider Portal provider-api 3002 / 8081
Reseller Portal reseller-api 3003 / 8082
Customer Portal customer-api 3004 / 8083

ポータルは動的サブドメインで分離(例: provider-xxx.example.com)

その他の複雑さ

  • 認証: Keycloak統合、WebAuthnパスキー、OTP認証、ポータル間セッション分離
  • データ分離: PostgreSQL Row-Level Security(RLS)によるマルチテナント分離
  • 権限制御: Capabilityモデル(CONSUME/PROVIDE/RESELL/ADMINISTER)

自動化戦略:手動テストゼロ

この複雑さを1人で保守するために、手動テストを完全に排除する方針を取った。

E2Eテスト(Playwright)

  • WebAuthn(パスキー)認証のテストも自動化
  • 仮想認証器を使ってCI環境でも実行可能
  • 全ポータルの主要フローをカバー

CI/CD

  • Self-hosted GitHub Actions Runner(WSL2上)
  • PR作成時に自動でE2Eテスト実行
  • Lint(ESLint, golangci-lint)・型チェック(TypeScript)

開発フロー

Claude Codeのspeckitワークフローで、仕様→設計→実装→検証を一貫して行う。

/speckit.specify(仕様作成)
    ↓
/qa.verify-spec(仕様の検証)← 仕様作成後に実行
    ↓
/speckit.clarify + 専門家検証(曖昧さ解消)
    ↓
/speckit.plan(設計計画)
    ↓
/qa.verify-design(設計の検証)← 設計後に実行
    ↓
/speckit.tasks(タスク生成)
    ↓
/speckit.analyze(整合性確認)← 実装前に必ず実行
    ↓
/speckit.implement(実装)
    ↓
/qa.verify-*(各種検証)
    ↓
テスト → Lint → コミット → PR → CI

フェーズ別ツール活用

各フェーズで使うツールを決めておくことで、抜け漏れを防ぐ。

フェーズ 補助ツール
仕様作成 Context7、Tavily、Sequential Thinking
仕様明確化 backend-architect、security-engineer
設計計画 backend-architect、Context7
タスク生成 Serena、Sequential Thinking
整合性確認 Serena、Codex
実装 Serena、security-engineer

検証コマンド

仕様・設計の検証:

コマンド タイミング 用途
/qa.verify-spec specify後 仕様の検証(要件の網羅性、実現可能性、矛盾の有無)
/qa.verify-design plan後 設計の検証(アーキテクチャの妥当性、既存パターンとの整合性)

実装後の検証:

/qa.verify-impl → /qa.verify-test → テスト → Lint → コミット → PR → CI
コマンド 用途
/qa.verify-impl 実装コードの検証(設計との整合性、コードスタイル、セキュリティ)
/qa.verify-test テストコードの検証(カバレッジ、テストパターン)
/qa.verify-migration DBマイグレーションの検証(Up/Down整合性、RLS、インデックス)
/qa.verify-rls RLSポリシーの検証(テナント分離、クロスアクセス防止)
/qa.verify-api API設計の検証(REST設計、認証、エラーハンドリング)

問題調査:

コマンド 用途
/qa.investigate 多角的な調査(MCP、専門家エージェント、サブエージェント活用)

技術スタック

領域 技術
Frontend Next.js 14 (App Router), TypeScript, TanStack Query, shadcn/ui
Backend Go, Echo, sqlc
Database PostgreSQL with Row-Level Security
Auth Keycloak
Test Playwright (E2E), WebAuthn仮想認証器
CI/CD GitHub Actions (Self-hosted Runner)

画面イメージ

System Portal ログイン画面

System Portal ログイン

メールアドレスを入力してOTPを送信する。

OTP入力画面

OTP入力

6桁のワンタイムパスワードを入力して認証。

Provider Portal サインアップ画面

Provider Portal サインアップ

サービス提供者として新規登録する画面。

現段階で実装済みの機能

  • 4ポータルの基本UI
  • 4APIの基本エンドポイント
  • Keycloak認証統合(WebAuthn + OTP)
  • アカウント・ユーザーCRUD
  • RLSによるデータ分離
  • Capabilityモデルによる権限制御
  • Playwright E2Eテスト(WebAuthn対応)
  • CI/CDパイプライン

今後の予定

  • 多言語対応(i18n)
  • 多通貨対応
  • サブスクリプション管理機能
  • 決済連携(Stripe等)
  • Webhook連携による自動プロビジョニング

Discussion