2026年6〜8月のふりかえりです。 前回に続いて3か月分まとめてとなりました。 ひきつづき B 社(週5日) での稼働となります。G社は無事契約終了になりました。

B 社

3〜5 月は Shopify への移行プロジェクトが活動の中心だったのですが、 6〜8 月はそこから軸足が移って、既存システム側の基盤・運用まわりの立て直しが仕事の大半を占めるようになりました。 6月にShopify移行プロジェクトを停止しましょうという話を進めて、実際にそのようになったのが理由です。

よって、以下の内容は基本的にはShopifyプロジェクト停止前提で動き始めた6月、停止が決まった7月以降というイメージでご覧いただければと思います。 また、以下に具体的な記載は無いですが、6月からShopifyプロジェクトという全社で取り組んでいた案件がなくなったことを受けて、並行してシステムの中長期計画を策定し7〜8月にかけて何度か経営陣のみなさんふくめて様々な相談をさせていただいた期間にもなりました。(私の作業内容も中長期計画に沿った形(先取りした形)で進めています)

※なお、この記事から僕の手書きの記事ではなく、Slackの#times_yagitaチャンネルの内容をClaude Codeに読ませて記事化するように変更してみました。

開発環境(dev)の構築

3〜5 月に着手した dev 環境の構築がそのまま 6〜7 月にかけて続いていました。

  • Aurora の clone を使って dev 用の DB を作る仕組みを整えて、実際に作って寝かせて再検証して壊す、というのを繰り返していました。
  • dev のホスト毎の設定(環境変数)の供給方式が決まっていない、というのが長く残っていた論点で、最終的に SSM を舐めて回る方式から S3 に per-host の .env を置く方式へ切り替えました。
    • ここは ADR を書いて方式を決めてから実装する、という進め方をしています。あとから「なんでこうなってるんだっけ」となりがちな領域なので。
  • 設定が育ちすぎていたので、生存確認・ホスト間 diff・死蔵キーの検出をやる監査ツールを書きました。実効の .env を監査できるようにした、という感じです。
  • dev/prod の Aurora クラスタパラメータグループの差分について、追従漏れを解消したうえで運用ルールを決めました。
  • マイクロサービス群と dev ホスト群の接続性を、環境インスタンスの discovery 規約として設計し直しました。N=1 前提だったものを N に単調拡張できる形へ、というやつです。

なお、この過程で「別 VPC で peering が無いので到達できない」みたいな地味に厳しい前提が発覚したりもしていました。

Shopify 移行関連の残り

  • 3〜5 月にやっていた Shopify の認証方式の移行が、静的トークンの全廃をもって完遂しました。
    • SSM のキー命名の統一や、後方互換で残していた経路の削除など、地味な後始末を含めて片付けています。
  • 認証情報の供給漏れ・キー命名の不整合といったバグの是正も、ここで ADR に沿って一気に直しました。

レガシー資産の棚卸し

自前コードに溜まっていた古い依存を、6 月にまとめて剥がしました。

  • 自前の CoffeeScript 114 ファイルを vanilla JS に変換して、CoffeeScript 依存を終了しました。
    • ただし inline coffee や gem 内の .coffee は残っているので、完全に根絶したわけではありません。
  • lodash の直接依存の排除、rx.js の削除。
  • hubot スクリプトも脱 CoffeeScript して、あわせて lint/test の基盤(Biome/Vitest/nvm)を入れました。
  • スクレイピング系の PhantomJS 依存を剥がして、プレーンな HTTP 呼び出しに置き換えました。
  • Go 側はエラー生成を go-errors に統一して、ガイドラインも整備しました。

画面パフォーマンスの改善

6 月後半から 8 月にかけて、社内管理画面と公開側の遅いページを片っ端から潰していました。 だいたいどれも「一覧の行 partial の描画コスト」か「N+1」か「キャッシュミス時にだけ出てくる重いクエリ」のいずれかでした。

  • 制作/受注一覧が常時 3 秒前後(1 日あたり最多のリクエスト数)、出荷チェックが常時 2.8 秒超、制作一覧が常時 6 秒超、配送データ一覧が常時 1 秒、注文一覧の総件数カウントが約 11 秒、といったあたり。
  • 公開側では SEO 系のコントローラのキャッシュミス時の描画が重く、調べていくと描画時間の 94% が 1 つの partial の階乗的なクエリに吸われている、みたいなことがわかったりしました。
  • 7 月半ばには、その配送ギャラリーの p99 が突然 28 秒に悪化するという事象があり、原因は直近の候補が枯渇したときにフォールバックが古い重いクエリへ落ちる、というものでした。
  • Spree のエンジンの URL ヘルパが最適化経路に乗っておらず 1 コール 3.19ms かかっていた、という全ページに波及する話も見つかりました。

こういうのは計測しないと絶対に見つからないので、数字を出しながら潰していくのが結局いちばん速いなと思っています。

デプロイと CI の時間短縮

  • Capistrano のデプロイで、アセットのビルド(webpack と Sprockets の precompile)を各 EC2 で毎回実行していたのを、CI で事前にビルドして S3 に配布し、デプロイ時は fetch するだけ、という形に段階的に作り替えました。
    • webpack 側、precompile 側とフェーズを分けて進めていて、precompile だけで 214 秒 × ホスト数、デプロイ時間の 58% を占めていた、という規模感でした。
    • ビルド出力をホストや環境に依存しない形にする(ビルド時に焼き込んでいた client の env を実行時注入に変える)ところが前提として必要で、そこから着手しています。
    • 無変更時の再ビルドをツリーハッシュでキャッシュして省く、publish の完了/失敗を Slack に通知して「green 待ち」を人間の注意力から外す、といった細かい整備も入れました。
  • client のみの変更で Rails 系の CI(rspec/rubocop/brakeman/erb-lint/slim-lint)が走るのを抑止しました。
  • CDK のデプロイも、スタック別に必要最小限のジョブだけ実行するようにして、純 IAM デプロイで 8 分の無駄なビルドを排除しました。
  • rspec の CI はテストが倍増して並列度が追いつかず 14〜16 分になっていたので、シャード数を増やす・固定オーバーヘッドを圧縮する方向で短縮を検討しました。
  • archive 済みの GitHub Action を現行メンテ版に移行したり、@master のような可変 ref 参照を潰したりもしています。

デプロイと CI は毎日全員が待たされる場所なので、ここを削るのは費用対効果が高いですね。

セキュリティ

  • コード中に明示参照されていた静的な AWS 認証情報(13 箇所ほど)を、instance profile / task role への委譲に置き換えました。あわせて SSM の棚卸しもしています。
  • 画像配信サービスのアセット管理画面に謎のアセットが大量発生していたので調べたところ、外部からの脆弱性スキャンの痕跡でした。WAF のハードニングを実施しています。

フロントエンドの刷新

8 月は client のフロントエンド要素技術の刷新が大きなテーマでした。

  • Hypernova を撤去して島型マウント(いわゆる islands)に置き換える、というのを基盤の新設から始めて段階的に進めています。
  • あわせて Vite への移行、ライブラリの刷新、webpack 出力が browserslist の誤配置で ES5 固定になっていたのを ES6 へ、といった整理も進めました。
  • リファクタリングの安全網として、変更対象ドリブンな特性化テストと段階的な型付け(checkJs)を先に入れています。
  • 使われていない「デッド島」の撤去もしています。

コンテナ化 / ECS 化

8 月後半からは、既存システムをコンテナに載せる大型のエピックを設計・分解していました。 バッチ・sidekiq・one-off・migration・web・退役、という単位に分けて、それぞれの前段に共通前提(イメージ供給と ECR の整備、コンテナ非互換の除去、排他制御を flock から MySQL の GET_LOCK へ、ログの出口と失敗検知の整備)を置く、という構成にしています。

  • 非同期の実行単位を所要時間で分けて、デプロイ単位と一致させる(長時間バッチを cron コンテナから分離する)というのが設計上の肝でした。
  • ローカル FS への依存(tmp/*.txt に状態を持っている、など)を DB に寄せる、といった前提潰しを先にやっています。
  • cron 44 本の発火保証とジョブ台帳、という薄い死活監視も先行導入しました。
  • 既存ホストの退役方式も並行して見えてきたところです。

見つかってしまった問題たち

調査を進める過程で、わりと年季の入った不具合がいくつか出てきました。

  • 件数 1 つを取るためだけに毎日 30MB のデータを作っているバッチがあったので廃止しました。
  • 2021 年にボットの流入で 118.6 万行入っていたテーブルの扱いを決める、みたいな話も出てきました。
  • 1 年以上実行されていない Redash のクエリが 1,183 件(全体の 63%)あったので、定期アーカイブの運用を整備しました。

長く動いているシステムを触ると、こういうのが必ず出てきますね。 「動いているように見えていただけ」というのがいちばん怖いです。

AI との付き合い方

  • ひきつづき Claude Code を複数リポジトリで並列に動かす形で進めています。
    • 7 月からは、git worktree + 環境分離スクリプトを組み合わせて、単一リポジトリを複数並列に動かすことができるようになっており活用しています。(dbや各種ポート等リソースが重複しないように自動調整するスクリプトです)
  • 3 か月やってみて、いちばん難しいのは「システム全体にわたって設定を一定に安定させる」ことだなと思いました。
    • 局所的には正しい変更が積み上がるのですが、全体としての一貫性は人間が意図的に見張らないと崩れます。ADR を書いてから実装する、共通前提を先に潰す、という進め方に寄せているのはそのためでもあります。
  • 6 月末あたりに動作が目に見えて速くなったのが体感としてありました。一方で調子の悪い日もあり、そのへんは付き合い方を覚えていくしかなさそうです。

G 社

引き継ぎが完了しているため、この 3 か月は特に稼働はありませんでした。 また、7月いっぱいで契約終了しましょうという調整をおこない、そのように終了しています。

3 か月をまとめると、Shopify 移行という大掛かりなプロジェクトを終了させて、既存システムを地道に刷新していきましょうという新方針と道筋を決め・合意もとって、新しく歩みだしたという期間になりました。

おわり