Skip to content

TypeScript リレーショナルデータベース

Filter this guidePick generator option values to hide sections that don't apply.

このジェネレーターは、Amazon Aurora(PostgreSQLまたはMySQL)とPrisma ORMを使用した新しいリレーショナルデータベースプロジェクトを作成します。AWS CDKまたはTerraformを使用してデータベースをプロビジョニングおよび管理するために必要なアプリケーションコードとインフラストラクチャを生成し、宣言的なスキーマ定義、自動マイグレーションデプロイ、型安全なORMクライアントを提供します。

リレーショナルデータベースの生成

Section titled “リレーショナルデータベースの生成”

新しいリレーショナルデータベースプロジェクトは2つの方法で生成できます:

  1. インストール Nx Console VSCode Plugin まだインストールしていない場合
  2. VSCodeでNxコンソールを開く
  3. クリック Generate (UI) "Common Nx Commands"セクションで
  4. 検索 @aws/nx-plugin - ts#rdb
  5. 必須パラメータを入力
    • クリック Generate
    パラメータデフォルト説明
    name 必須string-生成するデータベースプロジェクトの名前
    directory stringpackagesアプリケーションを保存するディレクトリ
    subDirectory string-プロジェクトが配置されるサブディレクトリ。デフォルトではプロジェクト名になります。
    infra aurora | noneauroraプロビジョニングするリレーショナルデータベースサービス。
    engine postgres | mysqlpostgres選択したサービスで使用するデータベースエンジン
    databaseUser stringdbadminデータベース管理者のユーザー名。デフォルトは 'dbadmin' です。
    databaseName string-初期データベース名。デフォルトではプロジェクト名になります。
    framework prismaprisma生成されるプロジェクトで使用するORMフレームワーク。
    iac inherit | cdk | terraforminherit優先するIaCプロバイダー。デフォルトでは、初期選択から継承されます。
    preferInstallDependencies booleantrueジェネレーター実行後に依存関係のインストールを優先するかどうか。複数のジェネレーターをバッチ処理する際にインストールを延期する場合はfalseに設定します(後続のジェネレーターがNxプロジェクトグラフを計算できるよう、必要に応じてインストールは実行されます)。最後に一度だけインストールします。

    ジェネレーターは<directory>/<name>ディレクトリに以下のプロジェクト構造を作成します:

    • Directoryprisma
      • Directorymodels
        • example.prisma サンプルモデル定義
      • schema.prisma メインPrismaスキーマ(モデルを参照)
    • Directorysrc
      • index.ts プロジェクトのエントリーポイント
      • prisma.ts Prismaランタイムクライアントラッパー
      • utils.ts ランタイム設定とシークレットヘルパー
      • create-db-user-handler.ts デプロイ時にアプリケーションデータベースユーザーを作成するLambdaハンドラー
      • migration-handler.ts デプロイ時にデータベースマイグレーションを実行するLambdaハンドラー
    • .gitignore 生成されたPrismaクライアント出力を含むGit無視エントリ
    • config.json ローカル開発接続の詳細とランタイム設定キー
    • Dockerfile マイグレーションハンドラー用のコンテナイメージ定義
    • project.json プロジェクト設定とビルドターゲット
    • prisma.config.ts Prisma CLIの設定

    ローカル開発スクリプトはすべてのデータベースプロジェクト間で共有され、packages/common/scripts/に生成されます:

    • Directorypackages/common/scripts/src/rdb
      • pull-image.ts データベースコンテナイメージをプル
      • start-container.ts ローカルデータベースコンテナを起動
      • wait-for-postgres-db.ts ローカルデータベースの準備完了を待機(PostgreSQL)
      • wait-for-mysql-db.ts ローカルデータベースの準備完了を待機(MySQL)

    このジェネレータは選択した iacProvider に基づいてInfrastructure as Codeを生成するため、packages/common に関連するCDKコンストラクトまたはTerraformモジュールを含むプロジェクトを作成します。

    共通のInfrastructure as Codeプロジェクトは以下の構造を持ちます:

    • Directorypackages/common/constructs
      • Directorysrc
        • Directoryapp/ プロジェクト/ジェネレータ固有のインフラストラクチャ用コンストラクト
        • Directorycore/ app 内のコンストラクトで再利用される汎用コンストラクト
        • index.ts app からコンストラクトをエクスポートするエントリーポイント
      • project.json プロジェクトのビルドターゲットと設定
    • Directorypackages/common/constructs/src
      • Directoryapp
        • Directorydbs
          • <name>.ts データベース固有のインフラストラクチャ
      • Directorycore
        • Directoryrdb
          • aurora.ts 汎用 Aurora データベースコンストラクト

    デプロイされたデータベースは以下のアーキテクチャを持ちます。デフォルトでは、Amazon RDS Proxy が Aurora クラスターの前に配置され、接続をプールし、IAM 認証を有効にします — 代替方法については RDS Proxy を無効にする を参照してください。PostgreSQL または MySQL エンジンのどちらを選択しても、アーキテクチャは同じです。異なるのは Aurora エンジンのフレーバーのみです。

    Application(Lambda, Agent, ...)RDS ProxyMigrations LambdaAurora(PostgreSQL or MySQL)Secrets Manager(DB credentials) SQL (IAM auth) Schema migrations Admin credentials

    生成されたプロジェクトはPrisma ORMを使用してデータベーススキーマを定義し、型安全なクライアントを生成します。ワークフローはモデルファーストです:データベースプロジェクトのprisma/models/ディレクトリ配下にPrismaモデルファイルを追加または更新し、それらのモデル変更からマイグレーションを生成します。

    Userモデルの例:

    packages/postgres/prisma/models/user.prisma
    model User {
    id Int @id @default(autoincrement())
    firstName String
    lastName String
    }

    詳細については、公式のPrismaデータモデリングガイドを参照してください。

    データベースクライアントの生成

    Section titled “データベースクライアントの生成”

    ジェネレーターは、プロジェクトをビルドするたびに型安全なTypeScript Prismaクライアントを作成するgenerateターゲットを自動的に設定します。クライアントはgenerated/prismaに書き込まれます(.gitignoreに追加されます)。

    いつでも手動でクライアントを生成することもできます:

    Terminal window
    pnpm nx generate <your-db-project-name>

    ワークスペースルートからPrisma CLIコマンドを実行するには、prismaターゲットを使用します:

    Terminal window
    pnpm nx run <project>:prisma generate

    src/prisma.tsのランタイムラッパーは以下をエクスポートします:

    • getPrisma() - AWS AppConfigからデータベース接続設定を読み込み、IAM認証を使用してPrismaクライアントを作成

    クライアントは自動的に:

    • RUNTIME_CONFIG_APP_ID環境変数を使用してAWS AppConfigからデータベース設定を取得
    • IAM認証用にAWS RDS Signerを介して一時的な認証トークンを生成
    • 証明書検証付きのSSL/TLS接続を管理
    • 永続的なデータベース接続プールを通じて接続プーリングを処理

    prisma/models/配下のモデルを追加または更新した後、migrate devを使用してマイグレーションファイルを生成し、同時にローカルデータベースに適用します。

    生成されたprismaターゲットは、実行前にローカルデータベースコンテナを自動的に起動します:

    Terminal window
    pnpm nx run <project>:prisma migrate dev

    ローカルデータベースに適用せずにマイグレーションファイルのみを生成したい場合は、--create-onlyを追加します:

    Terminal window
    pnpm nx run <project>:prisma migrate dev --create-only

    これにより、スキーマが変更されるたびにprisma/migrationsに新しいマイグレーションフォルダが生成されます:

    • Directoryprisma
      • Directorymigrations
        • Directory20260405013911_initial_migrations
          • migration.sql
        • migration_lock.toml
      • schema.prisma

    AWSスタックをデプロイすると、生成されたインフラストラクチャが生成されたマイグレーションをデプロイされたデータベースに自動的に適用します。

    既存のマイグレーションの適用

    Section titled “既存のマイグレーションの適用”

    他の開発者が作成したマイグレーションファイルをプルした場合、migrate deployを使用してそれらの既存のマイグレーションをローカルデータベースに適用します。

    Terminal window
    pnpm nx run <project>:prisma migrate deploy

    このローカル開発フローでは、migrate deployはマイグレーションファイルをローカルデータベースに適用します。AWSにデータベースをデプロイするわけではありません。

    生成されたprismaターゲットはPrisma CLIを公開しているため、ローカルデータベースに対してPrismaがサポートする任意のコマンドを実行できます。利用可能なコマンドについては、Prisma CLIリファレンスを参照してください。

    Terminal window
    pnpm nx run <project>:prisma <prisma-command>

    Prisma Studioは、ローカルデータベース用のビジュアルエディタです。テーブルの閲覧、レコードの検査と編集、データのフィルタリング、リレーションのフォロー、組み込みSQLコンソールを介した生SQLの実行に使用できます。開発中のマイグレーションの検証とテストデータのシードに便利です。以下で起動します:

    Terminal window
    pnpm nx run <project>:prisma studio

    devを停止する(例:Ctrl+Cで)と、ローカルデータベースコンテナは自動的に削除されますが、名前付きボリュームは保持されるため、データは再起動後も引き継がれます。

    任意のTypeScriptプロジェクトで、データベースパッケージからgetPrismaをインポートして呼び出すと、型安全なPrismaクライアントが取得できます:

    import { getPrisma } from ':my-scope/db';
    const prisma = await getPrisma();
    const users = await prisma.user.findMany({ orderBy: { id: 'asc' } });

    getPrisma()は遅延初期化されたキャッシュされたクライアントを返します。同じLambda実行コンテキスト内での後続の呼び出しは、新しい接続を開くのではなく、既存の接続プールを再利用します。

    Prismaクライアントはprisma/models/スキーマから派生した完全に型付けされたモデルを公開し、データベースからAPIレスポンスまでのエンドツーエンドの型安全性を提供します。

    リレーショナルデータベースジェネレーターは、選択した iacProvider に基づいて CDK または Terraform インフラストラクチャを作成します。

    CDK コンストラクトは common/constructs に作成されます。使用例:

    packages/infra/src/stacks/application-stack.ts
    import { MyDatabase } from ':my-scope/common-constructs';
    export class ApplicationStack extends Stack {
    constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);
    ...
    const db = new MyDatabase(this, 'Db', {
    vpc,
    vpcSubnets: {
    subnetType: SubnetType.PRIVATE_ISOLATED,
    }
    });
    }
    }

    これにより、RDS Proxy を備えた Aurora クラスター、管理者認証情報、アプリケーションデータベースユーザー、ランタイム設定の登録、およびマイグレーションハンドラーがプロビジョニングされます。

    生成されたインフラストラクチャは、2つのデータベースユーザーを作成します:

    • 管理者ユーザー - クラスターのプロビジョニング中に作成され、認証情報は AWS Secrets Manager に保存されます
    • アプリケーションユーザー - Lambda カスタムリソースを介して作成され、IAM 認証が有効化され、アプリケーションデータベースに対する DML 権限(SELECT、INSERT、UPDATE、DELETE)が付与されます

    アプリケーションユーザーは、ランダムな名前と IAM 認証で自動的に作成されます。生成されたデータベースクライアントは、短期間有効な RDS トークンを使用してこのユーザーとして認証するように既に設定されているため、アプリケーションコードがデータベースパスワードを処理することはありません。

    VPC には、パブリックサブネット、エグレス付きプライベートサブネット、およびプライベート分離サブネットを含める必要があります。データベースはプライベート分離サブネットで実行でき、アプリケーション Lambda 関数は AppConfig などの AWS サービスに到達できるように、エグレス付きプライベートサブネットで実行する必要があります。

    packages/infra/src/stacks/application-stack.ts
    const vpc = new Vpc(this, 'Vpc', {
    subnetConfiguration: [
    {
    name: 'public',
    subnetType: SubnetType.PUBLIC,
    },
    {
    name: 'private_with_egress',
    subnetType: SubnetType.PRIVATE_WITH_EGRESS,
    },
    {
    name: 'private_isolated',
    subnetType: SubnetType.PRIVATE_ISOLATED,
    },
    ],
    });

    connection ジェネレーターを使用して、プロジェクトをこのデータベースに接続します。データベースに到達するために必要なインフラストラクチャの配線については、関連するコンピュートタイプ(例:FastAPI、MCP サーバー、エージェント)の接続ガイドを参照してください。

    生成されるインフラストラクチャには、デフォルトでRDS Proxyが含まれており、アプリケーションとAuroraクラスター間に配置されます。RDS Proxyは以下のような利点を提供します:

    • コネクションプーリング - アプリケーションインスタンス間で共有できるデータベース接続のプールを維持し、新しい接続を確立するオーバーヘッドを削減します
    • 接続の回復性 - Auroraインスタンスの交換やメンテナンス中のフェイルオーバーと再接続を自動的に処理します
    • IAM認証 - IAMベースのデータベース認証をサポートし、アプリケーションコードでデータベース認証情報を管理する必要がなくなります
    • セキュリティの向上 - すべての接続に対してTLS暗号化を強制します

    RDS Proxyは次のように無効にできます:

    packages/infra/src/stacks/application-stack.ts
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    enableRdsProxy: false,
    });

    RDS Proxyが無効になっている場合、アプリケーションはAuroraクラスターエンドポイントに直接接続します。

    SSL Requirements When Connecting Without RDS Proxy

    Section titled “SSL Requirements When Connecting Without RDS Proxy”

    Auroraクラスターに直接接続する場合(RDS Proxyを使用しない場合)、getPrisma()を呼び出すランタイムはAmazon RDS CAバンドルを信頼する必要があります。生成されたPrismaクライアントは証明書検証を有効にします。CAバンドルを利用可能にする方法は、データベースに接続するランタイムによって異なります。

    Amazon RDSの場合、以下からグローバルCAバンドルを使用します:

    https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem

    ランタイム用に独自のコンテナイメージを準備する場合は、DockerfileでRDS CAバンドルをダウンロードし、オペレーティングシステムのトラストストアに追加します。

    RUN curl -fsSL "https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem" \
    -o /etc/pki/ca-trust/source/anchors/rds-bundle.pem && \
    update-ca-trust

    Node.js 20以降のランタイムを使用するZip形式のLambda関数の場合、NODE_EXTRA_CA_CERTSを設定してAmazon RDS CAバンドルを読み込みます:

    packages/infra/src/stacks/application-stack.ts
    const api = new Api(this, 'Api', {
    integrations: Api.defaultIntegrations(this)
    .withDefaultOptions({
    environment: {
    NODE_EXTRA_CA_CERTS: '/var/runtime/ca-cert.pem',
    },
    })
    .build(),
    });

    詳細については、AWS LambdaのAmazon RDS接続のSSL/TLS要件を参照してください。RDS Proxyを使用する場合、データベースに接続するランタイムでRDS CAバンドルを設定する必要はありません。

    Auroraクラスターのライターインスタンスとリーダーインスタンスを設定します。

    packages/infra/src/stacks/application-stack.ts
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    writer: ClusterInstance.serverlessV2('writer'),
    readers: [ClusterInstance.serverlessV2('reader')],
    });

    ワークロードに合わせてAurora Serverless v2のスケーリング制限を制御します。

    packages/infra/src/stacks/application-stack.ts
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    serverlessV2MinCapacity: 0.5,
    serverlessV2MaxCapacity: 8,
    });

    特定のAuroraエンジンバージョンを固定します。

    デフォルトでは、生成されたローカルデータベースコンテナイメージはデフォルトのAuroraエンジンバージョンと一致します。Auroraエンジンバージョンを変更する場合は、最大限の互換性を確保するために、一致するローカルコンテナイメージバージョンも使用することをお勧めします。対応するコミュニティデータベースバージョンを特定するには、Aurora PostgreSQLバージョンおよびAurora MySQLバージョンのAWSリリースノートを参照してください。

    ローカルデータベースイメージは、データベースプロジェクトルートにある生成されたconfig.jsonファイルのlocalDev.imageフィールドで設定されます。エンジンバージョンを変更する際は、その値を更新してください。

    engine = postgres
    packages/infra/src/stacks/application-stack.ts
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    engineVersion: AuroraPostgresEngineVersion.VER_17_7,
    });
    engine = mysql
    packages/infra/src/stacks/application-stack.ts
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    engineVersion: AuroraMysqlEngineVersion.VER_3_12_0,
    });

    削除保護はデフォルトで有効になっており(CDKではdeletionProtection: true、Terraformではdeletion_protection = true)、Auroraクラスターを誤削除から保護します。

    短期間の開発環境やプレビュースタックなど、データベースの削除が想定される環境では、削除保護を無効にすることができます。

    packages/infra/src/stacks/application-stack.ts
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    deletionProtection: false,
    });

    CDK コンストラクトはデフォルトで Aurora クラスターを保持します(removalPolicy: RemovalPolicy.RETAIN)。CDK スタックの削除時にクラスターのスナップショットを作成するか、破棄する場合は、これを変更してください。

    RemovalPolicy.DESTROY を使用する場合、クラスターを削除する前に削除保護も無効にする必要があります。

    packages/infra/src/stacks/application-stack.ts
    import { RemovalPolicy } from 'aws-cdk-lib';
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    removalPolicy: RemovalPolicy.SNAPSHOT,
    });

    スタックと共にデータベースを削除する一時的な環境の場合:

    packages/infra/src/stacks/application-stack.ts
    import { RemovalPolicy } from 'aws-cdk-lib';
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    deletionProtection: false,
    removalPolicy: RemovalPolicy.DESTROY,
    });

    Performance Insightsは、デフォルトでAuroraライターインスタンスで有効になっています(クラスターのKMSキーで暗号化されています)。また、AuroraエンジンログをCloudWatch Logsにエクスポートすることもできます(Aurora PostgreSQLの場合はpostgresqlAurora MySQLの場合はauditerrorgeneralslowquery)。データベースごとにログエクスポートを有効にします:

    packages/infra/src/stacks/application-stack.ts
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    enableCloudwatchLogs: true,
    enablePerformanceInsights: false, // disable if not required
    });

    Auroraクラスターとその認証情報シークレットの暗号化に使用されるKMSキーは、デフォルトで自動キーローテーションが有効になっています。セキュリティポリシーで外部的にローテーションを管理している場合は、これを無効にしてください。

    packages/infra/src/stacks/application-stack.ts
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    enableKeyRotation: false,
    });
    engine = mysql

    MySQL: API Gatewayストリーミングモード

    Section titled “MySQL: API Gatewayストリーミングモード”

    Aurora MySQLをAPI Gatewayストリーミングレスポンス(例:tRPCのhttpBatchStreamLink)と共に使用する場合、Prisma MySQLクライアントはクエリ完了後もNode.jsイベントループを保持し続け、Lambdaがストリームをフラッシュしてリクエストを終了できなくなります。

    これを回避するには、各クエリ後にfinallyブロックでクライアントを明示的に切断し、イベントループが終了してストリーミングレスポンスが完了できるようにします。

    オプション1: プロシージャごと

    export const listExampleTable = publicProcedure
    .output(z.array(ExampleTableSchema))
    .query(async () => {
    const prisma = await getPrisma();
    try {
    return await prisma.exampleTable.findMany();
    } finally {
    await prisma.$disconnect();
    }
    });

    オプション2: tRPCミドルウェア

    ミドルウェアパターンを使用している場合は、ミドルウェアに$disconnect()呼び出しを追加して、それに基づいて構築されたすべてのプロシージャが自動的にカバーされるようにします:

    packages/api/src/middleware/db.ts
    import { getPrisma } from ':my-scope/db';
    import { initTRPC } from '@trpc/server';
    export interface IDbContext {
    db: Awaited<ReturnType<typeof getPrisma>>;
    }
    export const createDbPlugin = () => {
    const t = initTRPC.context<IDbContext>().create();
    return t.procedure.use(async (opts) => {
    const db = await getPrisma();
    try {
    return await opts.next({
    ctx: {
    ...opts.ctx,
    db,
    },
    });
    } finally {
    await db.$disconnect();
    }
    });
    };

    RDS IAM認証トークンは15分後に期限切れになります。MySQL Prismaクライアントは、getPrisma()が呼び出された時点でIAMトークンを静的な値としてキャプチャします。既存の開いている接続は影響を受けませんが、トークンの期限が切れた後に新しい接続を確立する必要がある場合、認証は失敗します。PostgreSQLアダプターは、プールが新しい接続を開くたびにトークンを動的に更新することでこれを回避しますが、MySQLアダプターには同等のメカニズムがありません。

    バッチジョブやデータマイグレーションなどの長時間実行タスクの場合は、操作全体に対して一度ではなく、各作業単位の開始時にgetPrisma()を呼び出します。getPrisma()はMySQLに対して常に新しいクライアントを作成し、新しいIAMトークンを取得するため、各接続が有効なトークンで認証されることが保証されます。

    connectionジェネレータを使用して、このプロジェクトをワークスペース内の他のプロジェクトと統合できます。このプロジェクトに関連する接続は以下の通りです:

    tRPCAmazon Aurora
    tRPC API to Relational DatabasetRPC APIをAuroraリレーショナルデータベースに接続する
    SmithyAmazon Aurora
    Smithy API to Relational DatabaseSmithy APIをAuroraリレーショナルデータベースに接続する
    Strands AgentsTypeScriptAmazon Aurora
    TypeScript Agent to Relational DatabaseTypeScript AgentをAuroraリレーショナルデータベースに接続する
    Model Context ProtocolAmazon Aurora
    MCP Server to Relational DatabaseTypeScript MCP ServerをAuroraリレーショナルデータベースに接続する