ブログ

  • AWSほぼ未経験から2か月でSAAに合格した勉強法 ― ハンズオンなしでも資格取得できた話

    AWSほぼ未経験から2か月でSAAに合格した勉強法 ― ハンズオンなしでも資格取得できた話

    AWS Certified Solutions Architect – Associate(SAA-C03)に合格しました。

    スコアは761点で、無事合格ライン720点をなんとか超えることができました。

    結果だけ見ると普通に合格しています。

    ただ、試験が終わった直後の感想は、

    「これはたぶん落ちたな」

    でした。

    正直、合格しているとはほとんど思っていませんでした。

    この記事では、インフラ経験がほぼないアプリケーションエンジニアが、AWSの知識ほぼゼロの状態から約2か月勉強してSAAに合格するまでと、実際に資格を取って何が変わったのかを書いてみます。

    受験前は、AWSをほとんど知らなかった

    私はエンジニア歴5年ほどです。

    これまでの業務は、主にアプリケーション開発やコーディングが中心でした。

    基本情報技術者試験やJava Silverは取得していますが、インフラについて体系的に勉強した経験はほとんどありません。

    AWSを利用している案件に関わったこと自体はあります。

    ただ、自分でAWS環境を設計したり、ネットワークを組んだり、インフラ構成を考えたりした経験はほぼありませんでした。

    EC2やS3くらいなら名前は知っている。

    でも、

    「ALBとNLBは何が違うのか」

    「Direct Connectって何のために使うのか」

    「AuroraとRDSって何が違うのか」

    と聞かれると、きちんとは答えられない。

    そんな状態でした。

    実際、仕事の打ち合わせでもAWSのサービス名が出てくることがあります。

    以前は知らない単語が出てくるたびに、

    「何となくインフラの話をしていることは分かる」

    くらいの理解で聞いていました。

    その状態を少しでも変えたくて、SAAを受験してみることにしました。

    勉強期間は約2か月、合計100時間くらい

    勉強期間は約2か月です。

    平均すると、

    • 平日は1日1時間程度
    • 休日は1日3時間程度

    くらい勉強していました。

    正確に計測していたわけではありませんが、合計すると100時間前後だったと思います。

    使用した教材は、ほぼPing-tです。

    AWS認定の参考書も買いました。

    買った時点では、

    「参考書を一通り読んでから問題集をやろう」

    と思っていました。

    ただ、結局ほとんど使いませんでした。

    自分の場合は、文章を最初から読むよりも、実際に問題を解いて分からないところを調べる方が頭に入りやすかったです。

    そのため、途中からはほぼPing-t一本になりました。

    最初は、問題文の意味すらよく分からない

    AWSの知識がほぼない状態なので、最初は当然かなり苦戦しました。

    問題を読んでも、

    「このサービス名は何?」

    というところから始まります。

    選択肢を見ても、4つとも知らないサービスということもありました。

    なので、最初から正答率を上げようとはあまり考えませんでした。

    まずは、

    AWSにはどんなサービスがあるのかを覚える

    ことを優先しました。

    EC2、S3、RDSのような有名なものだけでなく、

    • Transit Gateway
    • Storage Gateway
    • RDS Proxy
    • Kinesis
    • SQS
    • DynamoDB
    • Route 53
    • Direct Connect
    • VPC Endpoint

    など、問題に出てきたサービスをその都度調べていきました。

    最初は点と点だった知識が、問題を解いているうちに少しずつつながっていく感覚がありました。

    一番意識したのは「不正解の理由」

    勉強中に特に意識したのが、

    正解だけ確認して終わらないこと

    です。

    SAAを勉強していると、

    「これでも要件を満たせそうじゃない?」

    と思う選択肢がかなり出てきます。

    正解は1つですが、それ以外の選択肢も完全に間違っているとは限りません。

    たとえば、

    「実現はできるけれど運用負荷が高い」

    「要件は満たすけれどコストが高い」

    「似たサービスだが、今回の用途には向いていない」

    というものが多いです。

    なので、間違えた問題では、

    「正解がなぜ正しいか」

    だけではなく、

    「他の3つはなぜ違うのか」

    も確認しました。

    これを繰り返していると、少しずつ

    「この問題は高可用性を聞いている」

    「これはコスト最適化がポイント」

    「これは運用負荷を下げたい問題」

    という問題の見方ができるようになります。

    個人的には、単純にサービス名を暗記するより、この勉強方法の方がかなり重要だったと思います。

    ハンズオンは、ほぼやっていない

    今回、AWSのハンズオンはほとんどやりませんでした。

    これまでの案件でAWSコンソールを少し触ったことはありますが、試験勉強のために、

    「VPCを一から作る」

    「EC2を構築する」

    「ALBを設定する」

    といったことはほぼしていません。

    AWSの理解を深めるという意味では、もちろん実際に触った方がいいと思います。

    ただ、

    SAAに合格することだけを目的にするのであれば、問題演習中心でも合格は可能

    というのが、自分の結果からの感想です。

    一方で、このやり方には明確な弱点もあります。

    資格に合格しても、AWS環境を実際に一から構築できるわけではありません。

    ここは受験後の今でも感じています。

    そして試験当日

    試験当日。

    ここまで勉強したので、

    「ある程度はいけるだろう」

    くらいには思っていました。

    ところが、実際に問題を解き始めると、思っていた以上に自信がありませんでした。

    感覚的には、

    3割:ほぼ正解だと思う

    4割:2択までは絞れるけど、最後が分からない

    3割:正直ほとんど分からない

    という感じでした。

    問題を解きながら、

    「これ大丈夫か?」

    と思う回数がかなり多かったです。

    特に厳しかったのが、

    「2択までは絞れる」

    問題です。

    2つまでは明らかに違う。

    残り2つのどちらか。

    でも最後の決め手が分からない。

    この状態で選ぶ問題がかなりありました。

    1問ならまだしも、これが何問も続くと、だんだん不安になってきます。

    試験終了。「たぶん落ちたな」

    全問解き終わった時点では、

    「これは落ちた可能性が高いな」

    と思っていました。

    「確実に取れた」と思える問題が3割程度。

    残りの多くは消去法か、最後は半分勘です。

    試験会場を出た後も、

    「720点届いてない気がするな」

    と思っていました。

    そして次に頭に浮かんだのが、

    「また受験料払うのか……」

    でした。

    SAAの受験料は決して安くないので、落ちたことより、

    「もう一回受けるなら、また約2万円か……」

    という現実的なダメージの方が先に来ました。

    当日の夜、合格メールが届いた

    その日の夜。

    AWSから試験結果のメールが届きました。

    正直、開くのは少し怖かったです。

    結果を見ると、

    スコア761点、合格。

    余裕のある点数ではありません。

    合格ライン720点に対して761点です。

    ただ、試験中の感覚を考えると、

    「よくこれで受かったな」

    という方が強かったです。

    受験直後にはかなり落ちたと思っていたので、合格通知を見たときは普通にうれしかったです。

    SAAに合格して、AWSが使えるようになったか

    では、SAAに合格してAWSを使いこなせるようになったか。

    これは、

    まだ全然そんなことはありません。

    というのが正直なところです。

    AWSの設計や構築は、資格問題よりはるかに複雑です。

    実際の案件では、

    • システム要件
    • ネットワーク
    • セキュリティ
    • コスト
    • 運用
    • 障害時の対応
    • 既存システムとの接続

    などを考える必要があります。

    問題集で、

    「この要件ならAuroraです」

    と選択できることと、

    実際のシステムでAuroraを採用して設計・構築・運用することは全く別です。

    なので、

    SAAに合格した = AWSの実務ができる

    とは思っていません。

    それでも、取ってよかった

    では、何が一番変わったか。

    一番大きかったのは、

    仕事中に出てくるAWS用語が分かるようになったこと

    です。

    資格勉強を始める前は、

    「Transit Gateway」

    「VPC Endpoint」

    「RDS Proxy」

    「CloudFront」

    「Kinesis」

    のような言葉が打ち合わせで出てくると、その場で話についていけないことがありました。

    今は少なくとも、

    「それが何のためのサービスなのか」

    「どういう場面で使うものなのか」

    くらいは理解できます。

    これは、自分の中ではかなり大きな変化でした。

    AWSを専門にしていなくても、アプリケーションエンジニアとして仕事をしていると、インフラの話は避けて通れません。

    そのときに、

    会話の内容が全く分からない状態から、ある程度意味を理解できる状態になった

    だけでも、勉強した価値はあったと思っています。

    SAAは「AWSの共通言語」を覚える資格だった

    受験前は、

    「資格を取ればAWSに詳しくなる」

    くらいの感覚でいました。

    実際に受験してみると、少し違いました。

    自分にとってSAAは、

    AWSを使いこなすための資格というより、AWSについて話すための共通言語を覚えるための資格

    だったと思います。

    AWSには非常に多くのサービスがあります。

    それぞれを実務レベルで使いこなすことは、2か月の資格勉強だけでは当然できません。

    ただ、

    「AWSにはこういう選択肢がある」

    「こういう要件ならこのサービスが候補になる」

    という全体像は見えるようになりました。

    これは、今後実務でAWSに触れる際の土台にはなると思っています。

    まとめ

    私はインフラ経験がほぼない状態から、約2か月、100時間程度勉強してSAAに合格しました。

    勉強はほぼPing-tだけ。

    ハンズオンもほとんどしていません。

    試験当日は、

    • 3割:ほぼ正解を確信
    • 4割:2択まで絞れる
    • 3割:ほとんど分からない

    という感覚でした。

    それでも結果は761点で合格でした。

    今回受験してみて感じたのは、SAAを取得したからといって、すぐにAWSの設計・構築ができるようになるわけではないということです。

    一方で、

    これまで意味が分からなかったAWSのサービス名が理解できるようになり、仕事の会話についていけるようになった。

    これは、資格を取ったことで得られたかなり大きなメリットでした。

    今後は、資格勉強で得た知識を、

    「知っている」から「実際に使える」

    に変えていきたいと思います。

  • 仕様書は、実機の近似である — クラウド API を実機で確かめるということ

    仕様書は、実機の近似である — クラウド API を実機で確かめるということ

    公式ドキュメントは、出発点であって終着点ではない

    この連載は、認証情報の使い分け、サイレント障害と続けてきた。通底しているのは、signal と現実のずれをどう埋めるか、という話だ。認証が通ったことは、意図した身分で通ったことを意味しない。処理が成功を返したことは、処理が効いたことを意味しない。今回扱うのは、その延長にある。仕様書に書いてあることは、実機がそう動くことの近似であって、保証ではない。

    最初に一度だけ断っておく。これは特定のクラウドを責める話ではない。仕様書は人が書き、実装は別の時間に別の都合で動く。どんなに丁寧に書かれた仕様や型も、実機そのものではなく、その近似だ。だから仕様と実機のずれは、どのプラットフォームを使っていても起こり得る。以下の例はさくらのクラウドのものだが、同じ構造のずれは、他のクラウドでも出会う種類のものだ。

    EastCloud ではさくらのクラウド上でアプリケーション実行基盤(PaaS)を開発している。以下は、その過程で実際に API を叩いて確かめた、仕様や signal と実機のずれである。3 つの差分を挙げ、そのうち一つについては、なぜ自分たちがそれを踏んだのかも書く。各差分には検証した時期を添える。なぜ時期を書くのかは、記事の終わりで触れる。仕様は変わり得るので、重要な判断の際は公式ドキュメントと各自の環境で改めて確認されたい。

    仕様書・SDKが言うことと実機の挙動の対応表。型のずれ・経路のずれ・成功と構成の3つについて、公式の記述と実機の挙動と正しい確かめ方
    図:仕様書・SDK が言うことと、実機の挙動。3 つの差分と、それぞれの正しい確かめ方

    差分 1:型のずれ(2026 年 5 月)

    オブジェクトストレージのコントロール API(バケットやアクセスキーを管理する面)で、アクセスキーを発行する処理がある。その応答に、キーの id が入っている。

    仕様書では、この id は 整数(64 ビット整数)と定義されている。だから素直に、整数として受け取る実装を書く。

    ところが実機は、この id を 20 文字の英数字の文字列で返す(S3 互換のアクセスキー id の形式、たとえば EXAMPLEACCESSKEYID00 のようなもの)。整数型にデコードしようとする実装は——たとえば Go で int64 に受けると——作成が成功した 201 を受け取ったその瞬間に、パースで失敗する。

    しかも、これは単に「読み取りで止まる」だけでは済まない。このキーのシークレットは、発行時の応答にしか含まれず、後から取り直せない。つまり応答のパースに失敗すると、キーは作られたのにシークレットを受け取れず、二度と使えないキーが残る。 「作成は成功したのに」という分かりにくさに加えて、使えない孤児キーが積もるという実害がある。

    付け加えると、同じ仕様書の別の箇所——このキーを指定する URL のパラメータ——では、同じ id が文字列として定義されている。仕様書の中で型の表現が二通りあり、実機は文字列のほうと一致していた、ということだ。

    学び:仕様書の型は、実機の型と一致するとは限らない。 とくに「作成に成功した直後、そのレスポンスを読む」経路は、型のずれが成功を失敗に化けさせる場所なので、実際の値を一度は目で見てから、受け取る型を決めると安全だ。


    差分 2:ドキュメントに載っている経路が、想定どおりとは限らない(2026 年 6 月)

    バケットが存在するかどうかを確認したい、という素朴な要求がある。ドキュメントを読むと、バケット名の下に plan という副リソースのパスがある。存在確認に GET で使えそうに見える。

    ところが実機でこれを GET すると、405 Method Not Allowed が返る。 存在するバケットでも、しないバケットでも、一律 405。このパスは別の method で使うもので、GET で読む用途ではなかった。ドキュメントにパスがあることを根拠に GET を前提で実装すると、実機で初めて 405 に気づく。

    正解は別の副リソース、usage のほうだった。存在するバケットなら 200、存在しないバケットなら 404 を返す。存在確認には、こちらを使う。

    学び:ドキュメントにそのパスが載っていることと、想定した method でそれが読めることは、別である。 GET で状態を読むつもりの経路は、使い捨てのリソースで一度その method を叩いて、本当に読めることを確かめてから採用すると確実だ。


    差分 3:成功は、構成の正しさを保証しない(2026 年 9 月)

    これが、前回のサイレント障害の記事と地続きになる差分だ。

    冗長化構成のデータベースを作るとき、ネットワークインターフェースの指定が独特な形をしている。配列なのだが、位置に意味があり、先頭の要素は空でなければならない。 仮想 IP は 2 番目に置く。プランの指定も、素直に書きたくなる場所ではなく、別の決まった場所に置く。生の wire(通信上で実際にやり取りされるデータの形)だけを見ても、どれが正しい並びなのかは分かりにくい。

    ここで注意が要るのは、間違った形で作っても、作成 API が 201 を返すことだ。 しかもその後、可用性ステータスは available になり、インスタンスの状態は up になる。割り当てられた 2 つの実 IP には ping も通り、データベースのポートにも接続できる。ステータスを読む確認も、実 IP への疎通確認も、すべて通ってしまう。

    構成が誤っていると分かるのは、仮想 IP への通信を試したときだけだった。正常なら、仮想 IP 宛ての ARP が主系の NIC の MAC アドレスで解決される。誤った構成だと、この ARP が解決しない(今回の環境での挙動で、ARP は同じ L2 セグメントからでないと観測できない)。実 IP やステータスだけを見るヘルスチェックは、すべて緑のまま通る。 仮想 IP 経由で疎通を試して、初めて壊れていると分かる。この挙動は、事業者にも確認している。

    前回の記事で、「成功という signal は、試みたことの報告であって、効いたことの報告ではない」と書いた。これはその、クラウド API 側での一例である。作成が成功を返すことと、作ったものが意図どおり機能していることは、別のことだ。

    学び:作成 API の成功と available は、構成が正しいことの証明ではない。 その構成が本当に意図どおり機能しているかは、構成とは独立した経路——この場合は、実 IP でもステータスでもなく、仮想 IP 経由の疎通——で確かめる必要がある。


    なぜ、誤った形を作ってしまったのか

    差分 3 には続きがある。「なぜ、その誤った並びを作ってしまったのか」という話で、ここは仕様や実機の側ではなく、こちらの側の話だ。

    実は、さくらが配布している公式の Go ライブラリは、この位置依存をきちんと扱っている。高レベルの型には要素ごとに位置を指定するフィールドがあり、内部のシリアライズが、指定された位置に要素を置いて、それより前を null で埋めて送る。答えは、ライブラリの中にあった。 高レベルの型を使えば、利用者は位置を正しく指定するだけで、正しい wire が組み上がる。ただし、その位置の指定を忘れると、Go のゼロ値がそのまま有効な位置として送られ、高レベルの型を使っていても差分 3 と同じ誤った形になり得る。ゼロ値が「未指定」と区別されないのは、別の場面でも刺さる注意点だ。

    では素直に高レベルの型を使えばよい、という話でもある。ただ、事情があって自前で wire を組むことはある。その場合、ライブラリがやってくれるはずの位置合わせを、自分で持つことになる。そして——これが痛いところだが——別のリソース(VPC ルータ)では「先頭は特別で null を置く」という同じ作法をすでにコードに書いてあったのに、データベースには引き継げていなかった。同じ作法を、片方では encode し、もう片方では落としていた。

    ここに、表面と振る舞いの差がある。型のシグネチャや、wire の生の形だけを眺めていると、「位置に意味がある」という約束事は見えてこない。それは、シリアライズの実装や、隣のリソースのコードの中に書かれている。表面の形だけを読んで、振る舞いまで読まなかった。 差分 3 で作った誤った形は、この読み落としの産物であり、しかも実機がそれを 201 で受理したので、気づく機会はいっそう遠のいた。

    学び:答えは、すでにライブラリや既存のコードの中にあることがある。 シグネチャや wire の表面だけでなく、その振る舞いまで読む。そして、表面に従って組んだものが正しいかどうかは、やはり実機で——意図どおり動くまで——確かめる。


    仕様も実機も、時間で変わる

    各差分に検証時期を添えた理由を書く。この記事自体が、その理由の実例になったからだ。

    本稿には当初、データベースのプラン変更と復元に関する差分を、あと 2 つ入れる予定だった。どちらも、実機で確かめた内容だ。だが公開前に確かめ直すと、どちらも今の記事には使えなかった。しかも、使えなかった理由が、2 つで正反対だった。

    プラン変更のほうは、6 月に挙動を確かめたあとに、その機能自体が一時的に停止されていた。観測のあとで、世界が動いていた。復元のほうは逆で、8 月に「API が見当たらない」と確かめたのに、任意の時点へ戻す機能(PITR)が、それより前から提供されていた。世界は動いていない。こちらが、別の場所を見落としていたのだ。

    過去の観測は、この二通りで裏切る。あとから古くなるか、はじめから一面的か。どちらにしても、そのまま今の事実としては使えない。

    同じことは第 1 弾でも起きた。あのとき「サービスプリンシパルではプロジェクトを作れない」と書こうとして、実機を叩き直したら、作れるようになっていた。階層構造の機能が、その少し前に提供されていたからだ。

    だから、仕様と実機の差分を扱うときは、必ず検証の時期を書く。 そして、過去の観測を今の事実として断定しない。公式ドキュメントが実機とずれるのと同じくらい、自分の観測も、現在の——あるいは観測した当時の——実機とずれていることがある。


    まとめ

    公式ドキュメントは、API を組むときの出発点だ。信頼できる出発点である。ただ、終着点ではない。そして公式が配布する SDK には、ときに答えそのものが書かれている——表面だけを眺めていると、それに気づけない。

    仕様書の型と実機の型が食い違うことがある。ドキュメントに載っているパスが、想定した method では読めないことがある。誤った構成でも作成は成功して available になり、実 IP やステータスを見る確認では壊れが見えないことがある。そして、その誤った構成を自分で作ってしまう原因は、ときに、答えが既にある場所——ライブラリの実装や、隣のリソースのコード——の表面だけを読んで、振る舞いまで読まないことにある。

    防ぎ方は、連載を通じて同じだ。ドキュメントや型という表面を鵜呑みにせず、使い捨てのリソースで実機を叩き、型・経路・成功を自分の目で確かめる。 ライブラリや既存のコードに答えがないかは、シグネチャだけでなく振る舞いまで読む。そして、その確認には日付を付ける。仕様も実機も、確かめた瞬間の姿でしかないからだ。

    公式ドキュメントは、実機という現実を写し取ろうとした、よくできた地図である。地図と現地のあいだのわずかな差分を、自分の足で歩いて埋める。それが、クラウドの上に基盤を作るという仕事の、地味だが本質的な部分である。


    参考リンク

  • 「成功」が嘘をつくとき — PaaS 運用で繰り返し踏んだサイレント障害

    「成功」が嘘をつくとき — PaaS 運用で繰り返し踏んだサイレント障害

    エラーを出さないバグが、いちばん危ない

    前回、さくらのクラウドで PaaS を作るときの認証情報の使い分けを書いた。その記事で一度触れた話がある。「認証が通った」は「意図した身分で認証が通った」を意味しない、というものだ。認証情報を取り違えても、各値が整合していればそのまま通ってしまい、エラーでは気づけない。処理が成功を返したことと、処理が意図どおりに効いたことは、別のことである。

    EastCloud ではさくらのクラウド上でアプリケーション実行基盤(PaaS)を開発している。その運用を続けるうちに分かってきたことがある。いちばん危険なバグは、エラーを吐くバグではない。成功を返しながら、実際には何も起きていないバグである。

    エラーは、少なくとも気づける。ログに赤い行が出て、アラートが鳴り、誰かが調べ始める。だが「成功を返しながら動いていない」バグは、失敗を見張る監視には引っかからない。すべてのレコードが succeeded だからだ。これを本稿では サイレント障害(静かに壊れていて、しかし失敗の signal を一切出さない状態)と呼ぶ。

    処理が成功を返し記録され監視も静かだが、本当に効いたかは検証されていない。試みの成功と効果の成功の隙間にサイレント障害が棲む
    図1:成功という signal は「試みた」ことの報告であって、「効いた」ことの報告ではない

    以下は、運用の中で繰り返し踏んだサイレント障害を、構造ごとに 4 つに分けたものである。個別のシステム名や数字は本質ではないので省く。大事なのは、どれも同じ一点から来ているという事実のほうだ。


    パターン 1:成功を返し続ける復旧ループ

    障害から自動で立ち直る仕組みを入れたとする。あるコンポーネントが落ちたら、作り直す。作り直しが済んだら「成功」を記録する。素直な設計に思える。

    ところが、作り直しの処理は成功を返すのに、作り直したはずの状態が実際には回復しない、という状況が起こり得る。たとえば作り直しの API 呼び出し自体は 200 を返すが、対象が別の理由で起動しきらない。すると仕組みはこう振る舞う。落ちていると判断し、作り直し、成功を記録し、しかし状態は回復していないので、次の巡回でまた落ちていると判断し、また作り直し、また成功を記録する。

    この無限ループの一周ごとに「成功」のレコードが積み上がる。 気づいたときには、成功を表す記録が大量に溜まっていた。失敗は一件も無い。だから、どの監視にも引っかからなかった。

    真因はこうだ。仕組みが見ていたのは「作り直しの処理が成功したか」であって、「直したかった状態が回復したか」ではなかった。成功の件数は、健全性の signal ではない。 むしろ、成功の件数が異常に増え続けていること自体が、何かが回復していないことの signal だった。

    教訓

    「試みが成功したか」ではなく「直したかった状態そのもの」を測る。 復旧ループを組むなら、ループが解消しようとしている条件を、ループの成否とは独立に観測する。同じ復旧が短時間に何度も走っていたら、それは成功ではなく、収束していないという警報である。


    パターン 2:止まっても「成功」に見える送り出し

    バックグラウンドで何かを送り続ける処理がある。ログの転送、バックアップの取得、メトリクスの送出。こうした「継続的に動き続けるもの」には、別の形のサイレント障害が潜む。

    それは、止まり方によっては、エラーを出さない。ただ静かになるだけである。

    送り出しが止まったとき、エラーのログは出ない。最後の送信が成功したあと、次が来ないだけだ。監視が「失敗したら鳴る」ようにできていると、この沈黙は検知できない。失敗の不在と、正常稼働は、見た目が同じになる。 ログやメトリクスが届かなくなっても、画面上は何事もなく「最後の成功」が表示され続ける。そして、それが必要になったとき——障害調査でログを遡ろうとしたとき——初めて、ずっと前から止まっていたことに気づきかねない。

    教訓

    継続的な処理は、失敗ではなく「陳腐化」で監視する。 「最後に成功した時刻」を持ち、それが一定時間を超えて更新されなければ鳴らす。監視すべきは「失敗が起きたか」ではなく「成功が途切れていないか」である。この 2 つは似ているようで正反対で、前者だけを監視していると、静かに止まったものを永久に見逃す。

    ひとつ注意がある。その「最後に成功した時刻」を、止まった送り出しと同じ経路で送っていると、経路ごと止まったときに更新も届かず、監視側からは単なる「データなし」に見える。データが来ないこと自体を警報にしておかないと、鮮度監視もまた同じ沈黙に陥る(いわゆる dead man’s switch の考え方だ)。


    パターン 3:台帳は「消した」と言うが、実体は残っている

    クラウド上にリソースを作ったり消したりする基盤を運用していると、2 つの「状態」を持つことになる。ひとつは、自分たちの台帳——「何があるべきか」を記録したデータベース。もうひとつは、クラウド事業者の側にある実体——「実際に何があるか」。

    この 2 つは、ずれる。

    環境を撤収する処理が途中まで成功し、途中で失敗したとする。台帳には「削除済み」と書き込まれたが、クラウド側の実体は消えずに残った。台帳は自分に「消した」と記録しているので、もう誰もそのリソースを見に行かない。だが実体は動き続け、課金も発生し続ける。 失敗のログは残っていないか、残っていても撤収の完了レコードに上書きされて見えない。

    これは前回の記事で書いた話と同じ構造だ。クラウドの一覧 API は、こちらが聞きたい質問(アカウントに何があるか)とは違う質問に答えている。台帳もまた、こちらが知りたいこと(実体はもう無いか)ではなく、こちらが記録したこと(消したと書いた)を答えているにすぎない。

    教訓

    「あるべき状態」の台帳と、「実際の状態」の実体がある場合、台帳の自己申告を証拠にしない。 定期的に実体の側を読み、台帳と突き合わせる照合(reconciliation)を回す。台帳が「消した」と言っていても、API で引いて本当に 404 が返るまでは、消えたことにしない。ただし——これは第 1 弾の壁 4 と地続きだが——別のプロジェクトの鍵で引けば、実体が残っていても 404 は返る。照合では「どの鍵で 404 を見たか」まで揃える必要がある。自分の記録は、現実の観測の代わりにはならない。


    パターン 4:宣言した側と、読む側の契約がずれる

    複数のコンポーネントが、構成を受け渡して動くシステムでは、もうひとつの形がある。片方が宣言した項目を、もう片方が読んでいない。 しかも、そのずれは何のエラーも出さない。

    たとえば、構成を宣言する側が、いくつかの設定を有効にすると書く。それを実行する側が、実はそのどれも読んでいない。宣言ファイルは文法的に正しいので、検証は通る。実行する側もエラーなく動く。だが、宣言したはずの設定は一つも効いていない。双方が独立に正しく動いているので、接続部にだけ空いた穴は、どちらのテストにも映らない。

    別の場面でも、まったく同じ形のバグを踏んだことがある。構成ファイルはある値を A というフィールドに書き、それを読む実装は B という別のフィールドを見ていた。両者とも単独では正しく、エラーも出ず、しかし渡したつもりの値は一度も渡っていなかった。これも、宣言と読み取りの契約がずれていた例である。

    教訓

    2 つのコンポーネントが構成を受け渡すなら、「読む側が、書く側の宣言を本当に全部消費しているか」をテストで固定する。 各コンポーネントが単独でコンパイルを通ることは、接続部が正しいことを意味しない。宣言された項目の一つひとつが、実際に読まれ、実際に効いていることを、端から端まで通して確かめる仕組みが要る。もうひとつ安いのは、読む側が知らないフィールドを受け取ったらエラーにすること(未知フィールドの拒否)だ。書く側の宣言を読む側が知らなければ、その時点で弾ける。


    共通する形と、共通する防ぎ方

    4 つのパターンは、すべて同じ一点から来ている。

    処理が返す「成功」は、「やってみた」ことを報告しているだけで、「効いた」ことを報告していない。 復旧の試みは成功するが、復旧は効いていない。送信の仕組みは正常だが、送信は途絶えている。削除は記録されたが、実体は消えていない。宣言は検証を通るが、読まれていない。どれも、試みの成功を、結果の成功と取り違えている。

    だとすれば、防ぎ方も共通する。signal そのものを信じず、signal とは独立した ground truth(現実の、動かぬ事実)で効果を確かめる。

    • 復旧ループは、成功の件数ではなく、直したかった状態が回復したかを見る
    • 継続的な処理は、失敗ではなく、最後の成功からの経過時間を見る
    • 台帳は、自分の記録ではなく、事業者の実体を読んで突き合わせる
    • 宣言は、各側が通ることではなく、読む側が全項目を消費しているかを通しで確かめる

    いずれも「調べたい対象そのもの」を観測しにいっている。調べたい対象が返してくる「成功」という自己申告を、証拠として採用しない。

    4つのサイレント障害パターンと、各々で信じてはいけない成功・確かめるべきground truth・検知の仕方の対応表
    図2:4 つのパターンは、すべて「signal ではなく ground truth を見る」に収束する

    まとめ

    前回の記事の「認証が通った、は、意図した身分で認証が通った、を意味しない」も、本稿の 4 つのパターンも、一文に畳める。

    成功という signal は、試みたことの報告であって、効いたことの報告ではない。

    エラーを出すバグは、少なくとも気づく手がかりを残す。だが成功を返すバグは、その手がかりを自分から消してしまう。だから、継続的に動くもの・自動で直るもの・外部の実体を持つもの・コンポーネント間で何かを受け渡すものを作るときは、最初から「これはどうやって静かに壊れ得るか」「静かに壊れたとき、何を見れば気づけるか」を設計に織り込んでおく必要がある。

    成功を信じない。効果を、動かぬ事実で確かめる。地味だが、サイレント障害に対してはこれが基本の構えである。

    続編として、公式ドキュメントや仕様が実機とずれる場面——仕様を読んだだけでは辿り着けない落とし穴——を別稿で扱った。


    参考リンク

  • 同じAIモデルなのに結果が違う?AI CLIの原因切り分け手順

    同じAIモデルなのに結果が違う?AI CLIの原因切り分け手順

    同じAIモデルを選んだのに、Codexでは修正まで進み、別のAI CLI(コマンドライン型のAI開発支援ツール)では途中で迷う。そんな差は、モデル名だけを見ても原因を切り分けられません。

    この記事が答える問いは、「同じAIモデルを選んだのにAI CLIで結果が違うとき、何をどの順番で確認すればよいか」です。

    先に結論を言うと、作業条件、モデルと版、指示と会話履歴、ツールと権限、実行環境の順に確認します。それらがそろって初めて、一つの条件だけを変えた比較へ進みます。

    この記事はこんな人向け

    • CopilotでGPT系モデルを選んだ結果と、Codexの結果が違って困っている
    • Claude CodeやCodexを替えたら、指示の守られ方やツールの使い方が変わった
    • 「モデルが悪い」と決める前に、設定や環境の差を調べたい
    • 比較結果をチームで再確認できる形に残したい

    なぜ同じモデル名でも結果が変わるのか

    AI CLIは、依頼文をモデルへ渡すだけの箱ではありません。指示ファイルを探し、利用できるツールをモデルへ示し、ファイルやコマンドの結果を会話履歴へ戻し、権限を確認します。長い会話を圧縮したり、別のエージェントへ一部の作業を任せたりする製品もあります。

    そのため、同じモデル名でも次の条件が違えば、取れる行動が変わります。

    • 実際に使われたモデルの版と提供元
    • システム指示、リポジトリの指示、追加したスキル
    • モデルから見えたツールと、その実行結果
    • 新しい会話か、再開した会話か、圧縮後の会話か
    • ファイル、ネットワーク、コマンドの権限
    • OS、シェル、作業ディレクトリ、依存関係

    つまり、比較するのはモデル単体ではなく、モデルを含む実行条件一式です。

    同じAIモデルで結果が違うとき、作業条件、モデルと版、指示と会話履歴、ツールと権限、実行環境の順に確認する流れ
    図1:上から順に条件を確認します。取れない情報は「不明」と残し、原因を推測で埋めません。

    症状ごとに最初の確認場所を変える

    観測した症状最初に確認することここでは断定しないこと
    同じモデル名なのに回答が違うモデルの提供元、確認できる版、推論設定(考える量)表示名だけでモデル本体の差と決めない
    指示を無視した読み込まれた指示ファイル、会話の圧縮、再開状態実行時の指示が不明なら、モデルの性格と決めない
    必要なツールを使わないその時点で見えていたツール、MCP(AIから外部ツールへ接続する仕組み)の接続状態、権限ツールが見えていなければ、選択ミスと決めない
    長い作業で急に迷う圧縮の発生、大きな出力、再開の有無圧縮を確認できなければ、忘れたと決めない
    ファイルを読めない・書けない権限、除外設定、組織の方針権限拒否を能力不足と扱わない
    Windowsだけ失敗するシェル、パス、文字コード、依存関係OS条件をそろえる前に製品全体の差へ広げない

    原因を切り分ける6つの手順

    1. 作業と合格条件を固定する

    依頼文だけでなく、開始時のコミット、未保存の変更、依存関係、テスト、制限時間、ネットワーク条件をそろえます。開始状態や採点方法が違うなら、同じ課題の比較ではありません。

    2. モデル名とCLIの版を分けて記録する

    選択時の名前、実行ログなどで確認できたモデル名・版、提供元、CLIの版を別々に残します。

    製品画面や設定に表示された名前だけでは、実際に使われた版を確定できない場合があります。確認方法がない項目は「不明」とします。

    3. 指示と会話履歴を確認する

    システム指示、ユーザーの依頼、AGENTS.mdやCLAUDE.mdなどのリポジトリ指示を分けます。どのファイルが読み込まれたか、会話を再開したか、途中で圧縮されたかも記録します。

    4. 見えていたツールと権限を確認する

    モデルは、存在を知らないツールを選べません。ツール一覧、MCPの接続、実行エラー、承認待ち、ファイルとネットワークの権限を確認します。

    5. OSと作業環境をそろえる

    対話実行、非対話実行、IDE(統合開発環境)、デスクトップ、クラウドでは処理の流れが異なる場合があります。OS、シェル、作業ディレクトリ、依存関係まで含めて同じ条件かを確かめます。

    6. 一つだけ変えて複数回比べる

    ここまでの条件を固定し、モデル、CLI、指示、ツールのうち一つだけを変えます。実行順を入れ替え、事前に決めた回数だけ繰り返します。1回の勝敗だけで順位を作りません。

    実際にハマりやすい4つの点

    表示名を正確なモデル版だと思う

    表示名や別名が指す先は、時期や提供元で変わる可能性があります。変更されない識別情報を取れなければ、「同じモデルの比較」とは言わず、「異なるAI CLIの比較」として扱います。

    最終回答だけを保存する

    最終回答だけでは、ツールが見えなかったのか、権限で止まったのか、会話の圧縮で条件を落としたのか分かりません。ツール履歴、エラー、終了理由も残します。

    失敗した実行を再試行で消す

    タイムアウト、利用制限、権限停止も実際の使い勝手の一部です。再試行する場合は元の失敗を残し、別の実行として記録します。

    同じ提供元のCLI(ネイティブ製品)が常に勝つと決める

    モデルとCLIを同じ提供元が調整できることは有利に働く可能性があります。しかし、常に勝つとは限りません。SWE-agentの研究でも、同じ基盤モデルでも操作方法や見せる情報で成績が変わり、情報を多く見せれば必ず改善するわけではないことが示されています。

    チームで残す記録

    比較1回ごとに、少なくとも次を残します。

    項目記録する内容
    課題依頼文、対象リポジトリ、開始コミット、合格条件
    製品AI CLI名、版、実行方法
    モデル選択時の名前、実行ログなどで確認できたモデル名・版、提供元。不明なら理由
    指示読み込まれた指示ファイル、追加したスキル
    会話新規・再開・分岐、圧縮の有無
    ツール見えていたツール、接続状態、エラー
    権限ファイル、ネットワーク、コマンドの許可と拒否
    結果変更内容、テスト、所要時間、停止理由

    今回確認できた範囲

    公開仕様と研究から、モデルの外側にある指示、ツール、会話履歴、権限、実行環境が結果へ影響し得ることは確認できます。

    一方、今回の記事ではCodex、Claude Code、Copilot CLIを同じ課題・同じ条件で比較実験していません。どの製品が高性能か、どの条件が今回の体験差を生んだかは不明です。

    この記事で示したのは順位ではなく、原因を調べる順番です。情報を取得できない段階では結論の範囲を狭めてください。

    参考資料

    まとめ

    同じAIモデルを選んでも、AI CLIが違えば、指示、ツール、会話履歴、権限、実行環境が変わります。

    作業条件から順に確認し、分からない項目は「不明」と残します。条件がそろった後で一つだけ変えて複数回比べると、「モデルが悪い」という感想を、再確認できる原因候補へ変えられます。

  • AIコーディングCLIの比較結果は信用できる?4つの落とし穴と防ぎ方

    AIコーディングCLIの比較結果は信用できる?4つの落とし穴と防ぎ方

    AIコーディングCLI(コマンドラインで動かすAIコーディングツール)を同じ課題で動かし、合格率や処理時間を比べる。数字を出すこと自体は難しくありません。難しいのは、その数字が本当に元の実行結果を表していると確認することです。

    この記事が答える問いは、「AIコーディングCLIを比較するとき、非公開テストの漏洩、偽の合格、失敗の分母落ち、出所不明のCSVをどう防ぐか」です。

    この記事では、次の4条件を満たす比較を「安全に結果を使える比較」とします。非公開テストが評価対象から見えない。候補コードが出した文字列を採点結果と誤認しない。失敗を含む全試行が残る。公開した集計を元の実行記録までたどれる。このどれかを確認できなければ、順位は出しません。

    結論は四つです。非公開テストの詳細を評価対象CLIへ返さない。候補コードと採点器の出力を分ける。タイムアウトや採点不能を分母から消さない。CSVを元の実行記録から作り直せるようにする。この四つが確認できるまで、製品の順位は出しません。

    この記事はこんな人向け

    • Codex、Claude Code、Copilot CLIなどを同じ課題で比較したい
    • AIコーディングツールの社内評価を作っている
    • 非公開テストを置けば安全だと思っている
    • タイムアウトを除いた合格率に違和感がある
    • CSVやレポートを第三者が再確認できる形で残したい

    ベンチマークが壊れる4つの場所

    1. 非公開テストは標準出力からも漏れる

    非公開テストを作業ディレクトリへ置かなくても、採点器が失敗したテスト名、期待値、確認式の断片を標準出力へ流せば、評価対象CLIへ情報が戻ります。再試行できる仕組みでは、1回目の失敗が2回目の答え合わせになります。

    公開Issueでも、前段の検証結果や非公開扱いのデータが次のエージェントから見える問題が報告されています。「非公開」という名前や配置だけでは、実際に見えないことを保証できません。

    対策は、ファイルと出力の両方を分けることです。

    • 評価対象CLIへ渡すのは、課題、開始時のコード、公開テストだけにする
    • 候補コードを確定してCLIを終了した後、分離した採点環境で非公開テストを使う
    • 同じ試行のCLIへ、合否や非公開テストの詳細を返さない
    • 再試行する場合は、別の非公開テストを使うか、新しい試行として分母に数える
    • 詳細な期待値や採点ログは、CLIから見えない監査用の場所へ保存する
    • 標準出力、標準エラー、環境変数、引数、作業ファイルの全経路を目印文字列で確認する

    2. 候補コードと採点器を同じ場所で動かすと偽合格を見抜けない

    候補コードと採点器を同じプロセスで動かすと、どちらが出した結果か分からなくなる危険があります。候補コードが次のような採点結果らしい文字列を出しても、見た目だけでは本物と区別できません。

    {"passed":6,"total":6,"score":1}

    また、採点処理を呼び出せたことを示す終了コード0と、課題に合格したことを混同すると、不合格まで成功に見えます。

    対策は、候補コードの実行と採点を分け、採点器が作った結果だけを管理側から受け取ることです。そのうえで、課題ID、問題数、合格数、点数、各テスト結果の件数を照合します。passed=6、total=6なのに結果が1件しかなければ、合格ではなく採点結果の不正として止めます。

    3. タイムアウトを除くと、失敗の多いCLIが有利になる

    合格率を「合格数 ÷ 正常に終わった実行数」だけで計算すると、タイムアウト、異常終了、権限停止、採点不能を分母から落とせます。半分止まるCLIでも、完走した回だけを見れば強く見えてしまいます。

    運用時の成績では、実行前に割り当てた最初の試行を分母へ残します。

    実行状態運用時の成績外部障害を除く参考成績
    A-1合格11
    A-2タイムアウト00
    A-3採点基盤の障害0除外
    A-4一部だけ完了00

    この例では、運用時の分母は4、外部障害を除く参考値の分母は3です。どちらか一方が常に正しいのではなく、答える問いが違います。後から都合のよい方だけを見せないため、両方の定義を実行前に決めます。

    4. CSVを再計算できても、出所は証明できない

    CSVから合格率を再計算して同じ数字になっても、CSVの行が本当に元の実行から作られたとは限りません。行を手で追加しても、そのCSVだけを再計算する処理では見抜けません。

    必要なのは、次の流れをたどれることです。

    実行 → 採点 → 実行記録 → CSV → 分析

    CSVは保存済みの実行記録から自動生成します。検証時も保存済みCSVだけを読み直すのではなく、元の実行記録からCSVを作り直し、分析結果まで一致するか確認します。

    元記録の信頼起点には、集計を確定した時点の実行記録を読み取り専用で複製した「確定スナップショット」を使う方法が、最も再現しやすいでしょう。

    1. 実行前の割当一覧に、課題IDと割り当てた試行数を記録する。
    2. 各試行の終了後、合格、不合格、タイムアウト、異常終了、採点不能の状態を元記録へ残す。
    3. 集計を確定する時点で、元記録を読み取り専用の場所へ複製する。
    4. 割当一覧と確定スナップショットの課題ID、割当試行数、状態別件数を照合する。
    5. 照合に通った確定スナップショットからCSVを再生成し、公開する集計と比べる。

    読み取り専用スナップショットを作りにくい環境では、既存行を変更せず訂正も新しい行として追加する台帳を使います。別の保管先へ複製する場合は、ファイル内容から計算する改ざん検知用の照合値(例:SHA-256)を併記する方法もあります。ただし、照合値だけでは「どの実行から作られたか」は証明できないため、課題ID、割当試行数、状態との照合も必要です。

    AIコーディングCLIの比較で、評価対象CLI、分離した採点環境、実行記録、CSV、分析をつなぐ証拠の流れ
    図1:結果を左から右へたどります。漏洩、件数矛盾、分母落ち、元記録との不一致が一つでもあれば順位を出しません。

    実際に見つかった3つの欠陥と修正

    模擬データを使った自己テストの後、別担当の確認で三つの欠陥が見つかりました。

    一つ目は、実行がタイムアウトした状態と、採点できなかった状態を同じ項目で扱っていたことです。このままでは、分母へ残すべき失敗を集計前に失う可能性がありました。修正後は、実行状態と採点状態を別々に保存し、矛盾する組み合わせを拒否します。

    二つ目は、実行ごとにコピーした評価条件一覧だけを確認し、基準となる一覧と同じ内容かを確かめていなかったことです。修正後は、実行記録が参照する評価条件と、変更されない基準版の対応を確認します。

    三つ目は、検証処理が保存済みCSVから分析を再計算するだけで、元の実行記録からCSVを作り直していなかったことです。修正後は、元記録を読み、CSVを再生成してから分析結果まで照合します。

    同じ欠陥が再発しない試験を追加し、模擬データを改変した場合に処理が停止することを再確認しました。ただし、確認したのは比較基盤の整合性です。実際のAIモデルの性能順位を確認したわけではありません。

    本番前に行う4つの小さな確認

    漏洩の確認

    非公開テストへHIDDEN-CANARY-1234のような目印を入れ、意図的に失敗する候補コードを採点します。評価対象CLIから見えるファイル、標準出力、標準エラー、環境変数、引数のどこにも目印が出ないことを確認します。

    偽合格の確認

    候補コードに、合格したように見えるJSONと終了コード0を出させます。採点器の結果として受理されず、不正な採点結果として止まることを確認します。

    分母の確認

    合格、タイムアウト、採点基盤の障害、一部完了の4行を用意します。運用時の成績では4行すべてが分母に残り、外部障害を除く参考値だけが3行になることを確認します。

    CSVの出所確認

    実行前に課題IDと割当試行数を記録し、実行後の状態を含む元記録から、集計確定時の読み取り専用スナップショットを作ります。課題ID、割当試行数、状態別件数を照合してからCSVを再生成します。

    確認試験では、スナップショットの課題ID、件数、状態のいずれか一つを変更します。検証処理が保存済みCSVを信用せず、不一致を検出して止まることを確認します。

    結果を使ってよいか判断する表

    観測した状態判定次の行動
    非公開情報がCLIの出力や環境から見える使用しない課題を廃棄し、未露出の課題でやり直す
    候補コードと採点器の出力を区別できない使用しない実行環境と採点経路を分ける
    問題数、合格数、点数、結果件数が矛盾する採点不能合否を付けず、原因を調べる
    タイムアウトを分母から落としている再集計最初の試行を分母へ戻す
    CSVはあるが元の実行記録へ戻れない未確認順位を出さず、参考値として扱う
    元記録からCSVと分析を作り直せる次へ進める候補別担当の確認と限界確認へ進む

    今回確認できた範囲

    今回確認したのは、模擬データを使った比較基盤です。非公開テストの出力漏洩、偽合格、状態の矛盾、分母落ち、CSVの出所不明を、異常な入力で拒否できるかを試しました。

    実際のCodex、Claude Code、Copilot CLIを使った比較実行は行っていません。そのため、製品の順位、実際の合格率、速度、費用はこの記事から判断できません。

    また、採点環境を論理的に分けても、OSレベルの隔離まで自動的に証明できるわけではありません。実運用では、コンテナや仮想マシン、ファイル権限、ネットワーク、プロセスの見え方を別に確認する必要があります。

    同じ課題を複数回実行したときの統計処理も重要ですが、この記事では深掘りしません。反復回数の扱いと信頼区間は、別の記事で扱う候補とします。

    参考資料

    まとめ

    AIコーディングCLIを比較するときは、最後の合格率だけを見ても結果を信用できません。

    非公開テストの情報を戻さない。候補コードと採点器の出力を分ける。タイムアウトや採点不能を分母から消さない。CSVを元の実行記録から作り直す。この四つを確認して初めて、製品を比べる準備が整います。

  • Claude Codeの精度が落ちたと感じたときに確認する6項目

    Claude Codeの精度が落ちたと感じたときに確認する6項目

    Claude Codeを長く使っていると、前より指示を外す、必要なファイルを読まない、途中で作業を終えるように見えることがあります。

    この記事が答える問いは、「Claude Codeの精度が落ちたと感じたとき、モデルの能力低下と決める前に何を確認すればよいか」です。

    確認するのは、症状、発生時点、会話の圧縮、指示と接続、大きな出力、新しいセッションでの再現という6項目です。

    この記事はこんな人向け

    • 長いセッションの途中から回答や実装が雑になったと感じる
    • /compactの後に要件や禁止事項が抜けたように見える
    • CLAUDE.mdやSkills(定型手順を再利用する機能)を用意したのに指示が反映されない
    • MCP(外部ツールとの接続)を追加した後から、ツールを使わない、途中で省略する症状が出た
    • 不具合報告やチーム共有の前に、再現条件をそろえたい

    1. まず「精度が落ちた」を一文にする

    「精度が落ちた」だけでは、次に何を調べるか決まりません。観測した症状を、他の人が確認できる書き方へ変えます。

    症状観測できる書き方最初に確認すること
    誤答既存実装を読まず、存在しないAPIを提案した読んだファイル、モデル、セッション状態
    指示逸脱変更禁止と伝えたファイルを書き換えたCLAUDE.mdの読み込み、指示の競合
    途中省略テスト前に完了と答えた会話の残量、ツールエラー、承認待ち
    古い前提訂正済みの仕様を再び使った再開した会話、圧縮後に残った情報
    ツール未使用検索やMCPを使わず推測で答えた接続状態、権限、利用できるツール
    再現しない失敗同じ依頼でも成功したり失敗したりする固定できていない条件、実行回数

    利用者からは、長いセッションで制約が抜けたという報告、再開後にMEMORY.mdの内容が失われたという報告、長いセッションで手順の後半が省略されたという報告があります。いずれも利用者報告であり、原因が確定した事例や、現在のすべての環境で起こる不具合を示すものではありません。

    Claude Codeの精度低下を、症状、発生時点、圧縮、指示と接続、大きな出力、新しいセッションの6項目で確認する図
    図1:上から順に確認します。どの項目も、モデル能力の低下を自動的に証明するものではありません。

    2. 発生時点と現在の状態を保存する

    新しい会話を始める前に、症状が出た直後の状態を残します。

    • Claude Codeのバージョンと選択したモデル
    • /contextで見える現在のコンテキスト(現在参照している会話・指示・ツール情報)
    • 作業ディレクトリとコミット
    • /compactの前か後か、再開した会話か
    • 直前に大きなログ、差分、検索結果を読んだか
    • MCPやSkillsを追加・変更した直後か
    • いつまでは期待どおりで、どの操作の後から変わったか

    Claude Codeの公式デバッグ資料では、/context、/doctor、/hooks、/mcpを使って、読み込まれた設定や接続状態を確認できます。

    ただし、/contextの表示だけでは、内部で各情報がどの程度重視されたかまでは分かりません。

    3. 圧縮の前後で残った情報を比べる

    /compactは、長い会話をそのまま全量保持する操作ではありません。圧縮後は、重要な要件が残ったか、必要なファイルを読み直したかを確認します。

    確認するもの圧縮前圧縮後
    中心の目的一文で説明できる同じ目的を説明できる
    禁止事項回答に反映された同じ禁止を守る
    対象ファイル読んだ履歴がある必要なら読み直した
    下位のCLAUDE.md対象範囲で読まれた該当ファイルを読んだ後に反映された
    完了条件テストや確認まで含む省略されていない

    公式資料では、プロジェクト最上位のCLAUDE.mdは圧縮後に読み直され、下位ディレクトリのCLAUDE.mdは、その範囲のファイルを読んだときに読み込まれると説明されています。

    内部の要約全文や、情報ごとの保持率を確認できない場合は、想像で補わず、目的・禁止事項・対象ファイル・完了条件を短く再提示します。

    4. 指示ファイルとMCPが実際に読み込まれたか確認する

    ファイルを置いたことと、その実行で読み込まれたことは別です。

    1. 現在の作業ディレクトリとプロジェクト最上位を確認する。
    2. /contextで読み込まれた指示を確認する。
    3. /mcpで接続状態と利用できるツールを確認する。
    4. /doctorと/hooksで設定やフックの問題を確認する。
    5. 短い目印となる指示を置き、対象範囲で読まれたことを確かめる。

    MCPが「接続済み」でも、利用できるツールが0件なら使えません。また、下位の指示ファイルは、対象ファイルを読むまで読み込まれない場合があります。

    5. 大きな出力と長い指示を減らす

    長いログ、巨大な差分、多数のMCPツール、長い指示書を一度に入れても、必ず良くなるわけではありません。診断中だけ、次の順に小さくします。

    1. 巨大なツール出力を、要点と参照先へ置き換える。
    2. 今回使わないMCPサーバーやツールを対象から外す。
    3. 長い指示から、目的・禁止事項・完了条件を抜き出す。
    4. 必要なファイルを明示して読み直させる。
    5. 同じ症状が残るか確認する。

    この最小化で症状が消えても、1回だけでは原因を確定できません。どの長さやツール数から悪化するかという共通の境界値も、タスクと版が違えば変わります。

    6. 新しいセッションで同じ条件を再現する

    現在のセッションだけを直し続けると、何が効いたか分かりません。履歴を保存してから、新しいセッションを作ります。

    固定する条件記録する内容
    入力実際に渡した依頼文
    コードコミット、未保存の変更
    実行環境Claude Codeの版、OS、シェル、作業ディレクトリ
    モデル表示名、確認できる実体、別モデルへの切り替え
    指示CLAUDE.md、Skills、追加した依頼文
    ツールMCP、フック、権限、承認設定
    判定期待する変更、禁止変更、テスト、確認手順

    新しいセッションでは、同じ依頼文、同じコミット、同じ版、同じモデル、同じツールと権限を使います。回答だけでなく、読んだファイル、ツール履歴、差分、テスト、停止理由も比べます。

    Claude Codeの症状を保存し、条件をそろえ、新しいセッションで再実行し、履歴と成果物を比較する流れ
    図2:新しいセッションは履歴を消して終わるためではなく、保存した症状と同じ条件で比べるために使います。

    一度の改善だけで原因を決めない

    新しいセッションで改善しても、それだけで「長い会話が原因だった」とは言えません。偶然の出力差、モデルの切り替え、更新、権限、作業状態の違いでも結果は変わります。

    反復回数と合格条件を先に決め、一つの条件だけを変えます。再現した条件だけを原因候補にし、確認できない項目は「不明」と残します。

    直らないときに残す記録

    不具合報告やチーム共有では、次を残します。

    項目内容
    症状何が期待と違ったか
    発生時点更新、圧縮、再開、MCP変更のどの後か
    期待結果合格と判断する条件
    環境Claude Codeの版、モデル、OS、シェル、コミット
    読み込まれた指示CLAUDE.md、Skills、その他の指示
    ツールMCPの接続状態、利用できるツール、使用履歴
    結果回答、差分、テスト、停止理由
    不明取得できない情報と、それによって判断できないこと

    今回確認できた範囲

    公開仕様から、/contextなどの診断コマンド、圧縮後のCLAUDE.mdの扱い、MCPの接続確認、大きなMCP出力への注意を確認できます。Anthropicは過去の品質問題で、モデル以外の設定やセッション状態が原因だった事例も報告しています。

    一方、今回の調査ではClaude Codeを使った比較実行を行っていません。新しいセッションでの改善率、再現率、速度差、費用差は不明です。公開Issueと手元の症状が同じ原因かどうかも、版とログを照合するまで分かりません。

    参考資料

    上のIssueはいずれも利用者報告であり、原因が確定した一次資料ではありません。症状を比べる手掛かりとして使い、対象の版と実行記録で確かめます。

    まとめ

    Claude Codeの精度が落ちたと感じたら、最初にモデルの能力低下と決めないでください。

    症状、発生時点、会話の圧縮、指示と接続、大きな出力、新しいセッションでの再現という6項目を順に確認します。履歴と成果物を残し、一つだけ条件を変えて比べると、体感を再確認できる問題へ変えられます。

  • AIエージェントの作業中に改善点を記録し、次回に生かす仕組みを作った

    AIエージェントの作業中に改善点を記録し、次回に生かす仕組みを作った

    ChatGPT、Claude Code、GeminiなどのAIツールやAIエージェントに、データ入力、調査、開発、監査を任せられる場面が増えている。ところが、作業が終わるたびに「どの確認が効いたのか」「なぜ手戻りが起きたのか」「次回は何を省けるのか」が会話の中に埋もれてしまう。

    そこで、実作業の中で得た気づきや失敗を記録し、次回の手順に反映する仕組みを作った。本記事では、この仕組みを改善研究ループと呼ぶ。AIが改善テーマと概算コストを先に提示し、人が選んだテーマ、または人が明示的にAIへ選定を任せたテーマだけを調べることで、依頼された作業を止めずに改善を続けられる。

    中心にある問いは一つだ。AIエージェントの実作業を止めずに、そこで得た知見を次回へどう反映するか。以下では、仕組みを作った理由、設計、今後確かめる指標を順に紹介する。

    この記事はこんな人向け

    • AIエージェントにデータ入力、調査、開発、監査を任せている
    • 作業中の気づきや失敗が、会話の中に埋もれている
    • 品質を落とさず、確認作業とトークン消費を抑えたい
    • AIの改善提案を、人が選べる形で運用したい

    AIに作業と研究を同時に頼むと起きる4つの問題

    「作業しながら、効率化も研究してほしい」という依頼は合理的に見える。しかし、研究の範囲を決めずに始めると、次の問題が起きやすい。

    • 依頼された作業が後回しになる:改善のための画面確認や比較に時間を使い、入力・開発・監査が進まなくなる。
    • 効果を測らないまま「改善できた」と判断してしまう:「速くなった気がする」という感覚と、ログや件数で確認した事実が混ざる。
    • 検証テーマの幅が狭くなる:目の前の小さな改善だけに偏ったり、反対に実行できないほど大きな構想へ飛んだりする。
    • 調査にかかるコストが膨らむ:トークン数、ツールの実行回数、待ち時間、確認作業の量を把握しないまま調査を続けてしまう。

    必要だったのは、AIへ漠然と「もっと考えて」と頼むことではない。何を調べるか、どこまで掘り下げるか、何を根拠に判断するかを先に決められる仕組みだった。

    依頼された作業と改善活動を分けて進める

    改善研究ループでは、ユーザーから依頼された作業と、その過程から改善点を集める活動を分ける。改善活動は実作業の横で補助的に進める。主役はあくまで依頼された作業であり、改善活動を理由に権限や作業範囲を広げることはしない。

    今回の依頼と改善記録を分け、改善記録だけを次回の依頼手順へ戻す2レーン構成図
    作業例は順番ではなく、判断・失敗・復旧・確認だけを次回の依頼手順へ引き継ぐ。

    記録と検証の詳しさは、作業の規模やリスクに応じて3段階から選べるようにした。

    モード用途記録するもの
    Lean(最小限)速度とトークン消費を抑えたい通常作業重要な判断、失敗、復旧手順、確認済みの件数
    Standard(標準)複数の工程を持つ作業計画と実績、採用・不採用の理由、再利用できる結論
    Deep(詳細)長期・高リスク、または調査自体が成果物になる作業役割分担、別担当による監査、検証に使ったログ・資料・判断記録一式

    毎回Deepを選べば詳しい記録は残る。ただし、改善の記録に時間をかけすぎると、依頼された作業を圧迫してしまう。通常はLeanから始め、リスクや不明点が大きいときだけ詳しく調べる。

    研究を始める前に、テーマとコストを一覧化する

    次に、改善テーマの選定をAI任せにしないための候補一覧を加えた。テーマが指定されていない場合は、細かな検証から定石にとらわれない仮説まで、方向の異なる候補を4〜6件提示する。

    以下の負荷と推定トークンは、今回の運用を始めるために仮置きした区分である。実績が蓄積した段階で見直す。

    ID研究テーマ例種類重要度負荷推定トークン
    R1「保存しました」という画面表示だけで、データが実際に保存されたと判断してよいか精密検証高軽S:2k〜5k
    R2一覧で対象を絞ってから詳細を開くと、画面の読み取り回数は減るか実務改善高中M:5k〜12k
    R3すべて入力した後にまとめて確認する方法と、入力と並行して順次確認する方法では、どちらがミスを防ぎやすいか仕組み中中M:5k〜12k
    R4あえて一画面・一対象に制限すると、異常にも早く気づけるか探索的仮説中軽S:2k〜5k

    候補を出す段階では、時間のかかる調査には着手しない。ユーザーは候補から選ぶだけでよく、必要なら複数のテーマを組み合わせたり、選定そのものをAIへ明示的に任せたりできる。もちろん、今回は改善研究を行わないという選択も残す。

    調査そのものが目的なら、テーマが選ばれてから着手する。実作業と並行する場合は、作業を進めながら判断理由や失敗内容だけを記録し、選ばれていない調査は始めない。

    トークン数は「実績」ではなく「計画値」として扱う

    AI運用では、トークン数を細かく見せるほど正確に見える。しかし、モデル、ツール出力、ファイルサイズ、会話履歴によって消費量は変わる。計測機能がない環境で「3,842トークン使う」と断定しても根拠がない。

    そこで、改善活動を追加したことで増えるトークンだけを、次の幅で見積もる。

    XSはおよそ2k以下、Sは2k〜5k、Mは5k〜12k、Lは12k〜25k、XLは25k超とする。

    これはあくまで推定範囲であり、依頼された作業そのものに使うトークンは含めない。また、トークン数が同程度でも、ブラウザの待ち時間や複数担当者との調整が必要なら負担は大きい。そのため、候補一覧では「推定トークン」と「作業負荷」を分けている。

    実際のトークン数を取得できる場合も、見積もりは消さず「推定」と「実績」を両方残す。直接計測できない場合は、詳細画面を開いた回数、ツールの実行回数、比較した資料数などを代わりの目安として記録する。

    「確認した事実」と「もっともらしい推測」を分ける

    研究記録は、次の4段階で根拠を分類する。

    • 確認済み:操作ログ、処理件数、ファイル内容の変化を示すハッシュ値、再読み込み後のデータなどで直接確かめた。
    • 計算値:実際に取得した数値を基に計算した。計算式や比較基準を示せる。
    • 推定:筋の通った説明はできるが、まだ比較実験はしていない。
    • 不明:必要な計測がない、または情報源が信頼できない。

    たとえば「一覧画面で対象を絞ったので速くなった」は、比較するまでは推定にすぎない。実際の効果を確かめるには、従来の手順と新しい手順で画面の読み取り回数や所要時間を比べる必要がある。一度うまくいった方法を、すべての作業に通用するルールだと決めつけないようにする。

    操作ログや処理件数などの証拠を4種類に分け、採用した知見だけを次回の手順へ反映する判断図
    証拠を分類し、採用・保留・不採用を判断してから次回の手順へ反映する。

    実際にハマったところ:保存表示だけでは確認にならない

    この記事を作る過程でも、アイキャッチ画像のタイトルと代替テキストは更新されていたのに、プレビューには古い画像が表示された。そこで画像ファイルそのものを開いて違いを確認し、正しい画像をアップロードし直した。保存後は編集画面を再読み込みし、プレビューの表示まで見直した。「設定値が変わった」で終わらせず、読者に見える結果まで確かめた例である。

    実装は、スキル・詳細ルール・記録スクリプトを分離する

    AIが毎回参照する SKILL.md には、作業方針を決める最小限のルールだけを置いた。詳しい進め方や記録用テンプレートは別ファイルに分け、必要なときだけ参照する。

    Gemini、Claude Code、Codexでは、設定ファイルや機能の呼び出し方が異なる。そのため、特定製品の設定をそのまま使い回すのではなく、「依頼された作業を優先する」「改善テーマを選ぶ」「確認できた事実と推測を分ける」「知見を次回の手順へ戻す」という共通部分を分離しておく。

    work-research-loop/
    ├── SKILL.md
    ├── agents/
    │   └── openai.yaml
    ├── references/
    │   ├── method.md
    │   ├── report-spec.md
    │   └── research-theme-menu.md
    └── scripts/
        └── research_ledger.py

    記録スクリプトは、作業開始時の条件、途中で起きたこと、計測結果、最終的に得た知見を決まった形式で保存する。同じ記録を再実行しても重複しないようIDを持たせている。複数のAIによる競合を防ぐため、運用上は改善記録を保存する担当を一つに限定し、ほかのAIは読み取りと確認だけを担当する。

    運用で外せない5つのルール

    1. 研究は権限を広げない:改善案を考えることと、データ更新・送信・公開の許可は別である。
    2. 同じデータを更新するAIは一つに絞る:並行して作業する場合は、担当するデータを完全に分ける。監査担当は読み取り専用にする。
    3. 保存完了のメッセージだけで判断しない:画面を再読み込みし、入力したデータが実際に残っていることまで確認する。
    4. 改善記録に機密情報を残さない:非公開リポジトリであっても、顧客名、認証情報、元資料へのURL、加工していない操作ログは保存しない。
    5. 提案と実行を分ける:定石にとらわれない案も候補には含めるが、選ばれていない実験は始めない。

    従来の進め方との違い

    従来の進め方改善研究ループを使う場合
    作業中の気づきが会話の中に埋もれる判断理由・失敗内容・復旧手順を決まった形式で残す
    AIが調査範囲を暗黙に決める候補と概算コストを見て人が選ぶ
    「速くなった気がする」で終わる確認済み・計算値・推定・不明を分ける
    複数のAIが同じデータを更新して競合する更新担当を一つに絞り、別のAIが読み取り専用で確認する
    同じ失敗を繰り返し調べ直す失敗の原因と復旧手順を、確認結果とともに次回へ引き継ぐ

    ただし、現時点で「トークンを何%削減できた」「作業時間が何分短くなった」とまでは言えない。仕組みを作ったことと、効果を測ったことは別だからだ。

    まとめ

    AIエージェントの仕事を継続的に改善するには、高性能なモデルへ置き換えるだけでは足りない。実作業で得た知見を、権限・根拠・コストの扱いを決めたうえで、次回の手順へ反映する必要がある。

    この仕組みの要点は、依頼された作業を優先しながら、改善テーマと概算コストを人が選べる形で提示することだ。人が明示的に任せた場合だけAIがテーマを選ぶ。検証では確認できた事実と推測を分け、失敗の原因や復旧手順まで次回へ引き継ぐ。

    AIに「もっと考えて」と頼むのではなく、何を調べるか、どれだけのトークンや時間を使うか、どの方法で確認するかを選べるようにする。こうすることで、AIの使い方を実務の結果から継続的に改善できるようになる。

  • ガバメントクラウドのR1・R2・R3とは?Replatform・Rebuild・Repurchaseの違いと、R2を実際に設計して分かったこと

    ガバメントクラウドのR1・R2・R3とは?Replatform・Rebuild・Repurchaseの違いと、R2を実際に設計して分かったこと

    ガバメントクラウドのR1・R2・R3とは?「この構成はR2なのか」という疑問から整理する

    ガバメントクラウドへの移行を検討すると、必ず「R1」「R2」「R3」という言葉に出会います。

    デジタル庁が定義している移行パターンの略号で、定義そのものは数行で説明できます。しかし実際の案件でこの言葉を使おうとすると、思ったほど簡単ではありません。

    本連載のきっかけも、まさにそこでした。

    ある行政系システムのガバメントクラウド移行案件で構成検討と概算見積を進める中、CSP側から「R2基本形」としてリファレンスアーキテクチャの提示を受けました。ところが実システムの要件を当てはめていくと、次の疑問が出てきました。

    • そもそも今回の移行は、R1とR2のどちらとして整理すべきなのか
    • R2とは、どこまで満たせばR2と言えるのか

    リファレンス構成に「R2」と書いてあるからといって、それを使って組んだ構成が自動的にR2になるわけではありません。

    そこで本連載では、まずR1・R2・R3の違いを整理し、そのうえで「R2として構成するなら何が必要か」「さくらのクラウドでそれを実現できるか」を、実際の設計検討をもとに全6回で検証していきます。

    第1回となる今回は、言葉の定義を確認したうえで、実際の構成を定義に照らすと何が起きるのかを見ていきます。


    R1・R2・R3とは何か

    R1・R2・R3は、デジタル庁がガバメントクラウドへの移行パターンとして定義している3分類です。それぞれReplatform、Rebuild、Repurchaseの頭文字を取っています。

    R2:Rebuild(アプリ再構築移行)

    システム全体をクラウド前提で再設計する移行パターンです。個別にアプリケーションを開発する場合、原則としてこのR2を目指すことになります。

    ここで重要なのは、R2が「クラウド向けに作り直す」という漠然とした話ではなく、モダン化の定義として具体的な項目に分解されている点です。GCASガイドでは、R2に対して次の1〜5すべてを求めています。

    1. APIベースのシステム構成 — RESTful API等を用いた疎結合なシステム連携により、組織横断的なデータ連携を促進すること。非同期処理、API定義の公開、データ管理責任範囲の明確化、フロントエンドとバックエンドの分離などが含まれます。
    2. ステートレスなアーキテクチャ — 状態を保持しないことで、どのサーバーでも同じ結果を返し、可用性向上とコスト削減を実現すること。コンテナの最適化(ステートレス化、イミュータブル化)とオートスケールの活用も含まれます。
    3. モダンな運用 — IaCによるインフラ管理、定型作業の自動化、本番環境へのログインおよび手作業の禁止、適切なデプロイ戦略の選択、障害対応の自動化・リモート化を進めること。
    4. サービスレベルの定義・計測 — KPIとサービスレベルを定義・計測し、継続的な振り返りと改善を行うこと。
    5. マネージドサービスの活用 — 監視、ログ管理、バックアップ、セキュリティ、データベース、オブジェクトストレージ化のマネージドサービスを活用すること。

    R1:Replatform(アプリ一部変更移行)

    既存アプリケーションを大きく作り直さず、クラウドへ適応させながら移行する考え方です。

    R1に対しては、上記のうち「5. マネージドサービスの活用」を原則として求める位置付けになっています。逆に言えば、API化・ステートレス化・運用のコード化・サービスレベル計測までは必須としていません。

    ただしR1はゴールではありません。デジタル庁はReplatformをRebuildへ移行するうえでの一時的な状態と定義しており、R1で移行したシステムも将来的にはRebuildの構成へ再度移行することが求められています。

    R3:Repurchase(SaaS利用移行)

    既存システムを自分たちで再構築するのではなく、SaaS等の既製サービスへ置き換える方式です。移行対象のシステムがSaaSを利用可能な場合、Rebuildのパターンで移行した場合との総コストを比較したうえで採用可能とされています。

    3つは「成熟度の順番」ではない

    R1→R2→R3と番号が進むほど高度、という関係ではありません。

    • 既存システムを活かしながら移行する → R1
    • 独自システムとしてクラウド前提で作り直す → R2
    • SaaSで代替する → R3

    という、移行戦略の違いです。R1がR2への通過点として位置づけられているのは事実ですが、R3はR2の上位互換ではなく、そもそも自前で作らないという別の選択肢です。


    実際の構成を定義に照らすと何が起きるか

    ここからが本題です。

    今回の案件で検討している構成を、レイヤーごとに整理すると次のようになります。

    レイヤー検討中の構成
    アプリケーション基盤クラウドサービス化
    データベースVM上のPostgreSQL
    共有ファイルNFS
    バックアップオブジェクトストレージ
    監視等マネージドサービス
    構成管理Terraform等によるIaC
    外部接続GSS/LGWAN等の閉域接続

    さらにデータベースについては、更新頻度の異なるデータを分けて考え、日常的に更新される系統はPrimary/StandbyをOSSでHA制御する構成、参照中心の系統は読み取り専用インスタンスを複数配置する構成を、それぞれ自前で設計しています。

    これをモダン化の定義に照らすと、いくつか引っかかります。

    データベースがマネージドサービスではない。 「5. マネージドサービスの活用」はデータベースを明示的に含んでいます。今回はデータ容量等の条件からマネージドDBが適合せず、VM上にPostgreSQLを構築してHA化する方式を検討しています。

    共有ファイルにNFSを使っている。 デジタル庁はモダン化の定義の中で、アプリケーションサーバから使用する共有ストレージやファイルサーバについて、NFSファイルサーバをそのままクラウドサービスに置き換えると一般的に高価かつ密結合になるとし、オブジェクトストレージに置き換えてAPIベースで連携することを求めています。今回はアプリケーションのアクセス方式の都合でNFSが必要になっており、この方針とは逆を向いています。

    つまり、少なくともインフラ構成だけを見て「これはR2です」と言うことはできません。現時点ではR1(Replatform)寄りの構成と見る方が自然です。

    ただし、インフラだけでは判定できない

    一点、留保が必要です。

    R1/R2はデータベース単体ではなく、アプリケーションを含むシステム全体の移行方式で判断されます。アプリケーション開発側が、APIベース、ステートレス、コンテナ/サーバレス、CI/CDとIaC、SLO計測まで含めて全面的に再構築するのであれば、「DBにVMが残ったから即R1」とも言い切れません。

    正確に言えるのは、いま手元にある情報だけでは今回の移行をR2として整理する根拠がない、ということです。

    そして、CSPから受け取った資料が「R2基本形」と題されていたことが、この混同の一因でもありました。あれはCSPが提示したR2のリファレンス構成であって、それを使う案件がR2になるという意味ではありません。資料自身にも、特定システム用の確定構成ではなく汎用的なモデルであり、実際の要件に応じてリソース・個数・容量を選定する必要があると明記されています。


    リファレンス構成は、受け取った時点ではきれいに見える

    提示されたR2基本形は、VM中心ではなく、多数のクラウドサービスを組み合わせてシステムを構成する考え方になっていました。コンテナ実行基盤、マネージドDB、オブジェクトストレージ、CDN/WAF、ロードバランサ、共有ファイルサービス、DNS、監視、メッセージング、KMS、シークレット管理、IaC、閉域接続まで、R2の要件を満たすための部品はひととおり揃っています。

    一覧として見ると、非常にきれいに見えます。

    しかし実際の要件を当てはめていくと、そのままでは成立しない箇所が複数出てきました。


    実際に設計して見えた論点

    R2をWebで調べると、「コンテナを使う」「マネージドDBを使う」「オブジェクトストレージを使う」「IaCを使う」といった説明が並びます。いずれも間違いではありませんが、実際の設計ではそれだけでは足りませんでした。

    1. マネージドDBがそのまま使えないケースがある

    CSPが用意するリファレンス構成には、当然のようにマネージドDBが含まれています。しかし実システムでは、必要なDBエンジン、データ容量、性能、バックアップ、冗長化といった条件によって、マネージドDBが適合しないケースが出てきます。

    今回もこれが発生しました。ここが、移行方式の整理に迷った最初のきっかけでもあります。

    2. 「DBを2台置く」だけではHAにならない

    マネージドDBが使えないとなると、冗長化を自分で設計することになります。

    必要になるのは、Primary/Standbyの配置だけではありません。レプリケーション方式、障害検知、StandbyのPrimary昇格、Split Brainの防止、アプリケーションから見た接続先の扱い、DB Proxy、クォーラムまで含めて考える必要があります。

    「DBを2台作りました」では、高可用性設計は完成しません。サービスの配置ではなく、障害時にシステムがどう動くかまで設計対象になります。

    3. データの性質によって冗長化方式を変える必要がある

    データをすべて同じDBとして一律に扱うのではなく、日常的に更新されるデータと、過去データとして参照されるがほぼ更新されないデータに分けて考えました。

    更新されるデータにはリアルタイムの冗長化が必要です。一方で、ほとんど更新されない巨大なデータまで同じレプリケーション構成に載せると、ストレージ・バックアップ・運用のコストが大きく膨らみます。

    そのため、更新頻度や利用方法に応じて、Active系とArchive系で異なるHA・バックアップ方式を採る構成を検討しました。

    4. ストレージは「どうアクセスされるか」で選ぶことになる

    前述のとおり、モダン化の定義は共有ストレージのオブジェクトストレージ化を求めています。それでもアプリケーションのアクセス方式によっては、共有ファイルシステムが必要になります。

    今回も、DB、共有ファイル、バックアップでストレージサービスを分けて考えることになりました。ここは定義と実装が正面からぶつかる箇所で、R2として整理しづらい理由の一つでもあります。

    5. マルチゾーンとマルチリージョンを区別する必要がある

    リファレンス構成には複数ゾーンが使われています。しかし設計を進めると、マルチゾーンで十分なのか、マルチリージョンまで必要なのかを明確に分けて判断する必要が出てきます。

    マルチゾーンはゾーン障害への対策、マルチリージョンはさらに広域な障害への対策です。ガバメントクラウドだから自動的にすべてマルチリージョンにする、という話ではありません。RTO・RPO、コスト、システムの重要度から決めることになります。

    6. ネットワークがアーキテクチャを決める

    アプリケーションやDBと同じくらい大きな論点になったのがネットワークでした。

    行政システムでは、インターネットだけでなく、政府系の閉域網やLGWANからアクセスするケースがあります。これらを同一のクラウド上のシステムへどう収容するかを考えることになります。

    さらに、CSP側に目的の閉域接続サービスが存在するかどうかで、構成そのものが変わります。今回も、サービス提供状況を確認したことで、理想の構成と実際に構築可能な構成の間に差があることが分かりました。


    「R2を選びます」から本当の設計が始まる

    R1・R2・R3の定義だけなら、数行で終わります。

    しかし実際の移行では、定義を読んだうえで自分の構成を当てはめた瞬間に、「これはどちらなのか」「どこまで満たせばR2なのか」という問いが立ち上がります。

    そして構成を具体化していくと、次の問題が順に出てきます。

    • リファレンス構成がそのまま使えない
    • マネージドサービスに収まらない要件がある
    • DBのHAを自分で設計する必要がある
    • データ特性によって冗長化方式を変える必要がある
    • ストレージも用途によって使い分ける必要がある
    • マルチゾーン/マルチリージョンを選択する必要がある
    • 閉域接続サービスの有無が全体構成へ影響する

    では、これらを踏まえたうえで、R2として成立させるにはどのようなコンポーネントが必要になるのか。

    次回は、実際の検討内容を一般化しながら、「R2要件を満たすアーキテクチャは何か」を構成図レベルで整理します。


    本連載の構成(全6回)

    1. ガバメントクラウドのR1・R2・R3とは?(本記事)
    2. R2要件を満たすアーキテクチャは何か?
    3. さくらのクラウドでR2構成を実現できるか?
    4. R2構成でネックになるサービスと代替案
    5. GSS接続のネットワーク設計
    6. LGWAN/LGCS接続のネットワーク設計

    なお、さくらのクラウドは2026年3月27日に全技術要件305項目への適合が確認され、ガバメントクラウドの対象クラウドサービスとして正式に採択されています。国産クラウドとしては唯一の採択で、AWS、Google Cloud、Microsoft Azure、OCIに続く5番目です。選択肢として現実的になったからこそ、「実際に組めるのか」を確認する必要があります。


    よくある質問

    Q. R1とR2の一番大きな違いは何ですか。

    A. R2(Rebuild)はモダン化の定義1〜5、すなわちAPIベースのシステム構成、ステートレスなアーキテクチャ、モダンな運用、サービスレベルの定義・計測、マネージドサービスの活用のすべてを求めます。これに対しR1(Replatform)は、このうち「5. マネージドサービスの活用」を原則として求める位置付けです。

    Q. VM上にデータベースを構築したら、それだけでR2ではなくなりますか。

    A. R1/R2はデータベース単体ではなく、アプリケーションを含むシステム全体の移行方式で判断されます。ただし「5. マネージドサービスの活用」はデータベースを明示的に含んでいるため、VM上にDBを構築する場合はその判断根拠を説明できるようにしておく必要があります。

    Q. 共有ファイルにNFSを使うことは問題になりますか。

    A. デジタル庁はモダン化の定義の中で、共有ストレージやファイルサーバをNFSのままクラウドへ置き換えると高価かつ密結合になるとし、オブジェクトストレージへの置き換えとAPIベースの連携を求めています。NFSを採用する場合、モダン化の方向性とは異なる選択になります。

    Q. R1のまま運用を続けることはできますか。

    A. デジタル庁はReplatformをRebuildへ移行するうえでの一時的な状態と定義しており、R1で移行したシステムも将来的にはRebuildの構成へ再度移行することが求められています。R1は終着点ではなく通過点という位置づけです。

    Q. CSPから提示された「R2基本形」を使えば、その構成はR2になりますか。

    A. なりません。リファレンス構成は特定システム用の確定構成ではなく汎用的なモデルであり、実際の要件に応じてリソースや容量を選定する必要があると資料自身に明記されています。実要件を当てはめた結果としてマネージドサービスから外れる箇所が出れば、その構成はR2の定義を満たさない可能性があります。


    参考

    • デジタル庁 GCASガイド「ガバメントクラウド概要解説」 https://guide.gcas.cloud.go.jp/general/overview-explanation/
    • デジタル庁 GCASガイド「ガバメントクラウドにおけるモダン化の定義」 https://guide.gcas.cloud.go.jp/modernization-guide/modernization-definition
    • デジタル庁 note「ガバメントクラウドにおけるモダン化の意味と定義」 https://digital-gov.note.jp/n/n3640f6b7a009
    • デジタル庁「ガバメントクラウド」 https://www.digital.go.jp/policies/gov_cloud

    ※本記事は、公開情報および実際のアーキテクチャ検討の経験をもとに、実務上の論点を整理したものです。ガバメントクラウドに関する個別要件や対応可否については、案件ごとに確認が必要です。

  • 「ルーティング」は一枚岩ではない — Cloudflare × さくらのクラウドで責務を分ける

    「ルーティング」は一枚岩ではない — Cloudflare × さくらのクラウドで責務を分ける

    はじめに

    作業チケットには「ルーティングを直す」と書いていた。

    でも手を動かしはじめてすぐ気づいた。自分がいま触っているのは、少なくとも 8 種類くらいの違う「ルーティング」だった。Cloudflare、さくらのクラウドの VM 上の nginx、WebAccel、オブジェクトストレージ、AppRun、SPA のルーター、backend API、そしてアプリ内の認可。全部が「どこへ流すか」を判断していて、しかも判断材料がそれぞれ違う。

    同じ言葉で呼んでいたせいで、「これは LB でやるべきか、アプリでやるべきか」という議論が毎回ふりだしに戻っていた。

    この記事では、ルーティングを一枚岩で考えるのをやめて、レイヤーごとに責務を切ったら設計も実装も検証も一気に楽になった、という話を書く。コードの詳細より、責務分担と検証観点が中心。

    想定読者はこのあたり。

    • Cloudflare を前段に置いてアプリを公開している人
    • さくらのクラウド / WebAccel / AppRun / オブジェクトストレージを使っている人
    • 既存アプリを段階的にモダン化している人
    • SPA と backend API のルーティングでハマったことがある人
    • 「これは LB でやるべき?アプリでやるべき?」と迷ったことがある人

    背景

    さくらのクラウド上で動いている既存の Web アプリを、Cloudflare 経由で公開していた。構成は伏せずに書きたいので、ホスト名とパスは実在のものから置き換えている。

    既存の経路はシンプルで、フロントとバックエンドが別ホストに分かれている。

    app.example.jp
      -> Sakura WebAccel
      -> Sakura Object Storage
      -> static frontend
    
    api.example.jp
      -> Sakura WebAccel
      -> Sakura AppRun
      -> PHP backend
      -> 外部 LLM API

    ここに、一部のパスだけ新しい経路を差し込むことになった。VM 上に nginx の edge router を立てて、/v2/ 配下だけをローカルのリリースに向け、それ以外は既存の WebAccel にそのまま流す。

    User
      ↓
    Cloudflare
      ↓
    Sakura Cloud VM / nginx edge router
      ├─ /v2/       -> local sealed release
      └─ otherwise  -> existing Sakura WebAccel
                         ↓
                       Object Storage / AppRun
                         ↓
                       Application
    Cloudflare からさくらのクラウド VM の nginx エッジルーターを経て、新経路と既存の WebAccel / オブジェクトストレージ / AppRun に分岐する公開経路の全体構成図

    アプリ本体のロジックはほとんど触っていない。やったのは公開経路、TLS、リダイレクト、パスルーティング、リリースの切り替え、ロールバック。いわば「インフラだけのモダン化」に近い作業だった。

    にもかかわらず、ハマったポイントの半分はアプリ側との境界線にあった。

    「ルーティング」には少なくとも 8 種類ある

    整理してみると、この構成の中で「ルーティング」と呼んでいたものはこれだけあった。

    • DNS routing
    • edge routing
    • load balancer / reverse proxy routing
    • static asset routing
    • SPA routing
    • API routing
    • authorization routing
    • provider routing

    全部「どこへ流すか」を決めている。だから同じ言葉で呼びたくなる。でも判断材料がまるで違う。

    特に混ざりやすいのは、次の 3 つだ。

    1. URL / Host / Path だけで判断できるネットワークルーティング

    リクエストラインとヘッダを見れば答えが出る。/v2/ で始まるかどうか。ホストが canonical かどうか。スキームが https かどうか。状態を持たない。

    2. session / tenant / permission を見ないと判断できない業務ルーティング

    「このユーザーはこの機能を使ってよいか」。同じ URL でも、誰が叩いたかで答えが変わる。DB を引かないと決まらない。

    3. provider / billing / audit を伴う外部サービスルーティング

    「このリクエストをどの外部プロバイダに投げるか」「クォータは残っているか」「証跡をどう残すか」。お金と監査がついてくる。

    この 3 つを同じ場所で解こうとすると、必ずどこかが破綻する。逆に言うと、判断材料を見れば置くべき層は自動的に決まる。これが今回いちばん大きかった学びだった。

    LB / Cloudflare / nginx 側でやるべきこと

    判断材料が URL / Host / Path / スキームだけで完結するものは、全部前段に寄せる。

    • ホストの正規化
    • HTTP -> HTTPS リダイレクト
    • canonical host へのリダイレクト
    • /v2/ のようなパスベースルーティング
    • 非 /v2 パスを既存 upstream へプロキシ
    • TLS 終端
    • WAF / Access challenge
    • origin への直アクセス禁止
    • health check の入口整理
    • static assets と API path の入口分離

    パスの割り振りとしてはこういう形になる。

    /v2/        -> new local release
    /api/*      -> backend
    /assets/*   -> static
    otherwise   -> existing frontend / SPA fallback

    ここに書かれている判断は、どれもリクエストを見るだけで決まる。DB もセッションも要らない。だから前段でやってよいし、前段でやったほうが速いし、設定ファイルを読めば挙動が全部わかる。

    アプリ側に残すべきこと

    一方、ここから先は絶対に前段に持ってこない。

    • ログイン済みか
    • session が有効か
    • tenant はどれか
    • user / role / permission は何か
    • この agent / route を使ってよいか
    • 外部 API へ送信してよいか
    • provider をどれにするか
    • quota / billing / retry をどう扱うか
    • audit evidence をどう残すか
    • public response に何を返すか

    実際のエンドポイントで書くと、こういう連なりになる。

    /api/example/invoke
      -> session check
      -> route allowlist
      -> confirmation check
      -> provider selection
      -> quota / billing
      -> external API call
      -> audit
      -> public-safe response

    このパスをどこに流すかは nginx の仕事だ。でもこのパスを誰に許可するかはアプリの仕事。ここが今回の記事の主張をいちばん短く言い切った形だと思う。

    ハマったところ

    1. /api/* を SPA fallback が飲み込む

    SPA では、存在しないパスを index.html に返す設定をよく書く。ブラウザ側のルーターに解釈させたいからだ。

    ところがこの fallback を素朴に書くと、/api/* や /health や /ops/* まで飲み込んでしまう。すると何が起きるか。API が壊れたときに HTML が返ってくる。

    curl でステータスコードだけ見ていると 200 なので気づかない。JSON をパースしようとして初めて落ちる。しかも落ちる場所がフロント側なので、原因がバックエンドにあることに気づくまで一往復余計にかかる。

    教訓:

    • SPA fallback の前に backend / API path を除外する
    • /api/* は backend に流す
    • 未知の API path は HTML ではなく JSON error を返す
    • browser path と API path を同じルールで扱わない

    ブラウザ向けのパスと機械向けのパスは、そもそも失敗の返し方が違う。混ぜてはいけない。

    SPA fallback が /api/* を飲み込んで 200 と HTML を返す経路と、backend を先に評価して 404 と JSON を返す経路の比較図

    2. Cloudflare Access の 302 を見て安心してしまう

    未認証でアクセスしたら Cloudflare Access の challenge が返ってきた。302 が出た。よし、守れている。

    ……と思ったが、これが証明しているのは「Cloudflare を通ったリクエストのうち未認証のものが止まっている」ことだけだ。origin が直接叩けないことの証明にはまったくなっていない。

    Cloudflare Access の 302 は「未認証が止まった」証拠であって、「origin が守られている」証拠ではない。

    実際に確認すべきなのはこのあたり。

    • 未認証リクエストが Access に止められること
    • 認証済みリクエストでも意図しない origin に到達しないこと
    • DNS が意図した入口を指していること
    • origin firewall / さくらのパケットフィルタが直アクセスを許していないこと
    • Tunnel / proxy / upstream の向き先が正しいこと

    前段のチャレンジ画面は「入口が動いている」ことしか教えてくれない。裏口が空いているかどうかは、裏口側から確かめるしかない。

    Cloudflare を経由する正面の経路と、オリジンの IP を直接叩いて Access を通らない経路が、同じオリジンに着地することを示す図

    3. /health が内部情報をしゃべりすぎる

    LB のヘルスチェックや監視のために /health を生やすのは便利だ。便利なので、デバッグ中にどんどん情報を足したくなる。

    気づいたら、レスポンスに provider の endpoint、モデル名、quota の設定値、内部モード、feature flag が並んでいた。認証なしで見えるところに。

    便利なエンドポイントほど、内部構成をしゃべりすぎる。

    教訓:

    • public health は最小限にする
    • status: ok と、公開してよい依存先のステータスくらいに絞る
    • 詳細診断は認証済みの admin / ops / 内部ログに寄せる
    • provider endpoint やモデル名は public health に出さない

    デバッグ用に足した情報は、デバッグが終わったら消す。あるいは最初から認証済みの別エンドポイントに置く。

    4. path routing と認可 routing を同じ場所で解こうとする

    /v2/ をどこに流すかは nginx で判断できる。設定ファイルに 3 行書けば終わる。

    でも「このユーザーがこの機能を使ってよいか」は nginx では判断できない。判断材料がリクエストの中にないからだ。session を引いて、tenant を特定して、role を見て、はじめて答えが出る。

    ここを無理に前段でやろうとすると、LB に認証情報を渡す仕組みを作ることになり、その仕組み自体が新しい攻撃面になる。

    教訓:

    • path だけで判断できるならインフラ
    • user / session / tenant が必要ならアプリ
    • provider / cost / audit が必要ならアプリ
    • ルーティングの判断材料を見れば、置くべき層が決まる

    ロードバランサーで解ける問題と、ロードバランサーで解いてはいけない問題がある。

    5. 既存経路と新経路の境界が曖昧になる

    一部のパスだけを新経路に寄せると、既存の WebAccel / AppRun / オブジェクトストレージと、新しい nginx edge が並存する期間ができる。

    この状態で「どちらが正本か」「fallback 先はどこか」「ロールバックはどこでやるか」を決めていないと、障害時に人間が迷う。片方を直したつもりで、もう片方が生きていた、みたいなことが起きる。

    教訓:

    • 新経路の責務をパス単位で明文化する
    • 既存 upstream へのプロキシは「意図してそうしている」と明示する
    • ロールバック先を先に用意する
    • release symlink / sealed release のように、いま何が active かを外から検証できる形にする

    「たぶんこっちが動いている」で運用しないこと。

    判断基準の表

    最終的に、こういう表に落ち着いた。迷ったらここに戻る。

    判断材料置くべき層
    Host / path / scheme だけCloudflare / LB / nginx
    TLS / WAF / AccessCloudflare
    origin 到達性 / firewallCloudflare / さくらのクラウド / packet filter
    static file pathObject Storage / WebAccel
    ブラウザの画面遷移SPA router
    API contractBackend
    session / tenant / permissionApplication
    provider / quota / billing / auditApplication / provider layer

    左の列を見れば右の列が決まる。逆に、右をどこにするか迷っているときは、左が曖昧になっている。

    判断材料ごとに、ホスト・パスだけで決まる層とセッションやテナントが必要な層に分かれることを示す対応図

    検証は 3 つに分ける

    もうひとつ、作業中に効いた分け方がある。「動作確認」をひとまとめにしないこと。

    「通った」「守れている」「業務的に正しい」は別々に検証する。

    • 通った — リクエストが意図した経路を通り、意図したステータスとコンテンツタイプが返ってくる。curl とステータスコードの世界。
    • 守れている — 未認証が止まる。origin に直接届かない。public に出してはいけない情報が出ていない。回避経路がない、という否定形の確認。
    • 業務的に正しい — 正しい tenant のデータが返る。権限のないユーザーが弾かれる。課金と監査ログが期待どおり残る。

    この 3 つは通る道が違うので、ひとつ確認したからといって他が保証されることはない。1 番目だけ見て終わりにしたときに、2 番目の抜けに気づかなかったのが今回の反省点だった。

    チェックリスト

    同じ構成を触る人向けに、最後にチェックリストを置いておく。

    • /api/* は SPA fallback より前に backend へ流しているか
    • 未知の API path は HTML ではなく JSON error を返すか
    • public health に内部 endpoint / モデル名 / secret に近い設定を出していないか
    • Cloudflare Access の未認証 challenge だけで origin protection 完了扱いにしていないか
    • 認証済みパスでも意図しない origin に到達しないことを確認したか
    • origin firewall / パケットフィルタは直アクセスを塞いでいるか
    • path routing と session / tenant / permission 判定を混ぜていないか
    • provider / billing / audit の判断を LB に押し込んでいないか
    • 既存経路と新経路の責務境界をドキュメントに書いているか
    • ロールバック先と、いま何が active かの検証方法があるか

    おわりに

    「ルーティングを直す」という一文には、ネットワークの話と業務の話と外部サービスの話が全部詰まっていた。詰まったまま考えていたから、議論も検証も毎回とっちらかっていた。

    レイヤーごとに分解して、判断材料で置き場所を決める。それだけで、設定ファイルを読めばわかることと、コードを読まないとわからないことが、きれいに分かれた。

    ルーティングは一枚岩ではない。分解して、それぞれの責務を決める。それだけの話だけれど、決めるまでは毎回ふりだしに戻っていた。

    よくある質問

    Q1. SPA を配信すると /api/* が HTML を返してしまうのはなぜか

    SPA の deep link 対応として、存在しないパスを index.html に返す fallback を設定しているからだ。この設定はブラウザ向けのパスには正しく働くが、除外指定をしないと /api/* や /health のような機械向けのパスまで飲み込んでしまう。結果として、API が 404 を返すべき場面で 200 と HTML が返り、フロント側の JSON パースエラーとして表面化する。fallback を書く前に backend / API のパスを先にマッチさせ、未知の API パスは JSON のエラーとして返すのが正解になる。

    Q2. Cloudflare Access を有効にすれば origin は守られたことになるのか

    ならない。未認証アクセスで challenge や 302 が返ることが証明しているのは、Cloudflare を経由したリクエストのうち未認証のものが止まっている、という事実だけだ。origin の IP が直接叩ける状態であれば、その経路は Access をまったく通らない。DNS の向き先、origin firewall やさくらのクラウドのパケットフィルタ、Tunnel / upstream の設定を、前段とは別に確認する必要がある。

    Q3. /health エンドポイントには何を書いてよいのか

    公開する health には status: ok と、外部に見せて問題のない依存先のステータス程度に絞るのが安全だ。provider の endpoint、モデル名、quota の設定値、内部モード、feature flag といった情報は、監視には不要である一方で、攻撃者にとっては構成の地図になる。詳細な診断情報が必要なら、認証済みの admin / ops エンドポイントか内部ログに寄せる。デバッグ中に足したフィールドが公開のまま残っていないかは、リリース前に一度見直しておきたい。

    Q4. 認可の判断を Cloudflare や nginx に寄せてはいけないのか

    判断材料で決まる。ホスト、パス、スキームだけで答えが出るなら前段でよいし、そのほうが速く、設定を読めば挙動もわかる。しかし「このユーザーがこの機能を使ってよいか」は session を引き、tenant を特定し、role を見なければ決まらない。この判断を無理に前段へ持ち込むと、LB に認証情報を渡す仕組みを別途作ることになり、その仕組み自体が新しい攻撃面になる。

    Q5. さくらのクラウドの WebAccel と自前の nginx は併用してよいのか

    併用自体は問題ない。実際、一部のパスだけを新しい経路に寄せ、それ以外は既存の WebAccel へプロキシする構成は現実的な移行手段になる。ただし、パス単位で「どちらが正本か」を明文化しておかないと、障害時に片方だけ直して終わったつもりになる事故が起きる。既存 upstream へのプロキシは、暗黙の残骸ではなく意図した設計としてドキュメントに残しておくとよい。

    Q6. 段階的な経路移行では、何を決めてから切り替えるべきか

    最低限、パスごとの責務境界、fallback 先、ロールバック手順、そして「いま何が active か」の検証方法の 4 つだ。とくに最後が抜けやすい。release symlink や sealed release のように、外から一発で現行リリースを確認できる形にしておくと、切り戻しの判断が速くなる。逆にこれがないと、「たぶんこっちが動いている」という前提で復旧作業を始めることになる。

  • さくらインターネット不正アクセス第二報を読む — クラウド利用者が今確認すべき認証・パスワード運用

    さくらインターネット不正アクセス第二報を読む — クラウド利用者が今確認すべき認証・パスワード運用

    ※本記事は2026年8月29日時点の情報です。さくらインターネットが公開しているニュースリリース、サポート情報および公式マニュアルをもとに執筆しています。本件は現在も調査が継続されているため、最新状況については必ず公式情報をご確認ください。

    • この記事で分かること
      • 2026年8月に公表された、さくらインターネットへの不正アクセスで何が確認されているのか
      • 「1,360,563アカウント」という数字をどう理解すべきか
      • 「さくらのクラウド」のサーバー自体にも影響があったのか
      • ハッシュ化されたパスワードにアクセスされた可能性があるとはどういうことか
      • クラウドやWebアプリを運用する側が、今確認しておきたい認証・パスワード・シークレット管理
      • 同様のインシデントに備えて、アプリケーション開発・インフラ運用で何を見直すべきか

    まず結論:「さくらのクラウドが侵害された」という発表ではない

    今回のニュースを見て、

    「さくらインターネットが不正アクセスを受けたということは、さくらのクラウド上のサーバーも侵害されたのではないか」

    と考える方もいるかもしれません。

    しかし、2026年8月19日に公表された第二報では、不正アクセスの可能性が確認された「販売管理システム」は、契約情報などを管理するシステムであり、「さくらのクラウド」をはじめとした各サービスの提供環境とは別のシステムであることが明記されています。

    また、8月17日の第一報では、その時点で「さくらのVPS」「さくらのクラウド」「さくらの専用サーバ PHY」「高火力 PHY」への影響は確認されていないと公表されていました。

    したがって、現時点の公開情報から、

    さくらのクラウド上で稼働している仮想サーバーそのものが今回の不正アクセスによって侵害された

    と判断することはできません。

    一方で、今回の調査では会員情報や認証情報に関する影響の可能性が判明しています。

    そのためクラウド利用者としては、「サーバーが侵入されたかどうか」だけを見るのではなく、アカウント・パスワード・管理者権限などの認証まわりを改めて確認する機会として捉えることが重要です。

    何が起きたのか:第一報から第二報まで

    今回の事象は、2026年8月9日にさくらインターネットが管理するサーバー環境で異常を検知したことから調査が始まりました。

    8月17日の第一報では、第三者が同社の管理環境を経由して「さくらのレンタルサーバ」の一部顧客環境へ不正アクセスしていたことが公表されました。不正ログインの対象は583アカウントで、攻撃者が顧客アカウントからアクセス可能な領域へ到達し、マルウェアが設置されていたことなどが確認されています。

    その後、認証情報の無効化やアクセス遮断などを実施したうえで調査を進めた結果、8月19日の第二報では、新たに契約情報等を管理する販売管理システムへの不正アクセスの可能性が確認されました。

    この販売管理システムへのアクセスは、レンタルサーバーへの不正アクセスを検知した8月9日より前に発生した事象とされており、両者の関連性を含めて現在も調査が続けられています。

    整理すると、現時点では次のようになります。

    公表主な内容
    8月17日 第一報さくらのレンタルサーバの一部顧客環境への不正アクセスを確認
    第一報不正ログイン対象は583アカウント
    第一報一部環境でマルウェアを確認
    8月19日 第二報販売管理システムへの不正アクセスの可能性を確認
    第二報会員情報にも影響した可能性
    第二報対象となる可能性のある会員情報は1,360,563アカウント
    第二報一部顧客のハッシュ化されたパスワード情報にもアクセスされた可能性
    8月26日問い合わせ窓口などを更新。VPSの一部対象者には管理者初期パスワード変更を案内

    「1,360,563アカウント流出」とは限らない

    今回特に注意したいのが、「1,360,563アカウント」という数字です。

    第二報では、

    対象となる可能性のある会員情報総数が1,360,563アカウント

    と公表されています。

    しかし、これは「1,360,563件の個人情報が漏えいした」という意味ではありません。

    公式FAQでも、1,360,563アカウントは対象となる可能性のある会員情報の総数であり、現時点で全件が漏えいした事実は確認されていないと説明されています。また、個別の利用者が対象に含まれるかどうかについても、現時点では確定的に案内できない段階とされています。

    第二報では、現時点でデータの外部持ち出しは確認されていないとも説明されています。

    したがって、

    136万アカウントが流出した

    ではなく、

    最大1,360,563アカウントの会員情報が影響を受けた可能性があり、実際に閲覧・取得された範囲は調査中

    と理解するのが正確です。

    ハッシュ化されたパスワードへのアクセスとは

    今回、エンジニアとして特に気になるのが、販売管理システムに保存されていた一部顧客の「ハッシュ化されたパスワード情報」にアクセスされた可能性です。

    通常、Webサービスではパスワードそのものを平文でデータベースに保存するのではなく、パスワードから生成したハッシュ値を保存します。

    イメージとしては次のような形です。

    ユーザーが入力したパスワード
            ↓
        ハッシュ関数
            ↓
        ハッシュ値
            ↓
    データベースへ保存

    ログイン時には、入力されたパスワードを同じ方法でハッシュ化し、保存されている値と比較します。

    そのため、データベース上のハッシュ値を見ただけで、そのまま元のパスワードが表示されるわけではありません。

    ただし、

    「ハッシュ化されているから、取得されても何もする必要がない」

    という考え方も危険です。

    パスワード自体が短い、単純、推測しやすいなどの条件によっては、攻撃者が候補となるパスワードを大量に試し、そのハッシュ値と照合することで元のパスワードを推測する攻撃が考えられます。

    また、同じパスワードを別サービスでも使い回していた場合、一つの認証情報が判明することで別サービスへの不正ログインにつながる可能性があります。

    さくらインターネット自身も、複数サービスで同じ認証情報を使い回した場合、一つのサービスから情報が流出すると他サービスにも不正アクセスされる可能性があるとして、認証情報の使い回しを避けるよう案内しています。

    まず確認したいこと1:パスワードを使い回していないか

    今回のような事象が起きた際、利用者側で最初に確認しやすいのがパスワードです。

    例えば、次のような状態になっていないでしょうか。

    さくらインターネット
        password-A
    
    GitHub
        password-A
    
    Google Workspace
        password-A
    
    AWS
        password-A

    この状態では、一つのサービスで認証情報が漏えいすると、他サービスにも同じID・パスワードでログインを試す「パスワードリスト攻撃」につながる可能性があります。

    理想的には、

    さくらインターネット
        password-A
    
    GitHub
        password-B
    
    Google Workspace
        password-C
    
    AWS
        password-D

    のように、サービスごとに異なるパスワードを設定します。

    人間がすべてを暗記するのは現実的ではないため、業務ではパスワードマネージャーなどを利用して、長くランダムなパスワードをサービスごとに生成・管理する方法が現実的です。

    なお、今回のFAQでは、自分が影響対象に含まれているか現時点では確認できない場合でも、不安がある場合には予防的措置としてパスワード変更を推奨しています。

    まず確認したいこと2:2要素認証を有効にする

    パスワードだけではなく、2要素認証も重要です。

    通常のログインが、

    ID
    +
    パスワード

    だとすると、2要素認証では、

    ID
    +
    パスワード
    +
    ワンタイムパスワード
    または
    セキュリティキー

    など、別の認証要素を追加します。

    これにより、仮にパスワードが第三者に知られたとしても、それだけではログインできない構成にできます。

    さくらインターネットでは、会員メニューについて2025年12月3日から2要素認証が必須化されています。また「さくらのクラウド」のコントロールパネルでも、ワンタイムパスワードやFIDO2対応セキュリティキーを利用した2要素認証の仕組みが用意されています。

    特に、

    • クラウド管理画面
    • GitHubなどのソースコード管理
    • Google Workspace / Microsoft 365
    • CI/CDサービス
    • ドメイン・DNS管理
    • VPN
    • 社内管理システム

    といった、侵害された場合の影響が大きいアカウントでは2要素認証を前提にするのが安全です。

    まず確認したいこと3:「人間のパスワード」だけを見ない

    アプリケーションを運用している場合、確認対象は人間がログインするときのパスワードだけではありません。

    システムにはさまざまな認証情報があります。

    人間が利用する認証情報
    ├─ クラウド管理画面のパスワード
    ├─ GitHubアカウント
    ├─ VPNアカウント
    └─ WordPress管理者
    
    アプリケーションが利用する認証情報
    ├─ DB_PASSWORD
    ├─ API_KEY
    ├─ ACCESS_TOKEN
    ├─ SSH秘密鍵
    ├─ CI/CD用トークン
    └─ 外部サービスの認証情報

    例えばWebアプリケーションでは、次のような値を扱うことがあります。

    DATABASE_URL=...
    DB_PASSWORD=...
    API_KEY=...
    SECRET_KEY=...

    これらがGitリポジトリに直接コミットされていたり、複数環境で同じ値を使っていたりすると、一つの環境への侵入が別環境へ波及する可能性があります。

    そのためインシデント発生時には、

    「ユーザーパスワードを変更したから終了」ではなく、どの認証情報をどこで利用しているかを棚卸しする

    ことが重要です。

    VPS利用者は「初期パスワード」の扱いにも注意

    今回のインシデントを受けて、2026年8月26日には「さくらのVPS」の一部利用者に対して、管理者パスワード変更の案内も公開されています。

    対象となるのは、販売管理システム内に管理者(root / Administrator)の初期パスワードが保存されていたことが確認されたVPS契約者のうち、契約時に受け取った初期パスワードを変更せず利用している一部ユーザーです。

    さくらインターネットは対象者へ個別にメールを送付しており、パスワード変更に関するメールを受け取っていない利用者は対象外としています。また、2022年9月1日以降に契約したVPSなども対象外とされています。

    ここから一般化できる教訓は、

    初期パスワードを恒久的に使わない

    ということです。

    例えばサーバー構築時には、

    サーバー作成
       ↓
    初期パスワード発行
       ↓
    初回ログイン
       ↓
    パスワード変更
       ↓
    可能ならSSH鍵認証等へ移行

    のように、初期認証情報を一時的なものとして扱います。

    これは、さくらのVPSに限らず、クラウド・ネットワーク機器・SaaS・データベースなどでも同様です。

    アプリ・クラウド運用者向け:今確認したいチェックリスト

    今回の事象をきっかけに、クラウド環境を利用している場合は次の項目を確認しておくとよいでしょう。

    アカウント・認証

    • 他サービスと同じパスワードを使い回していない
    • 管理者アカウントに2要素認証を設定している
    • 退職者・異動者・不要なユーザーが残っていない
    • 共用アカウントをできるだけ使用していない
    • 初期パスワードをそのまま使用していない
    • 不要になったAPIキーやアクセストークンを削除している

    権限

    • 全ユーザーに管理者権限を与えていない
    • 開発者に本番環境の不要な権限を与えていない
    • サービスアカウントにも必要最小限の権限を設定している
    • 本番・ステージング・開発環境で認証情報を分離している

    サーバー・ネットワーク

    • SSHやRDPをインターネット全体へ公開していない
    • 不要なポートを開放していない
    • Firewallの設定を定期的に確認している
    • OS・ミドルウェア・CMSを更新している
    • 管理画面にアクセス制限を設定できないか確認している

    アプリケーション

    • APIキーをソースコードへ直接記述していない
    • .env ファイルをGitへコミットしていない
    • 本番DBの認証情報を開発環境で使い回していない
    • ログへパスワードやアクセストークンを出力していない
    • シークレットを定期的に変更できる構成になっている

    ログ・監視

    • 管理者ログインを追跡できる
    • 重要な設定変更の履歴を確認できる
    • 不審なアクセスを調査できるだけのログを保持している
    • インシデント発生時に誰が調査するか決まっている

    すべてを一度に完璧にする必要はありません。

    まずは、

    ①管理者アカウント → ②外部公開サーバー → ③本番環境の認証情報

    の順に確認すると、優先順位を付けやすくなります。

    特に危険なのは「一つの認証情報から横展開できる構成」

    システム運用で避けたいのが、一つの認証情報を取得するだけで複数のシステムへアクセスできてしまう構成です。

    例えば、

    1つの共通パスワード
            ↓
     ┌──────┼──────┐
     ↓      ↓      ↓
    GitHub  VPN    Cloud
                      ↓
                     DB

    という構成では、一つの認証情報の侵害が大きな影響につながります。

    一方、

    GitHub
      └─ 個別アカウント + 2要素認証
    
    Cloud
      └─ 個別ユーザー + 最小権限 + 2要素認証
    
    Server
      └─ SSH鍵
    
    DB
      └─ アプリ専用ユーザー
    
    CI/CD
      └─ 専用トークン

    のように認証経路を分離しておけば、一つの認証情報が漏えいした場合でも影響範囲を小さくできます。

    これは「パスワードを強くする」こととは別の重要な考え方です。

    認証情報そのものが漏れる可能性をゼロにするのではなく、漏れた場合でも被害が横に広がりにくい設計にする

    ことがポイントです。

    クラウド側だけではなく、アプリケーション側の対策も必要

    クラウドサービスを利用すると、

    「インフラのセキュリティはクラウド事業者が対策してくれる」

    と考えてしまいがちです。

    しかし実際には、

    クラウド事業者側
    ├─ データセンター
    ├─ 物理サーバー
    ├─ クラウド基盤
    └─ サービス提供基盤
    
    利用者側
    ├─ OS設定
    ├─ Firewall
    ├─ ユーザー管理
    ├─ Webアプリ
    ├─ WordPress等のCMS
    ├─ APIキー
    ├─ DB
    └─ アプリケーションの認証

    のように、利用者側で管理しなければならない範囲も多く存在します。

    例えばクラウド基盤自体に問題がなくても、

    • WordPressのパスワードが漏れる
    • Webアプリに脆弱性がある
    • SSHを全世界へ公開している
    • GitHubからAPIキーが流出する

    といった理由でシステムが侵害される可能性はあります。

    そのため、

    「利用しているクラウドサービスが安全か」だけではなく、「その上に自分たちがどうシステムを構築しているか」まで含めて考える

    必要があります。

    インシデント発生時にやってはいけない3つの判断

    1. 「ハッシュ化されているから何もしなくていい」

    ハッシュ化はパスワード保護に重要な仕組みですが、認証情報へのアクセス可能性が判明した場合に、利用者側の対応が一切不要になるという意味ではありません。

    パスワードの使い回しがある場合などは特に、変更を検討する必要があります。

    2. 「136万件の個人情報が流出した」と断定する

    現時点で公式に発表されているのは、1,360,563アカウントが対象となる可能性のある会員情報総数ということです。

    全件の情報流出が確認されたわけではありません。

    3. 「さくらのクラウドそのものが危険」と判断する

    今回不正アクセスの可能性が確認された販売管理システムと、「さくらのクラウド」などのサービス提供環境は別システムであると公式に説明されています。

    インシデント発生時には、事業者名だけで判断せず、

    どのシステムに侵入されたのか、どの情報に影響した可能性があるのか

    を分けて読むことが重要です。

    今回の事例から得られる3つの教訓

    今回の事象から、クラウド・Webアプリケーションの運用者が改めて確認したいポイントは、大きく3つあります。

    1. 認証情報は「漏れない前提」ではなく「漏れた場合」まで考える

    パスワードを強くするだけではなく、

    • 使い回さない
    • 2要素認証を利用する
    • 最小権限にする
    • 認証情報を用途ごとに分離する

    ことで、一つの認証情報が侵害された場合の影響を抑えます。

    2. 初期パスワードや古い認証情報を残さない

    今回、さくらのVPSでは一部の古い契約について、初期管理者パスワードを変更していない対象者へ変更が案内されました。

    サーバー構築後は、

    • 初期パスワード
    • 一時APIキー
    • 検証用ユーザー
    • 不要になったアクセストークン

    などを残さない運用が重要です。

    3. 認証情報の棚卸しができる状態にしておく

    インシデントが起きた際に、

    どのパスワードを変更すればよいのか分からない

    このAPIキーがどのシステムで使われているのか分からない

    という状態では、迅速な対応が難しくなります。

    最低限、

    認証情報
    ↓
    利用システム
    ↓
    利用環境
    ↓
    所有者
    ↓
    最終更新日

    が追える状態にしておくと、インシデント対応が大きく変わります。

    まとめ

    2026年8月に公表されたさくらインターネットへの不正アクセスでは、「さくらのレンタルサーバ」の一部顧客環境に加え、契約情報等を管理する販売管理システムにも不正アクセスの可能性が確認されています。

    対象となる可能性のある会員情報は1,360,563アカウントと公表されていますが、これは全件の情報流出が確認されたという意味ではなく、実際の影響範囲については現在も調査が続けられています。

    また、不正アクセスの可能性が確認された販売管理システムは、「さくらのクラウド」をはじめとしたサービス提供環境とは別のシステムです。

    今回の事象からクラウド利用者が学ぶべきなのは、「特定のクラウドが安全か危険か」という二択ではありません。

    重要なのは、

    • パスワードを使い回さない
    • 2要素認証を利用する
    • 初期パスワードを残さない
    • 権限を必要最小限にする
    • APIキーやトークンも含めて認証情報を管理する
    • 本番・開発・検証環境の認証情報を分離する
    • 万が一認証情報が漏れても横展開されにくい構成にする

    といった基本的な対策を継続することです。

    クラウドサービスを使うことで物理インフラの管理負担は減らせますが、その上で動かすアカウント・OS・アプリケーション・認証情報の管理までクラウド事業者に任せられるわけではありません。

    今回の発表を、普段利用しているクラウド環境やWebアプリケーションの認証設計を見直す機会にしてみてはいかがでしょうか。

    本記事執筆時点で未確定の事項

    本件は現在も調査中です。2026年8月29日時点では、少なくとも以下については今後の公式発表を確認する必要があります。

    • 販売管理システムへの具体的な侵入経路
    • 「さくらのレンタルサーバ」への不正アクセスとの関連性
    • 1,360,563アカウントのうち実際に影響を受けた範囲
    • 実際に第三者が閲覧または取得した情報・件数の確定
    • 今後策定される再発防止策

    公式発表でも、原因や影響範囲について調査を継続し、新たに公表すべき事実が判明した場合には公表するとされています。

    参考リンク

    本記事は、以下のさくらインターネット公式情報を主な根拠としています。