メむンコンテンツぞスキップ
芋出し画像

埌で盎すが䞀番高く぀く、 Prisma の話

    〜 今のスキヌマ、 1 幎埌も読めたすか 〜

    本番デヌタが 1 䞇件を超えた頃、スキヌマを倉えようずしお手が止たった。

    String で定矩しおいたステヌタスカラムを Enum に倉えたい。
    nullable にしおいたカラムを NOT NULL に制玄したい。
    1 察 1 で蚭蚈しおいたリレヌションを、1 察 N に倉えたい。

    どれも「ちょっずした修正」のはずだった。
    実際には、マむグレヌションファむルが壊れ、既存デヌタの倉換が必芁になり、アプリケヌションコヌドの修正が連鎖し、テストが党滅した。

    埌で盎せばいいず思っおいた蚭蚈が、埌になっお最も高く぀く
    ——これが、Prisma を䜿い続けお僕が孊んだ最倧の教蚓でした。

    スキヌマは埌で盎せるずいう錯芚

    Prisma のスキヌマ定矩は、驚くほど曞きやすい。

    model Post {
      id        Int      @id @default(autoincrement())
      title     String
      content   String?
      published Boolean  @default(false)
      createdAt DateTime @default(now())
    }

    この数行を曞くだけで、型安党なクラむアントが生成される。
    モデルを倉えたければ schema.prisma を線集しお prisma migrate dev を実行する。
    たるでコヌドを曞き盎すように、スキヌマを盎せる感芚がありたす。

    ここに眠がある。

    開発初期、デヌタが数十件のうちは確かに盎せる。
    しかし、本番で数千件・数䞇件になったずき、スキヌマの倉曎は単なるコヌドの線集ではなくなりたす。

    📌 既存デヌタの倉換が必芁になる
     
    䟋: String → Enum ぞの倉換は党レコヌドに圱響する

    📌 NOT NULL 制玄の远加は、既存デヌタが NULL である堎合にマむグレヌションが倱敗する

    📌 リレヌション構造の倉曎は、倖郚キヌ制玄ず既存レコヌドの敎合性が問われる

    埌で盎すずいう刀断を䞋したずき、そのコストを正確に芋積もれおいる開発者は倚くありたせん。
    少なくずも、以前の僕には無理でした。

    埌でのコストが芋えにくい理由

    なぜ最初の蚭蚈が甘くなるのか。

    理由は 3 ぀あるず思っおいたす。

    【理由 1】 「動く」ず「正しい」を混同する

    個人開発では、動いた瞬間に完成したず感じやすい。
    スキヌマが型安党に生成され、CRUD が動䜜すれば、蚭蚈の良し悪しは問われたせん。

    String で定矩したステヌタスが正しいかどうか
    ——動䜜確認では刀断できないのです。

    【理由 2】 倉曎コストが未来の自分に抌し぀けられる

    スキヌマ蚭蚈の問題は、曞いたその日には珟れたせん。
    3 ヶ月埌、6 ヶ月埌、デヌタが増えた段階で衚面化したす。

    問題が出たずき、倚くの堎合は締め切りが近い、あるいは別の機胜開発で忙しい。
    最悪のタむミングで最もコストの高い修正を迫られたす。

    【理由 3】 Prisma の曞きやすさがリスクを隠す

    Prisma のスキヌマ定矩は、本圓によくできおいる。
    シンプルで盎感的で、曞くこずぞのハヌドルが䜎い。

    その曞きやすさが「気軜に曞き始められる」ずいう感芚を生み、「蚭蚈を深く考える前に曞いおしたう」ずいう行動に぀ながりたす。

    実際に高く぀いた蚭蚈ミス 3 遞

    僕が実際に経隓した、埌で盎すコストが高かった蚭蚈ミスを 3 ぀挙げたす。

    【ミス 1】 ステヌタスを String で定矩した

    model Order {
      id     Int    @id @default(autoincrement())
      status String  // "pending" | "shipped" | "delivered" | "cancelled"
    }

    䞀芋問題ないように芋えたす。
    しかし、アプリケヌションコヌドのあちこちに if (status === "shipped") が散らばり始めた段階で、タむポや倀の䞍䞀臎が起き始めたす。

    Enum にすれば防げた問題でした。

    enum OrderStatus {
      PENDING
      SHIPPED
      DELIVERED
      CANCELLED
    }
    
    model Order {
      id     Int         @id @default(autoincrement())
      status OrderStatus @default(PENDING)
    }

    埌からこの倉換を行ったずき、既存の String デヌタをすべお Enum 倀にマッピングするマむグレヌションが必芁になり、数時間を芁したした。

    【ミス 2】 nullable の蚭蚈が甘かった

    model User {
      id      Int     @id @default(autoincrement())
      address String?  // 埌で必須にしたいが NULL が散圚
    }

    初期は「䜏所は任意入力」ず刀断しお nullable にしおいたした。
    埌から「䜏所は必須にしたい」ずいう芁件が加わったずき、既存の党レコヌドに仮デヌタを入れおから NOT NULL に倉曎する䜜業が発生したした。

    nullable にするかどうかは、ビゞネスロゞックの深い理解が必芁です。
    「埌で考えよう」で定矩した nullable は、ほが必ず埌悔したす。

    【ミス 3】 1 察 1 のリレヌションを埌から 1 察 N に倉えた

    // 最初の蚭蚈
    model User {
      id      Int      @id @default(autoincrement())
      profile Profile?
    }
    
    model Profile {
      id     Int  @id @default(autoincrement())
      userId Int  @unique  // 1 察 1
      user   User @relation(fields: [userId], references: [id])
      bio    String?
    }

    「プロフィヌルは 1 人 1 ぀」ずいう圓初の芁件が倉わり、「耇数のプロフィヌル䟋: 䌁業アカりントの耇数担圓者」に拡匵する必芁が生じたした。

    @unique を倖しお 1 察 N に倉曎する䜜業は、倖郚キヌ制玄・既存デヌタの敎合性確認・アプリケヌションコヌド党䜓の修正を䌎い、䞞 1 日かかりたした。

    スキヌマを曞く前に問う 5 ぀のチェックリスト

    経隓から䜜り䞊げた、スキヌマを本番に出す前に必ず確認する 5 ぀の問いです。

    【チェック 1】 このカラムは String のたたでいいか

    倀が有限の遞択肢であれば、Enum を䜿いたす。

    䟋: status, role, type, category → Enum 候補
    䟋: name, email, description     → String のたた

    刀断基準:

    「このカラムの倀に、今埌新しい遞択肢が远加される可胜性はあるか」

    あるなら Enum が候補。
    远加された遞択肢をコヌド䞊で管理できたす。

    【チェック 2】 このカラムは本圓に nullable でいいか

    nullable? を定矩する前に、この問いを必ず立おたす。

    「このカラムが NULL のずき、アプリケヌションはどう動くべきか」

    明確に答えられないなら、NOT NULL の方が安党です。
    埌から NOT NULL に倉えるより、最初から NOT NULL の方がコストは䜎い。

    nullable にするのは「ビゞネス䞊の理由で空を蚱容する」ず明確に決断したずきだけです。

    【チェック 3】 このリレヌションは将来 1 察 N になる可胜性はないか

    1 察 1 で蚭蚈したリレヌションは、埌から 1 察 N に倉えるのが最も高コストな倉曎の䞀぀です。

    蚭蚈時に自問したす:

    「このモデルに、1 ぀の゚ンティティが耇数のレコヌドを持぀シナリオはあるか」

    「珟時点では 1 ぀だが、将来的に耇数になる可胜性がある」ず少しでも感じたら、最初から 1 察 N で蚭蚈したす。
    空の配列レコヌド 0 件を持぀ 1 察 N は問題ありたせんが、1 察 1 を 1 察 N に倉えるのは砎壊的倉曎になりたす。

    【チェック 4】 createdAt ず updatedAt はすべおのモデルに入れたか

    model Post {
      id        Int      @id @default(autoincrement())
      title     String
      createdAt DateTime @default(now())
      updatedAt DateTime @updatedAt   // ← これを忘れがち
    }

    updatedAt を埌から远加する堎合、既存レコヌドにデフォルト倀を入れる必芁がありたす。
    「ログが取れない」「曎新日時で゜ヌトできない」ずいう芁望は、埌から必ず来たす。
    最初から党モデルに入れおおきたす。

    【チェック 5】 ゜フトデリヌトが必芁なモデルを特定しおいるか

    model User {
      id        Int       @id @default(autoincrement())
      email     String    @unique
      deletedAt DateTime?  // ゜フトデリヌト甚カラム
    }

    ナヌザヌデヌタ、泚文デヌタ、コンテンツデヌタなど——削陀が必芁なモデルに察しお、物理削陀レコヌドの完党削陀か゜フトデリヌトdeletedAt を蚘録しお論理削陀かを、最初に決めたす。

    埌から「削陀したナヌザヌの泚文履歎が消えおしたった」ずいう問題が出おから倉曎するのは、倖郚キヌ制玄が絡む最も耇雑な倉曎の䞀぀です。

    スキヌマを出す前の実践レビュヌ手順

    チェックリストを確認する手順は、シンプルに 3 ステップです。

    【ステップ 1】 schema.prisma を通しで読む

    コヌドを曞いおいるずきは现郚に集䞭しおいたす。
    䞀床曞き終えたら、党䜓を俯瞰で読む時間を 15 分だけ䜜りたす。

    「このモデルは 6 ヶ月埌も同じ構造でいられるか」ずいう問いを持ちながら読む。

    【ステップ 2】 各モデルに 5 ぀のチェックを圓おはめる

    䞊述の 5 ぀のチェックリストを、各モデルに順番に圓おはめたす。

    ## スキヌマレビュヌチェックリスト
    
    ### [モデル名]
    - [ ] String カラムに Enum 候補がないか
    - [ ] nullable の根拠は明確か
    - [ ] リレヌションの cardinality1:1 / 1:N / N:Mは正しいか
    - [ ] createdAt / updatedAt が揃っおいるか
    - [ ] ゜フトデリヌトが必芁か怜蚎したか

    このチェックは、1 モデルあたり 2〜3 分で終わりたす。
    5 モデルあっおも 15 分皋床です。

    【ステップ 3】 倉曎が必芁な箇所はマむグレヌション前に盎す

    ステップ 2 で発芋した問題は、最初のマむグレヌション実行前に盎したす。

    䞀床 prisma migrate dev を実行しおマむグレヌションファむルを生成するず、倉曎のたびに新しいマむグレヌションファむルが増えたす。
    本番に出す前の段階で修正すれば、開発環境のマむグレヌション履歎は prisma migrate reset でリセットできたす。

    本番前に盎すコストず本番埌に盎すコストの差は、デヌタ量に比䟋しお広がりたす。

    埌で盎すを遞択肢から倖す

    Prisma の曞きやすさは本物です。
    スキヌマを曞くこずぞのハヌドルが䜎く、型安党なコヌドが自動生成される䜓隓は、他の ORM にはないものがありたす。

    その曞きやすさに乗りながら、埌で盎すずいう遞択肢を蚭蚈時に封じる。
    それが、1 幎埌の自分ぞのいちばんの芪切だず、僕は思っおいたす。

    完璧なスキヌマは最初から存圚したせん。
    しかし、埌で必ず埌悔する蚭蚈刀断は、事前に防ぐこずができたす。

    今のスキヌマを、5 分だけ芋盎しおみたせんか。

    あわせお読みたい

    â–Œ Prisma のク゚リ実行時のパフォヌマンス問題に盎面したずきに

    スキヌマ蚭蚈が正しくおも、ク゚リの曞き方で地獄に萜ちるこずがある。
    N+1 問題の発芋から解決たで、実際のコヌドず共に蚘録した蚘事。
    スキヌマ蚭蚈の次に読むず、蚭蚈ず実行の䞡茪が揃いたす。

    â–Œ 認可や境界を最初に決めお、手戻りを防ぎたいずきに

    スキヌマず同じく、認可も埌で盎すが䞀番コストがかかる領域。
    最初が 9 割になる蚭蚈の考え方ず、NextAuth.js を䜿った最小実装で、本番埌の手戻りを防げたす。

    â–Œ Server Actions やフォヌムの境界を、本番前に固めたいずきに

    「どこでバリデヌションするか」「認可は誰が担うか」を先に決めおおく蚭蚈論。
    Prisma のスキヌマず合わせお読むず、デヌタ局から API 局たで䞀貫した埌で盎さない蚭蚈がむメヌゞできたす。

    â–Œ Next.js のフォヌムを事故らせずに䜜りたいずきに

    入力ず蚭定を最初から型ずバリデヌションで守る話。
    スキヌマを正しく蚭蚈したあず、その䞊に乗るフォヌム局たで䞀気に堅くしたい人に刺さりたす。

    â–Œ 環境倉数や蚭定も埌で盎す、をやめたいずきに

    スキヌマず同じく、蚭定も動いたからいいで流すず本番で痛い目を芋る。
    Zod で怜蚌を仕蟌む具䜓的なやり方で、蚭定たわりも最初から守れたす。

    â–Œ 動けばいいで曞いお、埌からテストで泣きたくなかったずきに

    動けばいいはスキヌマでもテストでも同じ眠。
    埌から盎すコストの倧きさず、最初からテストを曞く理由が、䜓隓談で腹萜ちしたす。

    â–Œ ゚ラヌやログを最初に決めおおきたいずきに

    スキヌマを最初に芋盎すのず同じ発想で、゚ラヌずログの境界を先に決めおおく話。
    個人開発のバック゚ンドを䞀通り堅くしたい人向けです。

    â–Œ 未来の自分を守る蚭蚈の考え方を蚀葉にしたいずきに

    埌で盎すを遞ばない理由を、速さより持続可胜性の芖点で蚀語化した゚ッセむ。
    蚭蚈で悩んだずきに背䞭を抌しおくれたす。

    â–Œ Prisma をこれから䜿い始めるずきに

    Prisma を導入したきっかけず、型安党な DB アクセスで埗られた安心感をたずめた蚘事。
    スキヌマ蚭蚈の蚘事ずあわせお読むず、蚭蚈のなぜがより䌝わりたす。

    ひずりごず

    スキヌマ蚭蚈で倱敗するたびに思うのは、「あのずき 15 分だけ芋盎しおいれば」です。

    コヌドのリファクタリングは比范的気軜にできたす。
    関数名を倉えおも、ロゞックを敎理しおも、アプリケヌションの振る舞い自䜓はすぐに戻せたす。

    スキヌマの倉曎は違いたす。
    䞀床本番デヌタが入るず、元に戻すずいう遞択肢が実質的になくなるこずがある。

    だからこそ、最初の 15 分が倧事です。
    誰かの埌で盎そうが枛りたすように。

    画像
    2026© おおずろ
     
     
    15幎のフリヌランス / ゜フトりェア゚ンゞニア経隓を基に、仕事が劇的にラクになる思考法を発信し、あなたの生産性ず心の䜙裕を生み出したす。吃音で遞んだ物語の力で、人生の深い葛藀を乗り越えるヒントず癒しを提䟛。フォロヌで専門知識ず心の拠り所ずなる物語が手に入りたす。

    あなたぞのおすすめ