ローカルのPostgreSQLをRDSに移したとき、変えたのは .env だけだった

このサイトは、RSSで集めたニュースをAIに要約させて毎朝公開している。 記事データの置き場所を、2026年9月のうちに2回動かした。

JSONファイル  ->  ローカルDockerのPostgreSQL  ->  AWS RDS
   (〜9/13)            (9/13)                      (9/14)

後半の「ローカル -> RDS」で、アプリケーションコードの変更は1行もなかった。 書き換えたのは .env の接続情報だけだ。

狙ってそうなったわけではない。前日に決めた取り決めが、たまたま効いた。

証拠

接続処理は db.py の1ファイルに置いてある。このファイルの変更履歴はこれだけだ。

$ git log --format='%h %ad %s' --date=short -- db.py
3ed5ecb 2026-09-13 feat: JSON記事データのPostgreSQL移行スクリプトを追加

コミットは1本。追加した日のものだけで、RDSに移した9/14をまたいで一度も変更されていない。

何をしていたか

db.py の中身はこれで全部だ。

REQUIRED_KEYS = ("DB_HOST", "DB_PORT", "DB_USER", "DB_PASSWORD", "DB_NAME")


def get_connection(**kwargs):
    """.env の DB_* を使って psycopg 接続を返す。不足があれば明示的に落とす。"""
    missing = [k for k in REQUIRED_KEYS if not os.getenv(k)]
    if missing:
        raise RuntimeError(f".env に {', '.join(missing)} が設定されていません")
    return psycopg.connect(
        host=os.environ["DB_HOST"],
        port=int(os.environ["DB_PORT"]),
        user=os.environ["DB_USER"],
        password=os.environ["DB_PASSWORD"],
        dbname=os.environ["DB_NAME"],
        **kwargs,
    )

特別なことは何もしていない。決めたのは一つだけで、 他のスクリプトでは psycopg.connect() を直接書かない、というものだった。

正直に言うと、3ファイルの話である

ここで話を終えると、設計判断が効いた美しい話になってしまう。実際はそうではない。

今このデータベースを触っているスクリプトは3つしかない。

embed_articles.py   記事をベクトル化して保存
migrate_to_db.py    JSONからの一括投入
test_rag.py         過去記事のベクトル検索

3ファイルなら、仮に接続処理を各ファイルに直接書いていたとしても、 3箇所を置換すれば終わりだ。15分の差もつかない。

だからこの話の価値は「手間が減った」ことではない。

効いたのは、見積もれたこと

RDSに移すかどうかを決める場面で、私はコードを読み直さなくてよかった。

やることが「.env を書き換えて動作確認」だと最初から分かっていたので、 作業量をその場で見積もれた。見積もれたから着手できた。

逆の状態を想像してみる。接続文字列がどこに何個あるか分からない。 まず調べないと作業量が読めない。調べるのに30分かかるかもしれないし、 2時間かもしれない。今日はそんな時間がない。だから来週にする。 そして来週も同じことを考える。

個人開発で止まるのは、たいていここだ。 難しくて止まるのではなく、どれくらい大変かが分からなくて止まる。

集約しておくことの効果は、作業時間ではなく、 着手するかどうかの判断に効いていた。

取り残されたもの

かっこ悪い話も書いておく。

移行から3週間経って気づいたのだが、db.py の先頭はまだこうなっている。

"""ローカル PostgreSQL への接続ヘルパー。接続情報は .env (DB_*) から読む。"""

もうローカルではない。AWSのRDSを指している。.env.example も同様で、 「ローカル PostgreSQL (db/docker-compose.yml で起動したコンテナ newsbot-db)」 というコメントが残ったままだ。

コードを変えずに済んだ結果、変えるべき場所が一つも目に入らなかった。 差分が出なければレビューも起きない。

「変更不要」は「確認不要」ではない。 当たり前のようだが、 実際に差分ゼロで移行が通ってしまうと、確認する動機がどこにもなくなる。

移行できたことをどう確かめたか

コードが変わっていないので、動作確認は出力の一致で見た。

このサイトは記事をベクトル化して関連記事を引いている。 移行前と移行後で、同じ記事に対する検索結果の距離を比べた。

ローカル : x86 / pgvector 0.8.6
RDS      : ARM (Graviton) / pgvector 0.8.1

CPUのアーキテクチャも拡張のバージョンも違う。 それでも距離の値は小数4桁まで一致した。

浮動小数点の計算なので、環境が変われば下位の桁は動くと思っていた。 動かなかった。ここは正直、確認するまで分からなかった部分だ。

まとめ