KINTOテクノロジーズのブログ - TECH PLAY

TECH PLAY

KINTOテクノロジーズ

KINTOテクノロジーズ の技術ブログ

1123

この記事は KINTOテクノロジーズ Advent Calendar 2025 の15日目の記事です🎅🎄 こんにちは。KINTOテクノロジーズ株式会社でQAエンジニアをしているおおしまです。今回は、51歳の私が今年一年間、AIに助けてもらいながら業務に向き合ってきた経験と、その活用の仕方についてご紹介します。ほぼ自分語りになりますが、お付き合いいただければ幸いです。 前提:AI推進の機運と現場の課題に挟まれて — 51歳からの挑戦 私の勤務するKINTOテクノロジーズでは、会社全体としてAI活用を強く推進する機運があり、専門部署の設立や数多くの研修機会の提供、社内環境の整備・アップデートなど、非常に恵まれた環境が整っています。そんな状況に身を置くと、 「使わない手はない」という気持ちになる のは自然なことでした。 一方、私がメインで担当していた案件は、既存Webサービスの改善や機能追加を小さな単位で素早くリリースするものでした。規模は大きくありませんが、短期間で高品質を求められる開発・テストは常に厳しく、キャッチアップに苦労する日々。 自動化や仕様整理の効率化は必須であり、AIはそれを支える重要な道具 という認識は持っていました。 黎明期:まずは触ってみる — AIとの距離を縮めたきっかけ 昨年までは公私ともにAIに触れる機会はほとんどありませんでしたが、社内の機運もあり「学んで使えるようになりたい」という漠然とした思いはありました。そんな中、外部講師によるAI研修を受けたことが大きな転機になります。 研修は初歩的な内容でしたが、印象に残ったのは「毎日プロンプトを書いてAIと触れる」という講師のアドバイスでした。世の中の大きな成果を見上げるのではなく、少しずつでも使うことを習慣化する。これが私の中で「スモールスタートでも継続する」という意識に変わった瞬間でした。 この時期はまだ実務とは関係ない形で、 AIと仲良くなるための時間を過ごして いました。 習熟期:現場の必然に応える — 短納期対応でのAI活用模索 最初は業務無関係にプロンプトを書いて、期待通りの答えなのか質問の仕方が悪いのかといった試行錯誤をしていました。そのうち実業務で効率化できないかと抱えてきた課題について、小規模なものからAIで解決できないか試すようになったのが研修から3か月ほど経過したくらいです。 それまでは実務ではAIは全く活用していませんでしたが、このくらいならできそうという感触を実務での困りごとの解決に生かすように仕向けてみました。 結果としてはいろいろできそうという感触がありつつ、 まだ実戦投入にはしんどい状態 というのがこの時期です(案件内容によっては現在もこの状態です)。 開花期:自動化の可能性を掴む — コード生成とプロセス変革 今年9月、社内では「Vibe Coding Challenge」という企画が行われました(詳細は 別のテックブログ記事 で紹介しています)。QAというコーディングが主業務ではない私たちにとっても、この企画は業務の進め方を発展させるきっかけになりました。 具体的には、テスト実施やデータ作成に必要な自動化コード生成でAIが大いに役立ちました。 これが出来たらいいなと願いがありながらスキル不足でできなかったこれらの作業をAIの助力であっさりクリアできたこと。これまでマニュアルテストで確認していたもののうち 自動で置き換えできる領域の拡大可能性が見えた ことが大きな成果でした。 適応期:実戦投入と成果 — 高頻度リリース現場でのAI活用 可能性が見えてきた一方、現場のスケジュールは相変わらず厳しく、むしろ以前よりタスク量は増加。期間延長はできない中で、もうAIに頼らざるを得ない状況でした。 とはいえ、まだ社内コンセンサスが十分ではないため、従来の手法で検証を行いながら、AIによる自動テストでカバーできる部分を徐々に増やす方針を採用しました。 案件詳細はお伝えできませんが、これまで「5車種を3日間で確認」していたペースを、AI活用によって「5日間で60車種以上」をこなすことに成功。今後も続いていく同種の案件では、この成功をベースにより効率的な進行が可能となり、 大きな成功体験 になりました。 展開期:情報共有と発信 — 知見を広げる挑戦 得られた知見はまずQAグループでの定例ミーティングで共有していきました。その後、社内外の勉強会で複数回登壇して成果を外部発信する機会をいただきました。まだまだ先を走る人から見ると小さな成果かもしれませんが、 他社エンジニアとの交流から新しいアイデアを得られたのは大きな収穫 でした。 2025年登壇イベント一覧 日時とイベント名 登壇タイトル 内容 3月27日 JaSST Tokyo QA作業における生成AI活用事例 SpeakerDeck ※弊社ブース前でのミニセッションでプログラムには記載なし 9月24日 CO-LAB Tech Night vol.3 生成AIを自動テストに活用していくための試行錯誤と見えたもの — 11月14日 TokyoTestFest Claude Code × Playwright環境で自然言語による指示のみでフロントエンドテストを自動実行できた話 ※弊社ブース前でのミニセッションでプログラムには記載なし 11月20日 AI時代の開発現場 — 成功と失敗のリアル共有会 Claude Code × Playwright環境で自然言語による指示のみでフロントエンドテストを自動実行できた話 SpeakerDeck ※11/14とほぼ同じ 登壇機会が多かった理由としては会社がシンポジウムのスポンサーになったり、勤務先のOsaka Tech Labにイベントスペースがあって会場として多くの勉強会が開催されたりしたことが大きな助けになりました。そのほか、稚拙な内容ながらも恥を忍んで登壇できたのは、50歳を超えた厚かましさのおかげかもしれません。 終わりに:未来への展望 — AI4QAからQA4AIへ、次の挑戦 今年の取り組みは、とある勉強会で知ることになった今風の用語をお借りして「AI4QA:QA業務にAIを活用」の実現となります。一部できつつあるものの、まだまだ完成には程遠い出来というところも実感しています。この取り組みは来年以降も継続していきます。 その一方で、「QA4AI:AIに対してQAする」も世間的には進んできているようです。弊社でも各サービスや製品をAI活用を前面に押したものが増えるのではないかと想像しています。となると、これまで個人的には想定していなかったAI自体に立ち向かう時代も遠くないと感じています。 これはAI4QA以上の難関で、何をすればいいのかも見当が付きません。ただ、QA4AIが求められるのは、厳しくしんどい仕事である一方、51歳の私でも伸びしろを感じられる刺激的な面がある楽しみもあります。 とはいえ、自分自身の向上も大事ですが、エンジニアの仕事はいいサービス・製品を提供することが第一です。AI4QAでこれまで出来なかったことの実現や時間がかかったことが短縮できた成果を広げていくことは大事ですが、効率化による時間的・精神的余白が出来たことで人間だからできる品質向上への貢献ができれば、高速リリースの時代でもお客様に満足していただけるリリースに貢献できるのではと思います。 今年はこれまで触れる機会がなかったAIにある程度向き合うことができました。来年以降もしっかり向き合っていきたいと思います。
この記事は KINTOテクノロジーズ Advent Calendar 2025 の12日目の記事です🎅🎄 はじめに my route のAndroidアプリを開発している 長谷川 です。 開発をしていると、何らかの理由でメンテナンス性を犠牲にしてしまうことってありますよね。「今動けばいいや」という感じで。 この記事では、アプリがローカルにデータを保存(永続化)する際に陥りがちな罠と、それを防ぐテスト手法を紹介します。ここでは例として Android を取り上げていますが、ローカル永続化を扱うあらゆるアプリケーションに共通する問題であり、同様のアプローチで対策できます。 ケーススタディ:チケット機能の実装 シンプルなチケットの永続化 とあるアプリの開発では、お得なチケット機能があります。チケットには以下のような情報があります。 data class Ticket( val id: String, val name: String, ) このチケットはオフラインでも使える必要があります。オフライン状態ではサーバーから情報を取得できないため、ローカルに永続化する必要があります。 AndroidのSQLiteデータベースを扱いやすくする Room ライブラリを使うと、シンプルなデータ構造なら、アノテーションをいくつかつけるだけで永続化することができます。 @Entity data class Ticket( @PrimaryKey val id: String, val name: String, ) 現実は複雑... しかし、実際のチケット情報はもっと複雑です。 価格情報 有効期限 利用条件 AndroidのRoom (SQLite) などのRDB (リレーショナルデータベース) では、このような複雑なオブジェクトをそのまま保存できません。通常は以下のような対応が必要です。 テーブル設計を工夫してリレーションを作る TypeConverter (複雑な型を基本型に変換する仕組み) を使って変換する しかし、これらの対応は結構大変です... 「あ〜、今はそんなこと考えている時間ないなぁ!」 楽な方法:全部JSONにする! そこで思いつくのが、 全部JSONにしてしまう という方法です。 // ビジネスロジックで使う実際のデータクラス @Serializable // kotlinx.serializationを使用 data class Ticket( val id: String, val name: String, // ... その他複雑なプロパティ (価格、有効期限など) ) // データベースに保存する用のクラス @Entity data class TicketForDB( @PrimaryKey val id: String, val json: String, // Ticketを丸ごとJSON文字列として格納 ) // 保存 fun write(ticket: Ticket) { db.write( TicketForDB( id = ticket.id, json = Json.encodeToString(ticket) // オブジェクト → JSON文字列 ) ) } // 復元 fun read(id: String): Ticket { val ticketForDB = db.read(id) return Json.decodeFromString<Ticket>(ticketForDB.json) // JSON文字列 → オブジェクト } やった〜!複雑なデータ構造を持つチケット情報を簡単に保存できた! この方法なら 複雑なTypeConverterを書く必要なし テーブル設計で悩まなくていい 開発スピードが速い 数ヶ月後...チケット機能の改善 時は流れ、新機能の開発が始まります。 「一つのチケットで複数人が利用できる機能を追加しよう!」 今までは一つのチケットで一人しか利用できませんでしたが、グループ利用に対応するため、 maxUsersPerTicket というパラメータを追加しました。 @Serializable data class Ticket( val id: String, val name: String, val maxUsersPerTicket: Int, // 追加! // ... その他のプロパティ ) やったね!これで便利な新機能も簡単に開発できた! テストも通ったし、リリース準備OK! リリース後、問題発生... リリース後しばらくして、 「クラッシュ報告が来ています!オフラインでチケットが使えないという問い合わせが多数...」 何が起きたのか? 原因は、 新しく追加した maxUsersPerTicket プロパティ です。 問題の流れ: [v1.0] チケット保存 {"id":"abc123", "name":"Sample Ticket"} ↓ [v2.0にアップデート] ↓ [復元を試みる] maxUsersPerTicketが必要だが、JSONにない ↓ クラッシュ! 永続化されたJSONには maxUsersPerTicket がありません。しかし、新しい Ticket クラスは maxUsersPerTicket を必須としています。JSONライブラリは値を決められず、エラーになります。 // この時、永続化されたJSONには maxUsersPerTicket が存在しない val ticket = Json.decodeFromString<Ticket>(json) // → Field 'maxUsersPerTicket' is required for type Ticket どうすれば良かったのか? 解決策1:RDBでリレーショナルモデリングを頑張る RDBはJSONとして保存するよりも、圧倒的に型に強いです。 丁寧にテーブル設計を行っていれば スキーマ変更時にRoomのコンパイルエラーで気づける 型安全性が保証される データの整合性を保ちやすい 一方でデメリットもあります。 複雑なデータ構造の表現が難しい (RDBは表形式) テーブル設計に時間がかかる TypeConverterやリレーションの管理が煩雑 将来的なメンテナンス性も不透明 → 準備が大変な割に、メンテナンス性が必ずしも高くなるとは限らない 解決策2:JSONを使いつつ、ユニットテストで安全性を確保する JSONの手軽さを維持しつつ、ユニットテストで問題を早期発見する方法です。 課題 将来の開発者 (または未来のあなた) が、何も知らずに Ticket のプロパティを追加/削除/変更しても気づけるようにするには? 解決方法 過去のJSON形式をテストで保存し、デシリアライズをテストする まず、現在のバージョンで保存されるJSONをfixtureファイル (テストで使う固定サンプルデータ) として保存します。 // fixture.json (テストリソースとして保存) { "id": "abc123", "name": "Sample Ticket" } テストコード 以下の2つのテストを追加します。 @Test fun `古いバージョンのJSONをデシリアライズできる`() { // 過去に永続化されたJSONが、現在のコードで読み込めることを保証 val jsonString = loadJson("fixture.json") val deserialized = runCatching { Json.decodeFromString<Ticket>(jsonString) } // 失敗したら、新しいプロパティに初期値が必要など、問題に気づける assert(deserialized.isSuccess) { "デシリアライズに失敗しました: ${deserialized.exceptionOrNull()}" } } @Test fun `デシリアライズ後に再シリアライズすると元のJSONと一致する`() { // fixtureファイルの更新漏れを検知 val jsonString = loadJson("fixture.json") val deserialized = Json.decodeFromString<Ticket>(jsonString) val serialized = Json.encodeToString(deserialized) // プロパティを削除したのにfixtureを更新していないケースなどを検知 assert(jsonString == serialized) { "JSONが一致しません。fixture.json の更新が必要かもしれません" } } このテストが守ってくれるもの 古いJSONとの互換性 :過去のバージョンのJSONが読み込めることを保証 fixtureの更新漏れ防止 :データ構造が変わったら気づける 実際にテストを動かしてみよう ケース1:プロパティを追加した場合 問題が発生した例と同じく、数ヶ月後、複数人利用機能が追加されたとします。 @Serializable data class Ticket( val id: String, val name: String, val maxUsersPerTicket: Int, // 追加 ) 先ほどのユニットテストを実行してみます。使用しているJSONライブラリにもよりますが、概ね以下のようなエラーでテストが落ちます。 Field 'maxUsersPerTicket' is required これで将来の開発者やAIはこのデータクラスが永続化されていて、追加されるパラメータには初期値が必要なことが分かります。なぜならすでに永続化されたデータには新しい値が当然考慮されていないからです。 次にプロパティの名前が変更されたとします。 ある開発者がnameという名前は抽象的だ!と言い出して、 displayName に変更しました。 @Serializable data class Ticket( val id: String, val displayName: String, // 変更 ) 先ほどのユニットテストを実行してみます。同じように以下のようなエラーにより、問題に気づくことができます。 Field 'displayName' is required 次に、Ticketから名前が不要になりました。 @Serializable data class Ticket( val id: String, // val displayName: String, // 削除 ) たいていのプロジェクトではJSONライブラリの設定で、 ignoreUnknownKeys のような、知らない値が来たら無視するための設定を有効にしていることが多いと思います。 したがってこれによるクラッシュが発生することは少ないでしょう。 しかし永続化されているであろうfixtureファイルの更新を漏らしたくないです。 先ほどのユニットテストを実行してみます。 以下のようなエラーにより、fixtureファイルの更新漏れを防ぐことができるでしょう。 "JSONが一致しません。fixture.json の更新が必要かもしれません" (上記のテストではどのプロパティに差分があるかまでは分からないので、実際にはobjectとして比較する案が考えられる) まとめ 本記事では、永続化したデータを安全に扱うためのテスト手法を紹介しました。 今日から始められること 現在永続化しているデータのJSON例をfixtureとして保存 そのJSONをデシリアライズするテストを書く CIに組み込む 一度ユーザーの端末に保存されたデータは、簡単には消せません。それは「技術的負債」になりやすい部分ですが、裏を返せば、ここを堅牢に保つことこそがアプリの長期的な信頼性に繋がります。 また、今回紹介したFixtureを用いたテストは、 JSONライブラリの置き換え (例:GsonからMoshi/Kotlin Serializationへの移行) などにおいても極めて強力な武器になります。同じFixtureに対してテストが通れば、ライブラリや環境が変わっても「以前と同じようにデータを復元できる」ことが保証されるからです。 「今動くコード」を書くのは当然として、私たちはそこから一歩進んで、「ライブラリが変わっても、担当者が変わっても、少しでも安全に動き続けるコード」を残せるエンジニアでありたいものです。
こんにちは。プラットフォームGでPlatformEngineeringの考え方をベースにツール周りの開発・運用・展開の役割(とエンジニアリングマネージャーと本格的にアプリケーション開発もやり始めて、よくわからなくなった) 島村 です。 この記事は KINTOテクノロジーズアドベントカレンダー2025 の14日目の記事です🎅🎄 社内モニタリング基盤をリプレイスするにあたって、ECSやManagedServiceではなく、EKS上に構築した話についてお話しをします。 背景 弊社では元々、 社内モニタリング基盤 OpenSearch (Log + Alert + Visualization) Managed Prometheus (Metrics) Managed Grafana (Alert + Visualization) X-Ray (Trace + Visualization) SaaS NewRelic (ALL) となっていました。基本、そんなに監視運用レベルが求められないものはモニタリング基盤、ガッツリ色々見たい+関連サービスがあるものはNewRelicというような感じです。 OpenSearchについては、本当はバージョン追従をするべきなんですが、古いままで運用し、 2025/11についにEOLになりました。 コストや運用の手間を減らす目的と、AIのベクトルストアで使えるか確認のため、Serverlessの検証なども行ったんですが、「確認の際に横断的に見えないというのは課題だ」、ということで、全体的な刷新を行うことにしました。 合わせて、RCA(RootCauseAnalysis)の情報取得元としても使いやすくしようということで、関連プロジェクトとしてプロジェクト化しました。 (RCAの概要はこちらのイベントのLT参照) まずはStackを決める まず、弊社のワークロードの基本構成はECS+Fargateです。AWS上に環境を作る場合、PackModuleと呼ばれているTerraformのモジュール群があります。→ 過去参考動画 なので、ECSをベースに考えたのですが、制限事項も多いことから、まずは求められること(要件)を整理しました。 したいこと 横断的にLog/Metrics/Traceが可視化できること (リソース、ライセンス的に)安価であること 切り替えが容易であること Fluentbitでログを、AdotCollectorでMetrics/Traceを転送している部分を大きく変更しない。 永続ログはS3に保存できること モニタリング基盤から保存ではなく、途中でAWSコンポーネントからの転送でもOK NewRelicより可能なら長く検索できる期間があること 特に、2番目については、NewRelicというSaaSツールも既にありますから、使用するアプリケーションユーザ側の予算的に今までより高価になると意味がありませんでした。 しないこと こちらも重要だと思います。最低限必要なものを整理して、あれもこれも…とやると時間と手間が増えます。 AWSのアカウントは既存と同じにする 運用アカウント分割を過去は検討したが、現状ではやらない CloudInfraチームやSCoEなど、アカウント増やすなら関係各所が増えるのと、アカウント自体のセキュリティールールの運用のため Profile可視化(Pyroscope) アプリケーション担当者へのトランスファーや運用手順が増える S3にある永続ログを検索できるように戻したりとかはしない 生成AI周りの監視基盤 最終的にはLangFuseが生えましたが、最初の時点ではスコープ外 決まったこと 使うOSS 名称 機能 概要 Loki Log保存 ログ保存。OpenSearchのOSSやElasticも悩みましたが、全体揃ってるので基本GrafanaLabs系で統一 Tempo Trace保存 トレース保存 Grafana 可視化 各種可視化とアラート。Grafanaの構築単位は任意のアプリ群にしました Alloy AWSログ転送 Lambda/WAF/RDS系のログがKinesisFirehose(HTTP)からAlloyを経由してLokiに転送 Thanos Metrics保存 Mimirではなくこちらで。メンバーのナレッジがあったため 自作Logger AWSログ転送 ALB/Cloudfrontの、S3にしか出力できないログの転送用。現行はLogStashを使用 ArgoCD GitOps GitOpsのためこちらを選択 制限事項 Thanos/MimirともにNFSをサポートしてないので、ECS+Fargateだと厳しい CNDW2025でLokiをECS+Fargateで構築した人がいらっしゃったんですけど、コンポーネントとか考慮点が多い Grafana系だとLoki以外はDockerでのDeploy手順が公式でサポートされていない Prod環境だとHelmかTankaでのデプロイメントが推奨 あ、EKSで動かすしか無いか… もともと、EKSはアプリケーション要件があれば導入を検討しようという話もありました。そのため、ちょうど良い機会としてEKSを実行サービスとして決めました。ただ、Webアプリケーションを動かしているワークロードについてはECSのままとしています。 PlatformEngineeringTeamとして、CICDのテンプレートやその他ツール群を提供していますが、アプリケーション部門にEKSを提供するメリットがあまり見えなかったことと、提供のための各種修正を考慮した結果です。 構成 ※NewRelic経路は変わらないので割愛 AWSコンポーネント この時点で、ちょうどEKSにAutoModeが発表されました。制限事項の1つ目のEFSの対応という点では、EKS+Fargateでも対応不可だったので、AutoModeを使ってみようということになりました。 AutoModeでも、ARM64を指定した設定ができ、起動するEC2のインスタンスが安価になるので、構築後にArmアーキテクチャのNodePoolを設定しています。 EKS構築以外の新モニタリング基盤の推進に向けたおしごと PackModuleの修正 最初の方 にあった、Moduleの修正です。 意識しないと移行しない(=Default値が変わらないようにする)形で修正しました。 KinesisFirehose(HTTPエンドポイント向け)のModule作成 Backupの取得をALLにしてS3へ保存( 要件4 に関連する) 呼び出す各コンポーネントModuleの修正 Lambda WAF RDS セキュリティー調整 Firehoseですが、VPC内部に作成されないので、Alloyの前段のALBにインターネット経由での通信経路となります。その場合、さすがに認証認可もなしでALBにログを送るのもNGでしたので、Headerでの認証を追加しました。 構築時にSecretManagerにKEYを保存して、Firehoseからはそれを付与して送信。ALBではその値とマッチしているか?と確認しています。 コンテナの脆弱性を検知する仕組みをECR+通知で作っており、DockerHubから直接呼び出さずに、ECRに一時的に保管する運用も行なっています。が、かなり運用負荷が高いので、どうにかしたいのが課題となっています。 移行のお願い 一番泥臭く、CustomerSuccessEngineerチーム(CSE)が各担当にお声がけをしてチケットを切って管理する形で行なっています。一部は開発タスク優先で期限からはみ出ましたが、多くのプロダクトはありがたいことに協力いただき、年内での切り替えを想定しています。 アプリケーションの担当者の変更作業としては Fluentbitの使用バージョンの変更(LokiPlugin向け) 各種Configの修正 AdotCollector ECS TaskDefinition こちらは、PlatformGでConfluenceに作業手順を準備して、提供しています。 Firehoseなどの切替は、アプリケーション担当者と日程を調整し、PlatformGとCloudInfraGでTerraformの修正という形で行なっています。 おまけ アカウント分割の対応 移行中ではあるんですが、社内のAWSアカウントの最適化が進んでおり、そちらの変更反映も実施する予定です。 ただ、EKSの前にはNLB/ALBを挟んでいるため、VPCPeeringかVPCEndpointによる対応で済む見込みです。 (´・ω・) 運用アカウントに分割する日は、何時来るのかな LLM監視や追加機能のデプロイ RCAのためのLangFuse、実行時間やメモリなどの関係からCode分析機能がLambdaをやめてEKS上に移行、AWSメトリクス収集のための YACE のデプロイなど、モニタリング・RCA関連が色々と追加で載るようになりました。 所感 基本、機能要件とか技術制限など、何かしらの理由がない場合は、AWSでコンテナなどを動かすにはECSで十分だと思います。実際、n8nとか他のOSS系はECSで起動するようにしています。 新しくジョインしたメンバーがEKSと各種Grafanaスタックに経験が多かったこともあって、ある程度、スムーズに構築や移行できたこともあります。 ただ、AutoModeの運用経験や、実際に各環境のログなどを投入していくと問題、エラーなどが出てきました。安定運用までに色々と手を打たないといけないと考えています。 やはり、K8s運用は一筋縄ではいかないと実感しました。 さいごに PlatformEngneeringチームは、社内向けの横断ツールを統制して必要なものを開発しています。 必要なものを新規作成や既存のものをマイグレーションしたり、ツールを使ってもらうためのEnablingの活動や、マーケティング技術を使った内部展開などのチームもあります。 GoldenPathの整理(そもそも業務フローの可視化・改善)も実施していく予定です。 こういった活動に少しでも興味を持ったり話を聞いてみたいと思った方は、お気軽にご連絡いただければと思います。 @ card
この記事は KINTOテクノロジーズ Advent Calendar 2025 の14日目の記事です🎅🎄 はじめに 2025年にKINTOテクノロジーズのQAGに入社したメンバーで、アドベントカレンダーに参加しました! 入社してからこれまでのQAとして取り組んできたトピックをまとめています。 同じQAの方々にはアイデアのきっかけとして、開発の方々には「QAってこんなこともやるんだ」という認知の拡大につながればと思います。 テスト効率化のためのWebAppの作成 自己紹介 とみよしです。前職でも第三者検証でQAをしていました。開発経験はほとんどありません。 内容 ある日こんなことが。 スマホ端末でチャットに文言入力するのに効率よくテストをするためにはどうすればいいだろうかという話に。 いっそのことAIを使ってWebAppを作るか!という案が出ました。 なので作りました!! コピー ペースト 仕組みとしては作業自動化ツールのZapierを使用し、 AIで生成した質問をGoogle SpreadSheetにDBとして格納、 Google App Scriptを使用してWebAppとして作成しました。 ツール 行っていること 参考画像 1 Zapier form画面の作成。 Zapierの機能としてInterfacesからformの作成を行うことができます。 2 Zapier AIによる質問生成 form画面から入力された内容を元に質問を生成します。 ー 3 Zapier Googleスプレッドシートへの連携 生成した質問をGoogleスプレッドシートに連携します。Zapierの標準機能としてこちらの連携が行えます。 ー 4 Googleスプレッドシート DBの代わりとして使用 Zapierから連携した質問内容を保存する ー 5 GoogleAppsScript DBの代わりとして使用Zapierから連携した質問内容を保存する ー これを作成するにあたって最初はできるのか?と思いながら進めていましたが、 AIにどうすればできるのか、どうやればいけるのかなど細かく聞きながら進めていきました。 Zapierでスプレッドシートに連携することはできました。連携している内容に生成された質問JSON(D列)があります。 このJSONのquestionsの内容を一覧にして一つ一つコピーできるようなwebを作成したいです 添付:ダウンロードしたGoogleスプレッドシートのExcelファイル もちろん一発でできるわけもなく、AIに生成してもらったコードをそのまま利用してもエラーが発生しました。 そのエラーに対してもAIに一つ一つ確認していくことで今のような形になりました。 当初は検索機能などもなかったため、利便性の面ではやや物足りない状態でした。 ただ一度に大量のことを要求することはせず、細かく機能追加を行うように指示したのが今回はうまく行った要因かと思っています。 このように行っていったおかげでコードについてもほとんど自分からは手を加えてはいません。 ひたすらこうして欲しいと言ったのを繰り返し、コードと向き合っていた期間としては1〜2日程度で作成してくれました。 このWebAppであらかじめチャットに入力する内容を登録しておき、 スマホ端末でアクセスしてコピペをするだけになったことで、 ひたすらキーボード入力するよりは効率的に実施できるようになりました。 初のWebApp作成でしたがAIと二人三脚で何とか作り上げることができました。 開発ほぼ未経験でもこうして作り上げることができるので今後も挑戦していきたいと思います。 付録 Zapier: https://zapier.com/ Googleスプレッドシート: https://workspace.google.com/intl/ja/products/sheets/ Google Apps Script : https://developers.google.com/apps-script?hl=ja Appium環境構築初心者の体験談を発表してきました 自己紹介 ろきです。前職ではニュースアプリの会社でQAをやっていました。開発未経験です。 内容 こんにちは! 先日、 Appium Meetup Tokyo #3 で「Appium環境構築の初心者つまづきポイント」についてLTしてきました。 形式はオンラインとオフライン両方。時間は15分くらいで、スライドを使って4つのポイントを紹介しました。 そもそもAppiumに興味を持ったのは、「コーディングの第一歩を踏み出せそう!」と思ったから。 とはいえ、初心者だと環境構築で詰まってしまって心が折れることもありますよね。 私自身もかなりハマったので、「同じようなところで困っている人に少しでも役立てば…」と思って発表しました。 話したポイントはこんな感じです。 エラーはAIに聞くと意外と解決できる バージョン合わせはAppium公式HPを見ると確実 必要なツールだけ起動してツールの競合を防ぐ Gitコマンドは触って慣れるのが早い 登壇後、参加者の方から「あるあるばかりで共感できました!」と言ってもらえたのが嬉しかったです。 人前で話すのはやっぱり緊張しますが、終わったあとはホッとしました。 これからも少しずつコーディングに挑戦して、できることを広げていきたいです。 付録 https://speakerdeck.com/kintotechdev/appiumwodong-kasumatenotumatukihointo-chu-xin-zhe-kagan-sitariarunabi-toxue-hi Playwrightによる自動化 自己紹介 ひがしです。前職では第三者検証のQAをしていました。開発経験はほとんどありません。 内容 僕が入社して印象深かった経験は『テスト自動化』です。 前職では全くしたことがありませんでしたが、上長と先輩社員から「やってみる?」とお話を頂いた時は「ぜひ!」と二つ返事するくらいワクワクでいっぱいでした! ジョインした案件では、様々な申込条件で申込完了までの一連のフローを確認するリグレッションテストが必要となりました。 そこで、それを自動化で実施するために、この案件専用のリグレッションテスト用スクリプトを作成することになりました。 また、僕の所属チームでは、E2Eテスト自動化のためのツールとして『Playwright』を採用しており、 既に先輩社員がデータ作成用やリグレッションテスト用のスクリプトをある程度完成させている状態でした。 それらのスクリプトを参考に、指定された申込条件のスクリプトを作成するお手伝いをさせていただきました。 参照するスクリプトがあるものの、 プルダウンの選択値やテキストボックスの入力値、押下するチェックボックスやボタンなど、コンポーネントの操作が1つ異なるとそこで要素取得エラー等が出て、 なかなか思うように作業を進めることができないことがありました…。 そこで僕がお世話になったPlaywrightの機能が『コード生成機能』です。 この機能は、ブラウザ操作を録画し、その操作に対応する自動化用コードを出力してくれるものになります。 この機能を使い、一度申込条件に沿ったブラウザ操作を行なってみることで、 初心者でもすごく簡単にコード生成および要素の取得ができ、エラーを解決することができました。 (例:”取扱車種一覧を見る”をクリックする操作を録画) 他にもまだ知らないPlaywrightの便利な機能があると思いますので、 先輩社員に尋ねたり自身で調べながら少しずつ使用できるようになり、徐々にPlaywrightに慣れていきたいです。 Appium周りの対応と開発ルール周り整備を行った話 自己紹介 mです。KTC入社と同時にQAへジョブチェンジしました!前職まではAndroidアプリの開発をしていました。 内容 最近、Appiumを用いたE2Eテストの自動化に挑戦する機会がありましたのでその内容についてです。 主に2つのポイント、単体テストとE2Eテストの違いと所感、そして開発ルール周りの整備について触れます。 1. AppiumによるE2Eテストの導入 E2Eテストとはユーザーが実際に行う操作を端末上で再現し、アプリ全体の動作を検証するものです。 Appiumを使ってAndroidアプリとiOSアプリのE2Eテストの作成に取り組みました。 その中で特に課題となったのが実行にかかる時間です。 E2Eテストでは待機時間の発生が避けられません。具体的には、以下のような待機時間が発生します。 UI操作の待機 画面描画の待機 通信処理の待機 待機時間の増加に伴い、テスト実行時間とコストも増大します。 そのため、どのシナリオからテストを優先するかの判断や、外的要因によってテストが正常に実行できない場合に備えたリトライ処理の設計が重要になります。 現在は相互レビュー時に処理内容について相談することで、実行速度の高速化を進めています。 その結果、一部処理の負荷軽減を実現できました。引き続き検討と対応を進めていきたいと思います。 2. 開発ルール周りの整備について プロジェクトのメンバーが増えてきたため、ブランチ戦略やブランチ保護の設定見直し、PRのルール策定など開発にまつわるルールの整備を行いました。 ブランチ戦略の変更 以前はGitHub Flowを採用していましたが、現在はGit Flowに変更しました。 この変更の主な理由は、利用するアプリのバージョンごとにリリースを管理したかったためです。 Git Flowを採用することで、機能開発やリリースの管理が明確になり、複数のバージョンを同時に扱う際の混乱を軽減できます。 ブランチ保護の設定見直し 実運用環境で動作しているmainブランチで、 自身含めて新規でアサインがあった開発者の各個人の環境によって動作しない事象が発生していました。そのため、mainおよびreleaseブランチへのPR作成時に GitHub Actionsのワークフローを利用して 自動的に動作確認(全テスト実行)が通るかどうか確認できた場合のみマージ可能とする設定に変更しました。 PRのルール策定 開発者がそれぞれ以前のPRで何を対応していたかを明確にするため、 以下の項目を含むPRテンプレートを用意しました。 対応内容概要 詳細 動作確認した内容 レビュー時に確認して欲しいこと このテンプレートにより、PRの内容が整理されレビューが効率的になることを目指しています。 これにより、さらに安定・安全に開発を進めるための基盤を整えることができました。チーム全体で協力し、より良い開発環境を作り上げていきたいと思っています。 今回ご紹介したようなAppiumを用いたE2Eテスト自動化の取り組みや、 QA観点での開発ルール整備については社内イベントでも継続的に発信しています。 大阪支社(Osaka Tech Lab)にてCO-LAB Tech Nightというイベントを毎月実施しておりますのでぜひご参加ください、、、! QA回で登壇させていただいたときの様子です。 最後に 最後まで読んでいただきありがとうございます。 今回の内容が皆様のQA活動のきっかけの一つになれば幸いです。
This article is the Day 14 entry for the KINTO Technologies Advent Calendar 2025 🎅🎄 Introduction We, members who joined KINTO Technologies' QA Group in 2025, have participated in this Advent Calendar campaign! This blog describes the topics we have worked on as QA team members from our joining the company to date. We hope it serves as inspiration for QA professionals and helps developers understand that QA has tasks which are not perceived well. Creating a Web App for Test Efficiency Self-introduction I'm Tomiyoshi. I worked as a QA in third-party verification at my previous job. I have almost no development experience. Content One day, something came up. We discussed how to efficiently test text input in a chat on mobile devices. Someone said, "Why don’t we just use AI to create a web app? So, I built one!! Copy Paste The system uses Zapier, a process automation tool. After questions generated by AI are stored in Google Spreadsheet as a database, we use Google Apps Script to create the web app. Tool What a Tool Does Reference Image 1 Zapier Creating a form screen Zapier's Interfaces feature allows you to create forms. 2 Zapier AI-powered question generation Generates questions based on input from the form screen. — 3 Zapier Integration with Google Spreadsheet Links generated questions to Google Spreadsheet. This integration is enabled as a standard Zapier feature. — 4 Google Spreadsheet Used as a database substitute Stores question content shared from Zapier — 5 Google Apps Script Displays the web app based on the question content stored in Google Spreadsheet — When I started creating the app, I was in doubt that I could finish it. I proceeded by asking AI for details about how to accomplish each step for the app creation. I was able to link Zapier to the spreadsheet. The linked content includes the generated question JSON (in Column D). I want to create a web page that lists the contents of the questions in this JSON and allows for copying each one individually. Attachment: Downloaded Google Spreadsheet Excel file Of course, it didn't work on the first attempt, and errors occurred when I used the code generated by AI as-is. By checking each error with AI one by one, I was able to create the app in the current format. Initially, the app didn’t have a search function, so it somewhat lacked in convenience. However, I believe the key to success is not to request too many things at once but instruct AI to add detailed features step by step. Thanks to this approach, I rarely modified the code on my own. I simply kept writing about what I wanted to do on prompt, and AI gave shape to my ideas by coding for about 1 to 2 days. Once I registered template texts in advance to input into the chat using this web app, all I need to do is to access it from a mobile device and copy-paste, rather than to manually type texts on a keyboard, which increased the input task efficiency. This was my first web app creation, but I managed to build it, collaborating with AI. Despite a lack of development experience, I was able to create something like this, so I will continue trying to develop new things. Appendix Zapier: https://zapier.com/ Google Spreadsheet: https://workspace.google.com/intl/ja/products/sheets/ Google Apps Script: https://developers.google.com/apps-script?hl=ja Presenting My Experience as a Beginner Setting Up an Appium Environment Self-introduction I'm Roki. At my previous job, I worked as a QA at a news app company. I have no development experience. Content Hello! Recently, I gave a lightning talk at Appium Meetup Tokyo #3 about "Stumbling Blocks for Beginners in Appium Environment Setup." The event took place both online and onsite. I talked for 15 minutes about introducing four key points using slides. The reason I felt interested in Appium was that I thought this could be my first step into coding! However, as a beginner, getting stuck on environment setup may be discouraging. Since I struggled quite a bit myself, I wanted to present my experience, hoping it might be helpful for others facing similar issues. Here are the points I presented: AI is surprisingly capable of providing solutions when you ask about errors Checking the official Appium website ensures the correct versions Only launching necessary tools prevents tool conflicts Getting hands-on experience is the fastest way to learn Git commands After my lightning talk, I was happy when participants told me that they could really relate to all common issues. Speaking in front of people is still nerve-wracking, but I felt relieved when it ended. I want to continue coding little by little and expand what I can do. Appendix https://speakerdeck.com/kintotechdev/appiumwodong-kasumatenotumatukihointo-chu-xin-zhe-kagan-sitariarunabi-toxue-hi Automation with Playwright Self-introduction I'm Higashi. At my previous job, I worked as a QA in third-party verification. I have almost no development experience. Content The most memorable experience since I joined the company was testing automation. I had never done it at my previous job, but when my manager and colleagues said, "Would you like to try it?" I was so excited that I immediately said, "Absolutely!" The project I joined required regression testing to verify the entire process up to application completion under various conditions. To automate the process, we decided to create a regression test script specifically for this project. Also, my team has adopted Playwright as a tool for E2E testing automation, and my colleagues had already completed data creation and regression test scripts to some extent. Based on the scripts, I created ones for specified application conditions. Although I had reference scripts, when even one component operation differed—such as dropdown selections, text box inputs, or checkboxes and buttons to click—element retrieval errors would occur. This hindered me from making progress as smoothly as I expected... That's when I found a Playwright feature that helped me the most: the code generation feature. It records browser operations and outputs automation code for them. Using this feature for performing browser operations in line with the application conditions, even beginners can easily generate code and retrieve elements. Thanks to the feature, errors are solved. (Example: Recording the operation of clicking "View vehicle list") There are still many convenient Playwright features I don't know about, so I want to gradually learn how to use them by asking colleagues and researching on my own, thereby getting more familiar with Playwright over time. Handling Appium-Related Tasks and Establishing Development Rules Self-introduction I'm m. I made a job change to QA when I joined KTC! Until my previous job, I was developing Android apps. Content Recently, I had an opportunity to get involved with E2E testing automation using Appium, so I'll share that experience. I'll touch on two main points: the differences between unit tests and E2E tests along with my impressions, and the establishment of development rules. 1. Introduction of E2E Testing with Appium E2E testing reproduces the operations that users actually perform on devices and verifies the overall behavior of the app. I worked on creating E2E tests for Android and iOS apps using Appium. The particular issue was the execution time. Wait times are unavoidable in E2E testing. Specifically, the following wait times occur: Waiting for UI operations Waiting for screen rendering Waiting for network communication The more waiting time we have, the more test execution time and costs we need to spend in testing. Therefore, it is significant to decide which scenarios to prioritize for testing and to design retry processing for cases where tests cannot execute normally due to external factors. Currently, we are working on speeding up execution through discussions about processing content in our peer review phase. As a result, we have achieved reduced load on some processes. We will continue to discuss and address these issues. 2. Establishing Development Rules As the number of project members increased, we established development-related rules, such as reviewing branch strategies, branch protection settings, and PR rules. Changing Branch Strategies Previously, we used GitHub Flow, but we have now changed the version control system to Git Flow. That is mainly because we wanted to manage releases for each version of the app we use. Adopting Git Flow enabled clearer feature development and release management, reducing confusion when we handle multiple versions simultaneously. Reviewing Branch Protection Settings On the main branch running in the production environment, we faced an issue that the application didn’t work due to individual environment differences among newly assigned developers, including myself. To overcome the issue, we changed the branch settings to enable merging in creating PRs for the main and release branches only when GitHub Actions workflows automatically verify that operation checks (running all tests) pass. Establishing PR Rules To clarify what each developer was doing for previous PRs, we prepared a PR template including the following information: Summary of changes Details What was verified What reviewers should check This template was designed to organize PR content and make reviews more efficient. It helped us establish a foundation for more secure and safe development. We want to work together as a team to create an even better development environment. We continuously share initiatives like E2E testing automation using Appium and development rule establishment from a QA perspective at internal events. We currently hold a monthly event called CO-LAB Tech Night at our Osaka branch (Osaka Tech Lab), so please join us...! Here's a photo of the event when I presented at the QA session. Conclusion Thank you for reading to the end. We hope this content serves as inspiration for your QA activities.
この記事は KINTOテクノロジーズアドベントカレンダー2025 の13日目の記事です🎅🎄 はじめに はじめまして!の方も、いつもありがとうございますの方もこんにちは!! KINTOテクノロジーズ(以下、KTC)でエンジニア採用と採用広報を担当している たけの ひかる( @t_hikarutaaaan )です。 毎年恒例のアドベントカレンダー企画、 今年も呼吸をするようにエントリーしてみました!(笑) 今回は、 「エンジニア採用と採用広報の舞台裏」 をテーマに、 私の “とある1日” をゆるっと紹介してみようと思います。 すこしだけ自己紹介 入社して約4年、採用担当になって約2年。 当時は 人事も採用も完全にゼロ経験からのスタート。 技術の話は半分も理解できず、 スカウト1通送るだけであたふたして、 面談ではガチガチに緊張してスクリプトを棒読み。(今では完全にネタw) でも、止まらずに挑戦し続けたからこそ今言えます。 「採用という仕事が、本当に好きです。」 そしてKTCは、 “やってみたい” と手を挙げた人に本気で任せてくれる会社。 未経験の私が走り続けられたのは、そのカルチャーのおかげです。 やっと笑ってイベント司会ができるようになりました エンジニアって、魔法使いじゃん 実は、採用担当になって少し経ったころ、生成AIにコードを書いてもらいながら 採用データを分析できる小さなアプリをつくったことがあります。(アプリって言っていいレベルではないですがw) ワンクリックで画面にグラフが表示された瞬間、思わず声が出ました。 「え、すご…魔法じゃん。」 技術が人の困りごとを一瞬で解決してしまう瞬間にシンプルに感動しました。 で、そのとき思ったんですよね。 「あ、もっとちゃんと向き合わなきゃ」って。 現場の人たちがどんな想いでプロダクトつくってるのか、 「もっとちゃんと知りたいし、もっともーっとちゃんと伝えたい」と。 そこから更に毎日あたふたしながら走り回ってます。(笑) というわけでここからは、 そんな私の 「とある1日」 をゆる〜く紹介してみます! 時間 内容 実際にやったこと こんな気持ちでやってます(例) 09:00 スカウトtime ターゲット選定、プロフィール読み込み、スカウト文作成&送付 どの媒体にしようかな。良い人発見。「なぜ声をかけたいのか」を必ず書く 10:00 書類選考 職務経歴確認、現場メンバーと評価すり合わせ むむ…めちゃくちゃ良い人…! 11:00 現場MTG 採用状況共有、採用要件摺り合わせ、PJ状況ヒアリング 分からないことは素直に聞く。優しく答えてくれる文化に感謝 🙏 12:00 ランチtime 卵かけごはんをすする かつお節が合う。おなかいっぱい。 13:00 カジュアル面談 キャリアヒアリング、プロダクト紹介 双方コミュニケーションできた時が最高。時間足りない日も多い。 15:30 採用広報企画 採用トレンド調査、競合リサーチ、企画案作成、資料構成 煮詰まった…。壁打ち相手求む。 17:00 カジュアル面談 キャリアヒアリング、プロダクト紹介 技術質問に少し答えられず…あとで現場に確認。 19:00 イベント運営 受付、撮影、アナウンス、来場者サポート 基本、走り回ってます(笑)。写真撮って声かけて…ハイハイ! コスパ&タイパ最高の卵かけごはん 採用の難しさと向き合う日々 採用は、スペックだけでは測れない世界です。 会話の空気 ちょっとした表情の変化 選択の背景にある価値観 そういった“見えないもの”を丁寧に受け止める必要があります。 ある候補者の言葉が忘れられません。 「転職の決め手は、“誰と働くか”なんです」 その一言で、ハッとしました。 私はずっと会社としての魅力を伝えることに精一杯でした。 でも候補者の方が本当に知りたいのは、 「このチームなら、自分の挑戦を託せるか」 それからは、 現場の空気やカルチャー、そこで生じる悩みや挑戦も含めた本音を届けることを大切にしています。 面談の最後に 「一緒に働く姿が想像できました」 と言ってもらえた日は、心の中で小さくガッツポーズしています。(笑) 採用広報で挑戦したこと 今年、採用広報として 国内最大級のモビリティイベントである Japan Mobility Show 2025 の登壇企画を担当しました。 KTCが所属するTOYOTAグループ内の関係者や、 リアル領域とIT領域それぞれの担当者を巻き込みながら進めるプロジェクトで、 調整量も難易度も、正直これまでで一番大変でした。(笑) でも、どうしても実現したかった理由があります。 私たちの強みである「リアル × IT」での挑戦を、ちゃんと外に届けたかった。 そして、「一緒にやろう」と快諾してくれた部長の熱量を発信したかった。 求人票だけでは伝わらない空気や想いを、 生の言葉で届けたかったんです。 本番のあと、応援してくれていた社内メンバーから 「めちゃくちゃよかったよ!」 と声をかけてもらえて、すごく嬉しかったです。 さらに後日、登壇企画の動画が公開されたあと、 日々いろいろな業務で関わるグループ企業の方々にも 「YouTube見たよ!」「いい内容だった」「かっこよかった」 と声をかけてもらえたと。 さらに、登壇してくれた部長はこんな言葉をくれました。 「採用に効いてくるのはもう少し先かもしれないけど、 社内広報とか、KTCのセルフブランディングには効いてくるね」 めちゃめちゃ嬉しかったぁ。なんだろ。うまく言葉にできないけど(笑) 採用広報は、会社の挑戦と未来の仲間をつなぐ仕事。 私はその“橋渡し役”でありたいと思っています。 会場の写真を一生懸命撮ってます ちなみに以下がこの記事で触れた登壇企画のアーカイブ動画です! あつーーく、ギュギュっと詰まった50分なので是非ご視聴ください♪ https://youtu.be/NXM2lyapia0?si=QiK5GP2XFtCh0c9c 採用はチーム戦であり、未来づくり 採用に、これが正解!っていう形はありません。 毎回迷うし、悩むし、揺れ続けます。 (正直、答えが分からなすぎてソワソワする日もある。笑) でも、ひとつだけ確信していることがあります。 いい採用は、いい“対話”からしか生まれない。 KTCには、私を含めて5名の採用担当がいます。それぞれが部門に専任としてつく部門担当制。 だからこそ、現場とめちゃくちゃ密にコミュニケーションができるんです。 プロダクトの話も、カルチャーの話も、 嬉しいことも、しんどいことも、ぜんぶ一緒に考える。 そうやって、チームで採用をつくっている感覚がある。 これは本当に誇れるポイントだと思っています。 最後に、読者のみなさまへ エンジニアのみなさまへ   尊敬しています。本気で。   技術で未来を変えていく姿は、私にとってずっと魔法のように見えています🪄 プロダクト開発に関わるみなさまへ   本気でプロダクトと向き合う姿勢や、ひとつの価値をつくるためのコミュニケーションや試行錯誤。   そのリアルなストーリーに、私はいつも心を動かされています。 人事グループの仲間へ   いつもわちゃわちゃしている私と一緒に悩んでくれて感謝です!!   これからも一緒に走ってね!!(/・ω・)/ KTCのみなさまへ   いつも助けてくれてありがとうございます!!   私の大好きな会社がもっと強くなるために、まずは採用という場所から全力で貢献します!!! この記事を読んでくださったみなさまへ   もし少しでも何か響くものがあったら、   ぜひイベントで、カジュアル面談で、、、、どこかでお会いできたら嬉しいです!! 未来の仲間へ 私たちKINTOテクノロジーズは変革期の自動車産業のど真ん中で、 内製開発組織をゼロからつくる挑戦をしています。 こんなダイナミズムに関われるチャンスは、そう多くありません。 未来を一緒に創る仲間をお待ちしています🙌 以上、採用担当・広報担当の“とある1日”でした! 読んでくださり、本当にありがとうございました~~~!
This article is the Day 13 entry for the KINTO Technologies Advent Calendar 2025 🎅🎄 Introduction Nice to meet you if this is our first encounter, and hello again if you've been following along! I'm Hikaru Takeno ( @t_hikarutaaaan ), and I handle engineer recruiting and recruitment PR at KINTO Technologies (KTC). The annual Advent Calendar tradition—I signed up for it again this year as naturally as breathing! (lol) This time, I'll give you a casual look at the behind the scenes of engineer recruiting and recruitment PR through a day in my life. Brief Self-Introduction It's been about 4 years since I joined KTC and about 2 years since I became a recruiter in the company. Back then, I started with absolutely zero experience in HR or recruiting. I could barely understand half of the technical discussions and would get frustrated with just sending a single scout email. In addition, at interviews, I was so nervous, so all I could do was just read my script in a monotone voice. (Now, it’s a funny story. lol) As I have been committed to recruitment without stopping, I can say this now: "I truly love this job." KTC is a company that genuinely entrusts responsibilities to members who raise their hand and say they want to try. Thanks to that corporate culture, I was able to move forward even with no recruitment experience. Now, I can host events with a smile. Engineers Are Basically Wizards A little while after becoming a recruiter, I built a small app that could analyze recruiting data using generative AI for writing the app code for me. (It may not as well-developed as apps at a professional level, though. lol) With a single click on the app, a graph appeared on screen, which I couldn't help but speak out loud, "Wow, that's amazing! It’s like magic." I was simply impressed by how technology can solve someone's problem in an instant. And that's when I thought: "I need to engage in this job more seriously." I wanted to understand what kind of passion onsite members have when they build products, thereby introducing them to the public even in a more appropriate manner. Since then, I've been busy working on my job every day. (lol) From here, let me casually show you a day in my life! Time Activity What I Actually Did How I Feel About It (Example) 09:00 Scouting time Selecting target candidates, reading profiles, drafting & sending scout messages. With a consideration of which platform should I use, I found a great candidate, always writing "why I want to reach out that person." 10:00 Resume screening Reviewing work history, sharing evaluations with onsite team members. Hmm... this person is really impressive...! 11:00 Onsite team meeting Sharing recruiting status, checking if the potential candidates meet our requirements, catching up project updates. I ask honestly when I don't understand. I’m grateful for the culture where team members kindly answer my questions all the time. 🙏 12:00 Lunch time Gobble a tamago kake gohan (rice with a raw egg). Bonito flake is a great combination with the egg. I’m so full. 13:00 Casual interview Learning about candidates’ career, introducing our products The best moment is when we can have a real two-way conversation. I often don’t enough time to understand candidates just in the single interview. 15:30 Recruitment PR planning Researching recruiting trends and competitors’ strategies, drafting plans, organizing materials I’m stuck..., needing someone to bounce ideas off. 17:00 Casual interview Learning about candidates’ career, introducing our products I couldn't answer some technical questions...so got to ask them to team members later. 19:00 Event operations Reception, photo shooting, making announcements, assisting attendees I basically running around the event venue (lol), taking photos, talking to people... OK, coming right up! Tamago kake Gohan—the most cost-effective and time-efficient meal to me Facing the Difficulties in Talent Recruitment Every Day Recruiting is a field where we can’t judge individuals on their knowledge, skills, and other characteristics. The atmosphere of a conversation with them Subtle changes in their facial expression The values behind their choices You need to carefully perceive these hard-to-see signs from candidates. I can't forget what one said: "To me, the important factor when choosing a new job is 'who I work with.'" This made me realize something— I had been so focused on conveying attractive points about working at our company. But what candidates really want to know is: "Can I entrust my career to this team?" Since then, I've strive to talk openly and honestly to candidates about our teams’ atmosphere, corporate culture, and even what we struggle with and concerns arising from our working environment. I still remember when a candidate said at the end of an interview: "I can clearly picture myself working together with you." After hearing that, I made a little fist pump in my mind. (lol) Efforts I Made for Recruitment PR This year, as part of recruitment PR initiatives, I led a speaking session at Japan Mobility Show 2025 , one of the largest mobility events in Japan. It was a project that involved stakeholders within the TOYOTA Group where KTC belongs, as well as people engaging in both real-world and IT domains. To be honest, it was the most challenging project I've ever experienced with such large number of tasks for the event coordination and high-level difficulty in handling them. (lol) Despite that, I really wanted to make the project a success—that is because I wanted to properly convey to the public our strength of taking on new things collaborating with real and IT areas. I also wanted to share the passion of our senior managers who readily agreed to work the project together. I wanted to deliver through live words the atmosphere in KTC and our passion that can't be conveyed through job postings alone. After the event, team members who had been cheering me on said, "That was really great!" and it made me so happy. When the video of the speaking session was released, employees from group companies who I work with on various tasks also gave us the following comments: "I watched your YouTube video!" "Great content!" "That was cool!" And the senior manager, who spoke at the event session, gave me these words: "The recruiting impact might come a bit later, but it'll definitely work for internal PR and KTC's self-branding." I was so incredibly happy but couldn’t find words to clearly express my feeling. (lol) Recruitment PR is a job to facilitate sharing information about the company's initiatives with future teammates. I want to be the bridge between them and our company. Myself working hard to take photos at the event venue By the way, here's the archived video of the speaking session I mentioned above! I hope you enjoy this 50-minute video packed full of passion♪ https://youtu.be/NXM2lyapia0?si=QiK5GP2XFtCh0c9c Recruiting Is Achieved through Teamwork to Build Future There's no single right answer in recruiting talents. Every time, I get lost, worry, or waver. (Honestly, I feel restless for so many days because I can’t often find any solutions for my concerns. lol) But there's one thing I'm sure about: Good recruiting can only come from good dialogue with candidates. At KTC, there are 5 recruiters including myself. Each of us is assigned as a dedicated recruiter for specific divisions. That's why we are able to communicate super closely with the division members on the team, sharing information about products and cultures in each division, as well as happy things and tough things in their work—we think through everything together. That's how I feel we're building recruiting as a team. I think this is truly something to be proud of. Finally, to All Reading This Article To all engineers:   I respect you. I mean that seriously.   The way you change the future with technology has always looked like magic to me 🪄 To everyone involved in product development:   I understand your dedication to seriously engaging in product development through constant communication and trials and errors to create a single value.   Those real stories always struck me so deeply. To my teammates in the Human Resources Group:   Thank you for always worrying alongside me while I'm running around all over the place!!   Let's keep running together!! (/・ω・)/ To everyone at KTC:   Thank you for always helping me!!   I'll contribute to making my beloved company even stronger with all my efforts as an employee working at the recruitment frontline!!! To everyone who read this article:   If anything resonated with you even a little,   I'd love to meet you somewhere—at an event, a casual interview, or anywhere else!! To Future Teammates We at KINTO Technologies are taking initiatives in building an organization focusing on internal product development from scratch, right in the middle of the transforming automotive industry. Opportunities to be part of such dynamism don't come so often. We're waiting for teammates who will create the future together🙌 That's all for a day in the life of a recruiter and PR person! Thank you so much for reading!
This article is the Day 13 entry for the KINTO Technologies Advent Calendar 2025 🎄 Introduction I'm yuki.n ( @yukidotnbysh ) from the Master Maintenance Tool Development Team in the KINTO Backend Development Group, KINTO Development Division, based in the Osaka Tech Lab. Our team develops management systems that integrate with various services. These systems serve not only as administrative tools but also as solutions to business issues. To address these challenges, our management systems cannot be simple CRUD applications. Each system and its business requirements bring various complexities. I believed Railway Oriented Programming would be effective for handling these complexities in our business logic, so I introduced it in a project. Based on this case study, I would like to share the benefits we gained and the issues we faced. What is Railway Oriented Programming? Railway Oriented Programming Railway Oriented Programming is an error handling approach in functional programming proposed by Scott Wlaschin, who runs F# for Fun and Profit and authored Domain Modeling Made Functional . Looking at the article with the same title posted on F# for Fun and Profit , it seemingly have been published at least as early as 2013. In Railway Oriented Programming, functions are compared to railways, with success and failure handling represented as two separate tracks. The following diagram shows multiple of these railways connected together. Each processing step functions as a switch: if successful, processing continues on the success track; if it fails, it switches to the failure track. Once on the failure track, subsequent processing never succeeds, and the error flows through to the end. Specifically, this involves chaining functions that return Result types through a pipeline. Why Did We Adopt Railway Oriented Programming? Our team already had experience developing with Rust, and we adopted it as the backend server development language for this project as well. We designed the project architecture, according to the Clean Architecture diagram—for convenience, simply hereinafter referred to as Clean Architecture. When we introduced Clean Architecture in past projects, we found that the processing in the Use Cases layer (as depicted in the circle diagram above) often results in an unnecessarily complex and clunky structure design. Even when we carved some processing as domain services to combine them into the Entities layer, the readability of the Use Cases layer still suffered. In this situation, I learned about Railway Oriented Programming, which led to its adoption. Railway Oriented Programming with Rust Overall Structure The Use Cases layer we implemented has roughly the following structure. #[derive(Debug, thiserror::Error)] pub enum CreateUserUseCaseError { // Error type definitions } pub trait UsesCreateUserUseCase { /// Workflow fn handle( &self, input: CreateUserInputData, ) -> impl Future< Output = Result<CreateUserOutputData, CreateUserUseCaseError>, > + Send; } pub trait CreateUserUseCase: // Dependencies ProvidesUserFactory + ProvidesUserRepository { } impl<T: CreateUserUseCase + Sync> UsesCreateUserUseCase for T { async fn handle( &self, input: CreateUserInputData, ) -> Result<CreateUserOutputData, CreateUserUseCaseError> { // Chain of functions defined in the railway module } } mod railway { type RailwayResult<T> = Result<T, super::CreateUserUseCaseError>; pub(super) fn validate_input(/* ... */) -> RailwayResult<(Email, UserName)> { /* ... */ } pub(super) async fn check_email_not_exists(/* ... */) -> RailwayResult<(Email, UserName)> { /* ... */ } pub(super) fn build_user(/* ... */) -> RailwayResult<User> { /* ... */ } pub(super) async fn save_user(/* ... */) -> RailwayResult<User> { /* ... */ } pub(super) fn end(/* ... */) -> CreateUserOutputData { /* ... */ } } We use the Cake Pattern introduced in Thinking About DI in Rust — Part 2: Organizing DI Approaches Using Rust (only in Japanese) (I will omit the details as this diverges from the main topic of this blog). We define functions in the railway module and combine them within the handle method of UsesCreateUserUseCase . (Note: In Domain Modeling Made Functional, the part corresponding to the handle method is called workflow, and the arguments are called commands. This article follows that convention.) Let's break down each of these elements. Error Type Definition #[derive(Debug, thiserror::Error)] pub enum CreateUserUseCaseError { // Error type definitions #[error("Email address already exists.")] AlreadyExistsEmail, #[error("Invalid email address.")] InvalidEmail, #[error("Invalid username.")] InvalidUserName, #[error("UserFactoryError")] UserFactoryError(#[from] UserFactoryError), #[error("UserRepositoryError")] UserRepositoryError(#[from] UserRepositoryError), } We always define one error type for each Use Case. In Rust, error types can be defined as Enums. While the standard approach requires implementing the std::error::Error trait, using the thiserror crate simplifies error type definitions. Additionally, when defining with the thiserror crate, setting the #[from] attribute implements the From trait, allowing automatic conversion to the target error type without explicit conversion when the corresponding error occurs. RailwayResult Type mod railway { // Result type specific to this use case type RailwayResult<T> = Result<T, CreateUserUseCaseError>; } Since defining Use Case-specific errors for all functions would be cumbersome, we define a RailwayResult type alias so we only need to specify the return value. railway Module mod railway { /// Validates input values and converts them to value objects. pub(super) fn validate_input( input: CreateUserInputData, ) -> RailwayResult<(Email, UserName)> { let email = Email::try_from(input.email) .map_err(|_| CreateUserUseCaseError::InvalidEmail)?; let name = UserName::try_from(input.name) .map_err(|_| CreateUserUseCaseError::InvalidUserName)?; Ok((email, name)) } /// Confirms that the email address does not already exist. pub(super) async fn check_email_not_exists( (email, name): (Email, UserName), impl_repository: &impl UsesUserRepository, ) -> RailwayResult<(Email, UserName)> { impl_repository .find_by_email(&email) .await .map_err(CreateUserUseCaseError::UserRepositoryError)? .map_or(Ok((email, name)), |_| Err(CreateUserUseCaseError::AlreadyExistsEmail)) } /// Creates a new user. pub(super) fn build_user( (email, name): (Email, UserName), impl_factory: &impl UsesUserFactory, ) -> RailwayResult<User> { impl_factory .build(UserFactoryParams { email, name }) .map_err(CreateUserUseCaseError::UserFactoryError) } /// Saves the user. pub(super) async fn save_user( output: User, impl_repository: &impl UsesUserRepository, ) -> RailwayResult<User> { impl_repository .save(output) .await .map_err(CreateUserUseCaseError::UserRepositoryError) } /// Returns the result and terminates processing. pub(super) fn end( output: User, ) -> CreateUserOutputData { CreateUserOutputData { user: output.into(), } } } We create a module called railway and define the functions that form the tracks within it. This is not a Railway Oriented Programming convention but simply a guide we use for easier identification. In the code for this blog, we assume the following process flows: Validate input values (email address and username) Check email address existence Create User entity Save User entity Convert the saved User entity to a DTO for passing to the upper layer, and end the process Since the return value of the previous function is set as the input value for the next function, the first argument is named output . However, when output is a tuple, we destructure it from the start. This is because handling tuples as-is causes issues with variable ownership. Ideally, only the previous value should be set as the input for the next function, but we determined that the drawbacks outweighed the benefits—such as needing to pass unnecessary values as if through a bucket brigade. That is the reason we adopted a rule allowing new input values to be passed to each function. Overall Workflow The original programming convention uses F#, but Railway Oriented Programming is applicable in any language (or with libraries that supplement it) that has the concept of Result or Either types and the ability to compose functions. Fortunately, Rust comes standard with the following features essential for implementing Railway Oriented Programming, in addition to the Result type: ? operator: Expresses stopping processing when an error occurs map and and_then functions: Function composition By combining these, you can build a pipeline as follows: impl<T: CreateUserUseCase + Sync> UsesCreateUserUseCase for T { async fn handle( &self, input: CreateUserInputData, ) -> Result<CreateUserOutputData, CreateUserUseCaseError> { railway::validate_input(input) .map(|output| { railway::check_email_not_exists(output, self.user_repository()) })? .await .and_then(|output| railway::build_user(output, self.user_factory())) .map(|output| railway::save_user(output, self.user_repository()))? .await .map(railway::end) } } Benefits I Experienced in Practice The following are the benefits I experienced from practicing Railway Oriented Programming. Processing Flow Became Clear, Making Feature Addition Easier Since the workflow contents are connected through a pipeline, you can understand at a glance what processing is being performed. Of course, complex specifications inevitably lead to longer workflows, but even so, tracking the function flow helps us to roughly identify where and what is happening. With each process in the workflow extracted into functions, the scope of each process and its variables also became clear. This helped us add features simply by inserting new functions and modify them by changing the relevant function, which enhanced the system maintainability. Processing Input/Output Can Now Be Expressed Through Types I don't think this is a direct effect of Railway Oriented Programming, but we can now check by type level what data each function's arguments and return values represent. As compile errors can prevent type mistakes, we are able to avoid problems where incorrect values are passed during processing. Simplified Unit Test Scenarios Since implementing all success and failure tests for workflows was extremely labor-intensive and time-consuming, we adopted an approach of thoroughly testing individual railway functions, then only testing the happy path for the workflows. There may be controversies about whether tests for private functions are necessary, but I personally felt it was helpful to test each function in the railway module. So far, I haven't experienced any major problems with this approach. Additionally, as a secondary effect, when features are added, we can confirm there are no issues by adding tests for those functions and ensuring existing tests pass, which I think was beneficial. Issues I Experienced in Practice While gaining benefits from practice, we also faced some issues. Railway Oriented Programming Takes Some Getting Used To For those already familiar with functional languages, this approach probably doesn't feel unusual, but of course there are team members, including myself, who are not. The approach implementation is difficult until you get used to the style of writing. In fact, I struggled quite a bit when examining whether Railway Oriented Programming could be implemented using Rust. Currently, AI has significantly lowered the technical barriers for the implementation, but we humans still need to understand Railway Oriented Programming at some level to determine whether the outcomes are appropriately generated. That’s where supporting team members come in. In practice, the process of reviewing outcomes placed a significant burden on us in the early development phase of this project. Depending on the project's situation and conditions—such as development scale and deadlines—we suggest that you seek another solution instead of Railway Oriented Programming. We May Face fatal runtime error: stack overflow Depending on what kind of process is executed, Stack Overflow errors may occur at runtime. It is particularly troublesome because the error is not detected as a compile error, and you cannot determine which specific location contains issues just by searching around the source code. To find the error cause, you can use rust-lldb to check the stack trace and identify the code where the Stack Overflow error occurred. # Start binary with LLDB rust-lldb target/debug/your-bin # Execute run # Check backtrace when Stack Overflow occurs thread backtrace all When we address issues that are difficult to solve using a method chaining with map and and_then , we take an alternative solution to stop the method and write the processing line by line instead. This is the safest and easiest way to overcome tough issues. async fn handle(&self, input: InputData) -> Result<OutputData, UseCaseError> { railway::begin(self.uow()).await?; let output = railway::validate_email(&input.email)?; let output = railway::authenticate(output, input.password, self.authenticator()).await?; let output = railway::update_last_access(output, self.user_repository()).await?; let output = railway::commit(output, self.uow()).await?; railway::end(output) } The above solution isn't bad in itself, but it eliminates the pipeline through method chaining, creating the risk that we can write codes on a no-holds-barred basis. So, I think it's safest to only switch to this format when we hardly solve issues. As another option, you can expand the stack area by adding a value to the RUST_MIN_STACK variables. However, this merely postpones the issue and may cause the recurrence of the Stack Overflow errors. Therefore, I don’t recommend this solution. In my case, the error occurred in debug builds in the meantime when I executed asynchronous processing within functions defined in the railway module. async/await is syntactic sugar for the Future type, but, according to rust-lang/rust#132050 , the state held by the Future type is expanded to the stack area at runtime, which causes Stack Overflow errors at the execution of many async functions. In this case, I was able to avoid the error by storing the Future type data I wanted to simultaneously process into the Vec type data (because Vec type values are stored in the heap ). Increase in Codes in Return for Clarified Processing Flow When introducing Railway Oriented Programming in Rust, you end up connecting each function with map and and_then . Additionally, you need to define each of those functions, so the overall code volume increases compared to the one when you usually write codes. For example, if Railway Oriented Programming were not applied, the handle method would look like as follows: impl<T: CreateUserUseCase + Sync> UsesCreateUserUseCase for T { async fn handle( &self, input: CreateUserInputData, ) -> Result<CreateUserOutputData, CreateUserUseCaseError> { // Input validation let email = Email::try_from(input.email) .map_err(|_| CreateUserUseCaseError::InvalidEmail)?; let name = UserName::try_from(input.name) .map_err(|_| CreateUserUseCaseError::InvalidUserName)?; // Email duplication check let existing_user = self .user_repository() .find_by_email(&email) .await .map_err(CreateUserUseCaseError::UserRepositoryError)?; if existing_user.is_some() { return Err(CreateUserUseCaseError::AlreadyExistsEmail); } // User creation let user = self .user_factory() .build(UserFactoryParams { email, name }) .map_err(CreateUserUseCaseError::UserFactoryError)?; // Saving user let saved_user = self .user_repository() .save(user) .await .map_err(CreateUserUseCaseError::UserRepositoryError)?; // Result conversion Ok(CreateUserOutputData { user: saved_user.into(), }) } } Without functions, the implementation would be within the handle method (or with some functions partially extracted). Therefore, depending on the case, this approach might be simpler. So for applications with simple processing and mostly branching, it may be safer to unnecessarily adopt Railway Oriented Programming. P.S.: Where’s the Repository Pattern? While not directly related to the main topic of this blog, Domain Modeling Made Functional addresses the repository pattern in a section named “Where’s the Repository Pattern?” The book states the pattern in the functional approach as follows: “...when we model everything as functions and push persistence to the edges, then the Repository pattern is no longer needed.” However, since I couldn't fully grasp the intent and method behind this, we adopted the repository pattern for the code and our project described in this blog. Conclusion This concludes my explanation about practicing Railway Oriented Programming in Rust. Rust is an extremely expressive language with various features, and I feel that adopting Railway Oriented Programming can enhance it further. If you consider adopting Railway Oriented Programming in Rust, I hope this article can serve you as a helpful reference.
この記事は KINTOテクノロジーズアドベントカレンダー2025 の 13 日目の記事です🎄 はじめに KINTO開発部 KINTOバックエンド開発G マスターメンテナンスツール開発チーム・Osaka Tech Lab 所属の yuki.n( @yukidotnbysh )です。 わたしたちのチームでは各サービスと連携する管理システムを開発しています。これらは管理システムであると同時に、業務課題を解決するためのものでもあります。 そのため管理システムと言えども単純な CRUD システムというわけにはいかず、開発するシステムや業務によって様々複雑な課題が発生します。これらをビジネスロジックに落とし込むにあたって Railway Oriented Programming が効果的ではないかと考え、実際のプロジェクトで導入しました。その事例をもとにどのようなメリット・見えてきた課題があったのかをご紹介したいと思います。 Railway Oriented Programming について Railway Oriented Programming Railway Oriented Programming とは F# for Fun and Profit の運営や「 Domain Modeling Made Functional(関数型ドメインモデリング) 」の作者である Scott Wlaschin 氏が提唱した、関数型プログラミングにおけるエラーハンドリングの手法です。日本語では「鉄道指向プログラミング」と呼ばれています。 F# for Fun and Profit に投稿された 同じタイトルの記事 を見ると、少なくとも 2013 年には公開されていたようです。 Railway Oriented Programming では、関数を「線路(Railway)」に例え、正常系の処理と異常系の処理を 2 本の線路として表現します。 この「線路」を複数つなぎ合わせたのが以下のイメージ図です。 各処理ステップは「スイッチ」として機能し、成功すれば正常系の処理(線路)を進み、失敗すれば異常系の処理(線路)に切り替わります。一度異常系に入ると、以降の処理では成功することはなく、エラーとして最後まで流れていきます。 具体的には Result 型を返す関数をパイプラインで次々とつなぎ合わせていくイメージです。 Railway Oriented Programming を取り入れた理由 もともとわたしたちのチームでは Rust の開発実績があり、このプロジェクトでもバックエンドサーバーの開発言語として Rust を採用しています。 アーキテクチャとしては「The Clean Architecture」の図を参考にしています(以後、便宜的にあえて「Clean Architecture」と書きます)。 過去のプロジェクトで Clean Architecture を導入した時、上の図で描かれている「Use Cases」層の処理が複雑かつ肥大化していく傾向にあり、一部処理をドメインサービスとして「Entities」層へ切り出したとしても、やはり Use Cases 層の可読性が落ちてしまうという課題がありました。 そんな中で Railway Oriented Programming の存在を知り、導入することになりました。 Rust での Railway Oriented Programming 全体の構造 わたしたちが実装した Use Cases 層は概ね以下のような構造になっています。 #[derive(Debug, thiserror::Error)] pub enum CreateUserUseCaseError { // エラー型の定義 } pub trait UsesCreateUserUseCase { /// Workflow fn handle( &self, input: CreateUserInputData, ) -> impl Future< Output = Result<CreateUserOutputData, CreateUserUseCaseError>, > + Send; } pub trait CreateUserUseCase: // 依存関係 ProvidesUserFactory + ProvidesUserRepository { } impl<T: CreateUserUseCase + Sync> UsesCreateUserUseCase for T { async fn handle( &self, input: CreateUserInputData, ) -> Result<CreateUserOutputData, CreateUserUseCaseError> { // railway モジュールで定義した関数のチェーン } } mod railway { type RailwayResult<T> = Result<T, super::CreateUserUseCaseError>; pub(super) fn validate_input(/* ... */) -> RailwayResult<(Email, UserName)> { /* ... */ } pub(super) async fn check_email_not_exists(/* ... */) -> RailwayResult<(Email, UserName)> { /* ... */ } pub(super) fn build_user(/* ... */) -> RailwayResult<User> { /* ... */ } pub(super) async fn save_user(/* ... */) -> RailwayResult<User> { /* ... */ } pub(super) fn end(/* ... */) -> CreateUserOutputData { /* ... */ } } 「 Rust の DI を考える –– Part 2: Rust における DI の手法の整理 」で紹介されている Cake Pattern を用いています(本記事の本筋とは逸れるため詳細は割愛します)。 railway モジュールに関数を定義し、それらを UsesCreateUserUseCase の handle メソッド内で結合する、という形です。 (なお、「関数型ドメインモデリング」では handle メソッドにあたる部分を「ワークフロー」、引数は「コマンド」と表現されています。本記事でもこれに倣います) これらの要素をひとつずつ分解していきます。 エラー型の定義 #[derive(Debug, thiserror::Error)] pub enum CreateUserUseCaseError { // エラー型の定義 #[error("メールアドレスが既に存在します。")] AlreadyExistsEmail, #[error("無効なメールアドレスです。")] InvalidEmail, #[error("無効なユーザー名です。")] InvalidUserName, #[error("UserFactoryError")] UserFactoryError(#[from] UserFactoryError), #[error("UserRepositoryError")] UserRepositoryError(#[from] UserRepositoryError), } Use Case ひとつに対し、エラー型を必ずひとつ定義する形で運用しています。 Rust ではエラー型を Enum で定義することができます。標準のままだと std::error::Error トレイトを実装する必要があるのですが、 thiserror クレートを使うことでエラー型の定義を簡略化できます。 また thiserror クレートで定義した場合、 #[from] アトリビュートを設定することで From トレイトが実装されるので、該当エラーが発生した時に明示的に変換をせずとも、自動的に目的のエラー型へ変換できるようになります。 RailwayResult 型 mod railway { // このユースケース専用のResult型 type RailwayResult<T> = Result<T, CreateUserUseCaseError>; } Use Case 専用のエラーをすべての関数に定義するのは大変なので、 RailwayResult 型という型エイリアスを定義して、戻り値だけ設定するようにしています。 railway モジュール mod railway { /// 入力値を検証し、値オブジェクトに変換します。 pub(super) fn validate_input( input: CreateUserInputData, ) -> RailwayResult<(Email, UserName)> { let email = Email::try_from(input.email) .map_err(|_| CreateUserUseCaseError::InvalidEmail)?; let name = UserName::try_from(input.name) .map_err(|_| CreateUserUseCaseError::InvalidUserName)?; Ok((email, name)) } /// メールアドレスが存在していないことを確認します。 pub(super) async fn check_email_not_exists( (email, name): (Email, UserName), impl_repository: &impl UsesUserRepository, ) -> RailwayResult<(Email, UserName)> { impl_repository .find_by_email(&email) .await .map_err(CreateUserUseCaseError::UserRepositoryError)? .map_or(Ok((email, name)), |_| Err(CreateUserUseCaseError::AlreadyExistsEmail)) } /// ユーザーを新規作成します。 pub(super) fn build_user( (email, name): (Email, UserName), impl_factory: &impl UsesUserFactory, ) -> RailwayResult<User> { impl_factory .build(UserFactoryParams { email, name }) .map_err(CreateUserUseCaseError::UserFactoryError) } /// ユーザーを保存します。 pub(super) async fn save_user( output: User, impl_repository: &impl UsesUserRepository, ) -> RailwayResult<User> { impl_repository .save(output) .await .map_err(CreateUserUseCaseError::UserRepositoryError) } /// 戻り値を返し、処理を終了します。 pub(super) fn end( output: User, ) -> CreateUserOutputData { CreateUserOutputData { user: output.into(), } } } railway というモジュールを作り、その中に「線路」となる関数群を定義していきます。 これは Railway Oriented Programming の流儀ではなく、単純にわたしたちが確認しやすいように目印として設けています。 この記事のコードの場合では以下の流れを想定しています。 入力値(メールアドレス・ユーザー名)の検証 メールアドレスの存在チェック User エンティティの生成 User エンティティの保存 保存した User エンティティを上位層に渡すための DTO に変換し、終了 前回の関数の戻り値が次の関数の入力値になるため、第一引数は output と命名しています。 ただし output がタプルだった場合は始めから展開しています。これはタプルのままだと変数の所有権の問題で取り扱いが面倒なためです。 基本的には前回の値だけがそのまま次の関数の入力値になることが望ましいとは思うのですが、バケツリレーのように不要な値まで渡し続ける必要が発生するなどデメリットの方が多いと判断し、各関数で新たな入力値を渡しても良いというルールにしています。 ワークフロー全体 原典では F# が使われていますが、Result 型や Either 型の概念があり、かつ関数を合成する機能がある言語(またはそれを補完するライブラリなど)であれば Railway Oriented Programming の導入は可能です。 Rust では幸い、Result 型以外にも Railway Oriented Programming を実現するのに欠かせない以下の機能が標準で備わっています。 ? 演算子:エラー発生時の処理停止を表現 map ・ and_then 関数:関数の合成 これらを組み合わせることで以下のようにパイプラインを構築することができます。 impl<T: CreateUserUseCase + Sync> UsesCreateUserUseCase for T { async fn handle( &self, input: CreateUserInputData, ) -> Result<CreateUserOutputData, CreateUserUseCaseError> { railway::validate_input(input) .map(|output| { railway::check_email_not_exists(output, self.user_repository()) })? .await .and_then(|output| railway::build_user(output, self.user_factory())) .map(|output| railway::save_user(output, self.user_repository()))? .await .map(railway::end) } } 実践して感じたメリット 以下、Railway Oriented Programming を実践して感じたメリットです。 処理の流れが明確になり、機能追加がしやすくなった ワークフローの中身がパイプラインで繋がっているので、どういう処理が行われているのかは一目である程度わかるようになりました。 もちろん複雑な仕様であればワークフローが長くなることは避けられませんが、それでも関数の流れを追えば、どこで何が行われているのかはだいたいの当たりをつけられるようになりました。 ワークフロー内の各処理も関数に切り出されていることで、それぞれの処理・変数のスコープも明確になりました。 このおかげで機能追加の場合は新たに関数を差し込むだけでよく、変更の場合は該当の関数のみ修正すれば良くなり、保守性も向上したように感じます。 処理の入出力を型で表現できるようになった これは Railway Oriented Programming と直接結びつく効果ではないと思いますが、各関数の引数・戻り値が何のデータであるかを型レベルでチェックできるようになりました。 コンパイルエラーで型の誤りを防げるようになり、処理途中で誤った値が渡ってしまうといった問題を回避できるようになりました。 単体テストが書きやすくなった ワークフローに対し正常系・異常系すべてのテストを実装するのは非常に大変だったため、各 railway 関数それぞれをしっかりテストして、ワークフローのテストではハッピーパスを通すというやり方を取っています。 Private な関数のテストコードが必要かどうかの是非はあると思いますが、それでも railway モジュールの各関数をテストできるのは個人的にメリットと感じました。いまのところは大きな問題も感じていません。 また、副次的効果として、機能追加があった場合でもその関数分のテストを追加し、既存のテストがパスすれば問題ないことが確認できるので、この点は良かったと思います。 実践して感じた課題 実践してメリットが得られた反面、やはりいくつか課題もありました。 Railway Oriented Programming の慣れが必要 普段から関数型言語に慣れている方であればそれほど違和感ない手法と思うのですが、もちろんわたし含めてそうでないメンバーもいます。そのため、この書き方に慣れるまではどうしても実装が難しくなりますし、実際、わたしも Rust で Railway Oriented Programming が実装できるか調べていた時はかなり苦戦しました。 現在は AI のおかげでかなり難易度は下がりましたが、できあがったものが適切な内容かどうかはやはりある程度の理解が必要です。そのため、メンバーに対してのフォローがどうしても必要になります。 実際のところ、このプロジェクトでも開発初期はどうしてもレビュー負荷が大きくなりました。そのため、開発規模や納期など、プロジェクトの状況・条件によっては Railway Oriented Programming の採用を見送ることも検討した方が良いかもしれません。 fatal runtime error: stack overflow が発生する場合がある 実装内容によっては実行時に Stack Overflow エラーが発生する場合があります。 コンパイルエラーとして検出されないのが非常に厄介で、かつ具体的にどの箇所が問題なのか、ソースコードを見るだけでは判断がつきません。 原因の探し方ですが、rust-lldb を使ってスタックトレースを確認することで、Stack Overflow エラーが発生したコードを特定することができます。 # LLDB でバイナリを起動する rust-lldb target/debug/your-bin # 実行 run # Stack Overflow が発生したらバックトレースを確認 thread backtrace all 解決が難しい場合の別案として、もっとも安全かつかんたんな解決策は map や and_then によるメソッドチェーンをやめ、1 行ずつ処理を書いていく形です。 async fn handle(&self, input: InputData) -> Result<OutputData, UseCaseError> { railway::begin(self.uow()).await?; let output = railway::validate_email(&input.email)?; let output = railway::authenticate(output, input.password, self.authenticator()).await?; let output = railway::update_last_access(output, self.user_repository()).await?; let output = railway::commit(output, self.uow()).await?; railway::end(output) } これはこれで悪くありませんが、メソッドチェーンによるパイプラインがなくなり、どうにでも書けてしまうという問題が発生します。なので本当にどうしても解決が難しい場合のみこの形式に置き換えるというのが安全と思います。 なお、他の方法としては RUST_MIN_STACK 変数の値を追加することでスタック領域を拡張できます。しかしこれは問題を先送りにしているだけで、いつの日か Stack Overflow エラーが再発しかねません。そのため、この解決方法はあまりおすすめできません。 ちなみにわたしの事例では、デバッグビルドの時に railway モジュール内に定義した関数の中で、非同期処理を並列実行する場合に起こるケースがありました。 async/await は Future 型の糖衣構文ですが、 rust-lang/rust#132050 を見ると実行時に Future 型の持つ状態がスタック領域へ展開されるため、多くの async 関数を実行する時に Stack Overflow エラーを引き起こしてしまうようです。 このケースでは、並列で処理したい Future 型のデータを Vec 型のデータへ格納することで対処できました( Vec 型の値はヒープ領域に格納される ためです)。 処理フローが明確になる代わりにコードは増える Rust で Railway Oriented Programming を導入すると、各関数を map と and_then でつなぎ合わせていく形になります。それに加えて、それぞれの関数を定義していく必要があるので、ふつうに書くより全体のコード量は増えます。 たとえば Railway Oriented Programming を適用しなかった場合の handle メソッドは impl<T: CreateUserUseCase + Sync> UsesCreateUserUseCase for T { async fn handle( &self, input: CreateUserInputData, ) -> Result<CreateUserOutputData, CreateUserUseCaseError> { // 入力値の検証 let email = Email::try_from(input.email) .map_err(|_| CreateUserUseCaseError::InvalidEmail)?; let name = UserName::try_from(input.name) .map_err(|_| CreateUserUseCaseError::InvalidUserName)?; // メールアドレスの重複チェック let existing_user = self .user_repository() .find_by_email(&email) .await .map_err(CreateUserUseCaseError::UserRepositoryError)?; if existing_user.is_some() { return Err(CreateUserUseCaseError::AlreadyExistsEmail); } // ユーザーの作成 let user = self .user_factory() .build(UserFactoryParams { email, name }) .map_err(CreateUserUseCaseError::UserFactoryError)?; // ユーザーの保存 let saved_user = self .user_repository() .save(user) .await .map_err(CreateUserUseCaseError::UserRepositoryError)?; // 結果の変換 Ok(CreateUserOutputData { user: saved_user.into(), }) } } となり、関数がなく代わりに handle メソッドの中(または部分的に関数を切り出すなど)で実装することになります。このため、場合によってはこの方がシンプルなこともあると思います。 なので、かんたんな処理・分岐がほとんどといったアプリケーションの場合、無理に Railway Oriented Programming を採用しない方が無難かもしれません。 余談:「リポジトリパターンはどこにある?」 この記事の本筋とは直接関係しませんが、「関数型ドメインモデリング」では「リポジトリパターンはどこにある?」という題でリポジトリパターンについて言及されていて、関数型のアプローチではリポジトリパターンを すべてを関数としてモデル化し、永続化を端に追いやることで、リポジトリパターンは必要なくなります。 と書かれています。 しかしわたしがこのことについての意図・方法を読み切れなかったため、この記事のコードおよびわたしたちのプロジェクトではリポジトリパターンを採用しています。 おわりに 以上、Railway Oriented Programming を Rust で実践した内容についての紹介でした。 Rust は非常に表現力が豊かで様々な機能を持つ言語ですが、Railway Oriented Programming を採用することでより強化できるのではないかと感じています。 もし同じように Rust で Railway Oriented Programming の採用を検討している方がいらっしゃいましたら、この記事が少しでも参考になれば幸いです。
Introduction This article is Day 12 of the KINTO Technologies Advent Calendar 2025 . Hello. I'm Matsuo from the Cloud Infrastructure Group. While this wasn't announced at AWS re:Invent, there was an update that I personally found exciting, so I'd like to share it. It's the automatic management feature for Service Quotas. In October 2025, the automatic management settings feature became generally available, enabling notifications when Service Quotas limits are approaching. Then recently, the automatic adjustment mode that was announced at GA was added. Previously, implementing quota monitoring required building a complex architecture yourself, but with this feature, you can set up quota monitoring and automatic adjustment just by clicking through the console. And it's free. However, I should mention upfront that automatic adjustment doesn't support all quotas. In this article, I'll share the specifications and constraints I discovered through actual testing! Update Timeline Date Content October 2025 Automatic management feature added. At launch, only Notify Only mode was GA. Automatic adjustment mode was announced November 2025 Notify and Adjust mode was added Official announcements: AWS Service Quotas の自動クォータ管理の一般提供を開始 - AWS AWS Service Quotas now supports automatic quota adjustment What Makes This Great Before (Traditional Method) To implement quota monitoring, you needed an architecture like this: https://aws.amazon.com/solutions/implementations/quota-monitor/ Source: AWS Solutions Library Monitor metrics with CloudWatch Alarms Lambda functions to call Service Quotas API and send quota increase requests EventBridge trigger configuration SNS for notifications Amazon DynamoDB for managing monitored quotas This resulted in quite a complex architecture that was difficult to build and maintain. After (Automatic Management Feature) Setup complete with just a few clicks in the console Automatic notifications at 80%/95% Automatic Adjustment mode automatically sends quota increase requests No charges for resources that were previously needed for quota monitoring Compared to the previous method, there's no complex configuration. It seems much easier to adopt. Before After Setup effort Required building Lambda/EventBridge/SNS/DynamoDB etc. Just a few clicks in the console Notification timing Set thresholds yourself Automatic notifications at 80%/95% (fixed) Quota adjustment Self-implemented with Lambda etc. Handled by automatic adjustment mode Cost Charges for each resource Free Feature Specifications Notification Timing According to the official documentation , notifications are sent at the following thresholds: When 80% utilization is reached When 95% utilization is reached Important: These thresholds are fixed. When configuring in the console, I thought "Hmm, where do I set the threshold?" but it turns out it's not configurable by design. Customizations like "I want notifications at 70%" aren't possible, so you'd still need to use CloudWatch Alarms for that. Automatic Management Modes Mode Description Notify Only (NotifyOnly) Sends notifications at 80% / 95% Notify and Adjust (NotifyAndAdjust) In addition to notifications, automatically sends quota increase requests Notification Destinations It's integrated with AWS User Notifications, and you can configure the following notification destinations: Email (via SES; events from unsupported regions are sent via Virginia) AWS Console Mobile Application (requires prior app installation and push notification enablement) Chat channels (delivered to Slack/Teams via Amazon Q Developer; requires prior chat client configuration) Pricing It's free to use. There are no additional charges for the automatic management feature itself. AWS User Notifications used for notifications is also free, but if you use SES, mobile push, or Amazon Q Developer behind the scenes, or if you set up custom monitoring with CloudWatch Alarms separately from the automatic management feature, additional charges may apply. Configuration Method Note : As of November 2025, this feature is not yet supported in Terraform Console Configuration Open the Service Quotas console Select Automatic management from the left menu Click Start automatic management Select the automatic management mode (Notify Only or Notify and Adjust) Configure notification settings (optional) Configure exception settings (optional) Review and submit Super easy. CLI Configuration Here's an example configuration for the us-west-2 (Oregon) region. # When specifying User Notifications destination and automatic adjustment aws service-quotas start-auto-management \ --opt-in-level ACCOUNT \ --opt-in-type NotifyAndAdjust \ --notification-arn arn:aws:notifications::xxxxxxxxxxxx:configuration/xxxxx \ --region us-west-2 Official documentation Note : Configuration is required for each region. Setting it in the Oregon region doesn't apply to the Tokyo region. If you want to configure all regions via CLI, you'll need to write a script or similar. Internal Mechanism (Event Pattern) When you configure automatic management, internally an event pattern like the following is set as a detailed filter in AWS User Notifications: { "source": ["aws.health"], "detail-type": ["AWS Health Event"], "detail": { "service": ["SERVICEQUOTAS"], "eventTypeCode": [ "AWS_SERVICEQUOTAS_THRESHOLD_BREACH", "AWS_SERVICEQUOTAS_INCREASE_REQUEST_FAILED", "AWS_SERVICEQUOTAS_APPROACHING_THRESHOLD" ], "eventTypeCategory": ["accountNotification"] } } Meaning of each event type ( official documentation ): eventTypeCode Meaning AWS_SERVICEQUOTAS_APPROACHING_THRESHOLD An adjustable quota is approaching the threshold. In automatic adjustment mode, a quota increase request is sent here AWS_SERVICEQUOTAS_THRESHOLD_BREACH A non-adjustable quota has exceeded the threshold. Since the quota cannot be increased, you need to optimize usage AWS_SERVICEQUOTAS_INCREASE_REQUEST_FAILED The quota increase request failed Actual Testing Test Environment Region: us-west-2 (Oregon) Automatic management mode: Notify and Adjust Required Permissions The permissions required to use the automatic management feature and view permissions are as follows. Permissions required to use: ServiceQuotasFullAccess AWSHealthFullAccess Permissions required to view: AWSHealthFullAccess Checking Supported Quotas I checked from View supported quotas in the console, but perhaps because it was just after release, the coverage was more limited than I expected. I hope the supported resources will expand in the future. Examples of supported services: AWS Systems Manager Amazon EC2 WAF (Regional only) ELB Lambda Route53 IAM Examples of unsupported services: VPC API Gateway EventBridge Amazon Simple Email Service (SES) For global services like Route53 and IAM, it seems only notifications are available and automatic adjustment is not supported Verifying Automatic Adjustment Behavior I tested with AWS WAF's Maximum regex pattern sets per account in WAF for regional. This quota has a default value of 10, so creating 8 would reach 80%. Test Procedure 1. Preparation First, configure automatic management in Service Quotas. Enable automatic management in Service Quotas with Notify and Adjust mode (I didn't capture the screen when setting up in the Oregon region, so this is the settings screen from the Virginia region) Move to notification settings. Here you configure AWS User Notifications. This time, I set up Amazon Q Developer to send notifications to a Slack channel. Note : You can select the event source region, but since you can only receive events from regions where automatic management is enabled, you need to configure automatic management for each region you want to monitor (it's a bit confusing because automatic management and AWS User Notifications are separate settings) You can select services to exclude from automatic management, but this time I created it without any settings 2. Create Regex Pattern Sets Next, create regex pattern sets to trigger the threshold. WAF console -> Regex pattern sets -> Create regex pattern set Region: us-west-2 (Oregon) *Select Regional Create 8 with arbitrary names 3. Check Utilization Service Quotas -> AWS WAF -> Maximum regex pattern sets per account in WAF for regional Confirmed that utilization was at 80% 4. Wait for Notification/Automatic Adjustment Wait a few minutes... Test Results Time until notification/automatic adjustment: Not confirmed precisely, but completed in a few minutes Quota value: Changed from 10 to 11. You can't specify the quota value after automatic adjustment, but it seems to update to a quota that falls below 80%. Slack notifications are hard to read Newline codes ( \n ) are displayed as-is, making long text appear as one block. Also, the notification body doesn't include specific information about which quota is approaching the threshold, so you need to check the Affected resources tab in the AWS Health Dashboard via the link attached to the notification. As a notification, you can tell something is approaching the threshold, but it takes extra effort to check the details. Notes and Constraints 1. Limited Supported Quotas Honestly, this is the biggest constraint I felt at the moment. It's disappointing that quotas for basic services like VPC and SES aren't supported. Currently, automatic management of Service Quotas alone won't handle all quota-related issues. We'll have to wait for the supported quotas to expand. 2. Thresholds Cannot Be Customized The 80%/95% thresholds are fixed. Requirements like "I want early notifications at 50%" or "No notifications needed until 100%" cannot be accommodated. 3. AWS Organizations Support Not Implemented As of November 2025, bulk configuration at the Organizations level is not supported, so you need to configure each account individually. There's an --opt-in-level option in the CLI command, so I hope it will be supported eventually. 4. Automatic Adjustment Approval Is Not Guaranteed Automatic adjustment is merely a feature that automatically sends quota increase requests. Whether the request is approved by AWS is a separate matter, and it may be rejected. 5. Notifications/Automatic Increases May Take Time Right after the quota was raised to 11, I added 3 more regex patterns for a total of 11, bringing utilization to 100%. However, this time there was no notification and no automatic adjustment. But several hours later, I confirmed that automatic adjustment had occurred, so it seems that notifications and automatic adjustments may take time in some cases. Conclusion The automatic management feature for Service Quotas is personally a really great update that significantly lowers the barrier to quota monitoring. It's free to start and can be configured with just a few clicks from the console. There are still constraints like limited supported quotas and no IaC (Terraform) support, but I found that for supported quotas, it can actually reduce the effort required for quota expansion work. At our company, we also operate a custom-built quota management tool, and we plan to continue using it for quotas that aren't supported by the automatic management feature. I hope you found this article helpful.
はじめに この記事は KINTOテクノロジーズ Advent Calendar 2025 の12日目の記事です🎅🎄 こんにちは。クラウドインフラ所属の松尾です。 AWS re:Inventで発表された新機能ではないですが、 個人的に熱いと感じたアップデートがあったので紹介します。 Service Quotasの自動管理機能です。 2025年10月に「自動管理設定」機能がGAとなり、 Service Quotasの上限値が近づくと通知が飛ぶようになりました。 そして先日、GAのタイミングで予告されていた「自動調整」モードが追加。 これまでクォータ監視を実装しようとすると、複雑な構成を自前で用意する必要がありましたが、 この機能を使えばコンソールからポチポチするだけでクォータの監視から自動調整までやってくれます。 しかも無料です。 ただ、先に言っておくと自動調整について、「全部のクォータに対応しているわけではない」という制約があります。 この記事では、実際に検証してわかった仕様や制約を書いていきます! アップデートの経緯 日付 内容 2025年10月 自動管理機能の追加。追加時は「通知のみ」モードがGA。自動調整モードの予告あり 2025年11月 「通知と自動調整」モードが追加 公式アナウンス: AWS Service Quotas の自動クォータ管理の一般提供を開始 - AWS AWS Service Quotas now supports automatic quota adjustment 何が嬉しいのか Before(従来の方法) クォータ監視を実装するには、こんな構成が必要でした: https://aws.amazon.com/solutions/implementations/quota-monitor/ 出典: AWS Solutions Library CloudWatch Alarmsでメトリクスを監視 Lambda関数でService Quotas APIを叩いて上限緩和リクエストを送信 EventBridgeでトリガー設定 SNSで通知 Amazon DynamoDB 監視対象のクォータの管理 これだとかなり複雑な構成になるので構築、運用が大変でした。 After(自動管理機能) コンソールで数クリックで設定完了 80%/95%で自動通知 「自動調整」モードなら自動で上限緩和リクエストまで送ってくれる 今までクォータ監視で必要だったリソースの料金の発生はなし 従来までの方法と比べ、複雑な設定は無し。かなり導入がしやすそうです。 Before After 設定の手間 Lambda/EventBridge/SNS/DynamoDB等の構築が必要 コンソールで数クリック 通知タイミング 自分で閾値を設定 80%/95%で自動通知(固定) クォータ調整 Lambda等で自前実装 自動調整モードで対応 料金 各リソースの料金が発生 無料 機能の仕様 通知タイミング 公式ドキュメント によると、以下のタイミングで通知が送信されます: 80% 使用率に達した時 95% 使用率に達した時 重要:この閾値は固定です。 コンソールで設定するとき「あれ、閾値設定するところないな?」って思ったんですが、そもそも変更できない仕様でした。 「70%で通知が欲しい」みたいなカスタマイズはできないので、その場合は従来通りCloudWatch Alarmsを使う必要があります。 自動管理モード モード 説明 通知のみ(NotifyOnly) 80% / 95%で通知を送信 通知と自動調整(NotifyAndAdjust) 通知に加えて、自動でクォータ増加リクエストを送信 通知先 AWS User Notificationsと統合されていて、以下の通知先を設定できます: Eメール(SES経由、サポートされていないリージョンからのイベントはバージニア経由で送信) AWS コンソールモバイルアプリケーション(事前にアプリのインストールとプッシュ通知の有効化が必要) チャットチャネル(Amazon Q Developer経由でSlack/Teamsに配信、事前にチャットクライアントの設定が必要) 料金 無料で使用できます。 自動管理機能自体には追加料金はかかりません。 通知に使われるAWS User Notificationsも無料ですが、 裏で呼び出しているSES・モバイルプッシュ・Amazon Q Developerの使用や、 自動管理機能とは別にCloudWatch Alarmsで独自の監視を設定する場合は、別途料金がかかる場合があります。 設定方法 📝 補足 : 2025年11月時点では本機能は現在Terraformでは対応しておりません コンソールでの設定 Service Quotasコンソールを開く 左メニューから「自動管理」を選択 「自動管理を開始」をクリック 自動管理モードを選択(「通知のみ」または「通知と自動調整」) 通知設定を構成(オプション) 例外設定を構成(オプション) 確認して送信 めちゃくちゃ簡単。 CLIでの設定 以下はus-west-2(オレゴン)リージョンでの設定例です。 # User Notificationsの通知先と自動調整を指定する場合 aws service-quotas start-auto-management \ --opt-in-level ACCOUNT \ --opt-in-type NotifyAndAdjust \ --notification-arn arn:aws:notifications::xxxxxxxxxxxx:configuration/xxxxx \ --region us-west-2 公式ドキュメント ⚠️ 注意 : リージョンごとに設定が必要です。オレゴンリージョンで設定しても、東京リージョンには適用されません。 CLIで全リージョン設定する場合はスクリプトを組むなどの対応が必要です。 内部の仕組み(イベントパターン) 自動管理を設定すると、内部的にはAWS User Notificationsの詳細フィルターとして以下のようなイベントパターンが設定されます: { "source": ["aws.health"], "detail-type": ["AWS Health Event"], "detail": { "service": ["SERVICEQUOTAS"], "eventTypeCode": [ "AWS_SERVICEQUOTAS_THRESHOLD_BREACH", "AWS_SERVICEQUOTAS_INCREASE_REQUEST_FAILED", "AWS_SERVICEQUOTAS_APPROACHING_THRESHOLD" ], "eventTypeCategory": ["accountNotification"] } } 各イベントタイプの意味( 公式ドキュメント ): eventTypeCode 意味 AWS_SERVICEQUOTAS_APPROACHING_THRESHOLD 調整可能な クォータが閾値に近づいた。自動調整モードならここでクォータの引き上げリクエストが送信される AWS_SERVICEQUOTAS_THRESHOLD_BREACH 調整できない クォータが閾値を超過。クォータの引き上げできないので使用率を最適化する必要あり AWS_SERVICEQUOTAS_INCREASE_REQUEST_FAILED クォータの引き上げリクエストが失敗した 実際に検証してみた 検証環境 リージョン:us-west-2(オレゴン) 自動管理モード:通知と自動調整 必要な権限 自動管理機能を使用するために必要な権限、および閲覧権限は以下の通りです。 使用するために必要な権限 ServiceQuotasFullAccess AWSHealthFullAccess 閲覧するために必要な権限 AWSHealthFullAccess 対応クォータの確認 コンソールの「サポートされているクォータを表示」から確認してみたんですが、リリース直後だからか思ったより対応範囲が限定的でした。 今後、対応するリソースが増えることを期待したいです。 対応していたサービスの例: AWS Systems Manager Amazon EC2 WAF(Regionalのみ) ELB Lambda Route53 IAM 対応していなかったサービスの例: VPC API Gateway EventBridge Amazon Simple Email Service(SES) Route53やIAMなどのグローバルサービスの場合、通知のみできるようで自動調整には対応していない印象でした 自動調整の動作確認 AWS WAFの「Maximum regex pattern sets per account in WAF for regional」で検証してみました。 このクォータはデフォルト値が10なので、8個作成すれば80%に到達します。 検証手順 1. 事前準備 まずはService Quotasで自動管理の設定を行います。 Service Quotasの自動管理を「通知と自動調整」モードで有効化 (オレゴンリージョンで設定した際、キャプチャしてなかったのでバージニアリージョンでの設定画面になりますmm) 通知設定に移ります。ここではAWS User Notificationsの設定を行います。 今回はAmazon Q Developerを用意し、Slackチャンネルに通知するようにしました。 ⚠️ 注意 : イベントソースのリージョンを選択できますが、自動管理を有効にしているリージョンのイベントしか受け取れないため、 監視したいリージョンごとに自動管理の設定が必要です(自動管理とAWS User Notificationsは別設定だからちょっとややこしい) 自動管理の例外とするサービスを選択できますが、今回は何も設定しないまま作成 2. 正規表現パターンセットを作成 次に正規表現パターンセットを作成し、閾値に引っかかるようにします。 WAFコンソール → 正規表現パターンセット → 「Create regex pattern set」 リージョン:us-west-2(オレゴン)※Regionalを選択 適当な名前で8個作成 3. 使用率の確認 Service Quotas → AWS WAF → 「Maximum regex pattern sets per account in WAF for regional」 使用率が80%になっていることを確認しました 4. 通知/自動調整の発動を待つ 数分待機... 検証結果 通知/自動調整反映までの時間:正確には確認できていませんが、数分程度で完了 クォータ値:10→11に。自動調整後のクォータ値の指定はできませんが、80%を切るようなクォータに更新してくれそう? 通知に関して、Slack通知は見づらい 改行コード( \n )がそのまま表示されてしまい、長文が一塊になっています。 また、通知本文には「どのクォータが閾値に近づいたか」の具体的な情報が含まれておらず、 通知文に添付のリンクからAWS Health Dashboardの「Affected resources」タブを確認する必要があります。 通知としては「何か閾値に近づいた」ことはわかるが、詳細確認には一手間かかる印象です。 注意点・制約 1. 対応クォータが限定的 正直、今のところこれが一番大きな制約だなと感じました。 VPCやSESといった基本的なサービスのクォータが対応していないのは残念です。 現時点ではService Quotaの自動管理だけでは「クォータ周りの調整がすべて解決」とはならない。 対応クォータの拡大を今後待つしかないです。 2. 閾値のカスタマイズ不可 80%/95%の閾値は固定。「50%で早めに通知が欲しい」「100%になるまでは通知不要」みたいな要件には対応できません。 3. AWS Organizations対応は未実装 2025年11月時点では、Organizations単位での一括設定には対応していないため、 各アカウントで個別に設定する必要があります。 CLIコマンドには --opt-in-level というオプションがCLIであるのでいつか対応されることを期待したいです。 4. 自動調整の承認は保証されない 自動調整はあくまで「上限緩和リクエストを自動送信する」機能です。 リクエストがAWSに承認されるかどうかは別の話で、拒否される可能性もあります。 5. 通知・自動緩和までに時間がかかる場合がある クォータが11に上がった直後、正規表現パターンを3つ追加して合計11個にして使用率を100%にしてみました。 が、今度は通知もされず、自動調整もありませんでした。 しかし数時間後、自動調整されていることが確認できたことから、 場合によっては通知や自動調整までに時間がかかることがあるようです。 まとめ Service Quotasの自動管理機能は、クォータ監視のハードルを大きく下げてくれる個人的にはかなり良いアップデートです。 無料で始められて、コンソールから数クリックで設定できます。 対応クォータがまだ限定的だったり、IaC(Terraform)未対応だったりとまだまだ制約はありますが、 サポートされているクォータに関しては実際にクォータ拡張作業の工数を削減できることがわかりました。 弊社では独自実装のクォータ管理ツールも運用しており、 自動管理機能でサポートされていないクォータについては引き続きそちらで対応していく予定です。 以上、この記事が誰かの参考になれば幸いです。
この記事は KINTOテクノロジーズ Advent Calendar 2025 の12日目の記事です🎅🎄 はじめに KINTOテクノロジーズのFACTORY EC開発グループでバックエンドエンジニアをやっている、うえはら( @penpen_77777 )です。 技術書典19に、KINTOテクノロジーズの有志エンジニアによるサークル「KINTOテクノロジーズ執筆部」として参加してきました。 この記事では社内有志で技術書を作り上げるまでの道のりをご紹介します。 ちなみに今回作った新刊の紹介はこちらになります!無料なのでもしご興味があれば電子版のダウンロードよろしくお願いします。 https://blog.kinto-technologies.com/posts/2025-10-31-techbookfest19-announcement/ https://techbookfest.org/product/qCPrJpWLmKnLt7eWVd9zJ6 始まり 私はこれまでに技術本の執筆をしたことがあり、久々に技術本を書きたいなという思いがありました。 文章を他人に読んでもらうだけなら技術ブログや登壇でも十分なのですが、やっぱり自分の書いた文章が本になるのは感慨深いものがあります。 弊社では社員有志でサークルを組んで技術書を書くということがなかったため、今回チャレンジしてみることにしました。 仲間を作る サポートしてくれそうな人を見つける 技術書典へ参加する約半年前の6月くらいから動き出し始めました。 早めにサポートしてくれそうな人を見つけておくとタスクを進めておく上で非常に心強いです。 弊社には技術広報グループがあり社員の技術的な外部発信の相談に乗ってもらえます。 やり遂げることができたのも技術広報のおかげだなと思っています。本当に感謝しています。 執筆に興味がありそうな人を見つける 技術書典への参加は初めての試みということもあって、本当に参加者が集まるのかが不安なところでした。 いきなり全社に参加者募集の告知をして、参加者を集めるのはハードルが高いと感じていました。 そこで興味がありそうな人に声をかけてあらかじめ参加する確度の高い人を集めることにしました。 弊社ではSlack上でtimes(分報チャンネル)を活用する人も多く、気軽に自分の気持ちを表明できるのが良いところです。 技術書典への出展したい気持ちを匂わせることで、興味がありそうな人が誰か知ることにしました。 ここで5人くらい集まったので、最悪全社告知して集まらなくても企画ができそうだなと思い、安心して進めることができました。 告知する 全社で執筆者を募集できるよう簡単なスライドを作りました。 技術書典について、執筆に対するメリット等をまとめていて参加を訴求する内容となってます。 イベントの規模を紹介するのに公式から出ている協賛資料が参考になりました。 https://techbookfest.org/assets/tbf18/for-sponsors.pdf 印刷所の選定をする 物理本を作るため印刷所の選定が必要になります。 技術書典ではバックアップ印刷所が設定されており、このバックアップ印刷所に入稿することで印刷から会場への納品までやっていただける非常に便利な仕組みとなっています。 バックアップ印刷所には日光企画・ねこのしっぽがあるのですが、今回は日光企画さんを選択しました。 組版システムを選定する・設定を整える 組版システムとは印刷向けの見た目に変換するものを言います。 技術書向けの組版システムとしてはRe:VIEWがよく使用されます。 独自の「Re:VIEWフォーマット」で記述されたテキストファイルをRe:VIEWに通すことによって、電子書籍としてよく用いられるEPUB、PDFなどに変換されます。 紙面上のスタイルの設定と内容が分離していることで、執筆者が見た目を意識せずどんな内容の文章を書くかという本質的な営みに集中できるのがメリットです。 今回は組版システム^[読み方は「くみはん」らしいです。毎回そばんと読んでしまいます。 https://ja.wikipedia.org/wiki/%E7%B5%84%E7%89%88]として「Vivliostyle」を使用しました。 https://vivliostyle.org/ja/ VivliostyleはCSSを使って見た目を変えられるのが特徴で、フロントエンド技術に詳しい方であれば難なく使いこなせるかと思います。 ゼロから設定を整えるのは大変なので、今回はゆめみさんが配布されているテンプレートを活用させていただきました。 このようなテンプレートを配布いただき大変感謝しております。ありがとうございました! https://github.com/yumemi-inc/daigirin-template 上記のテンプレートを元に以下の修正を入れました タイトル・発行者・奥付けを今回の技術書向けの内容に修正 紙面サイズをB5へ変更^[ここでB5にはJIS B5とISO B5があることを知りました。同じB5でもサイズが異なるのでご注意を。] 目次の自動出力を有効化、うまく出力できていない箇所はテンプレートを調整 技術書典へサークル登録する 色々準備がある中で忘れそうにはなりますが、サークル参加申込は忘れずに行いましょう。 カレンダーに予定を入れたりする方が良いかもですね。 執筆者に書いてもらう 執筆者が執筆に困らないようガイドラインを作成し、共有しました。 全体的なスケジュールとそれぞれのフェーズでやること 執筆方法(Vivliostyle Flavored Markdown^[一般的なmarkdownを書籍特有の構造も表現できるよう拡張した記法。 https://vivliostyle.github.io/vfm/#/]の記法 , PDFのプレビュー方法等) 原稿管理 原稿管理はGitHubで実施し、mainブランチからそれぞれ執筆者ごとにブランチを切ってもらい執筆作業を行ってもらいました。 執筆者ごとにPRを出しておくと進捗確認ができて便利です。 Slackリストを活用する 書籍内でテーマが被らないようテーマが決まったらSlackのリストにまとめてもらうようにお願いしました。 他にも巻末に入れる自己紹介文や執筆状況等、自分で把握しておきたい内容を入れておくと見通しが良いです。 Confluenceで表を使って管理しても良かったのですが、個人的にはSlackの方が見る頻度が高いのとNotionのデータベースっぽく使えるSlackリストで管理していました。 表紙を作成してもらう 技術書の表紙を自分で作るか悩んでいたところ、参加者の一人から「クリエイティブ室のデザイナーさんに協力をお願いしてみては?」と提案がありました。 せっかくなら人を集めてワイワイしながら作っていこうということで、デザイナーが生成AIを駆使して表紙を作成する「生成AI × ライブペインティング」イベントの開催が決まりました。 今回の技術書を作るのに開催されたイベント「Vibe Painting Hour #01」 イベントでは5人のデザイナーの方に来ていただき、参加者が見守る中、1時間という制限時間で生成AIを駆使して表紙を作っていただきました。 「モビリティ感があって未来感のある表紙を作る」という、うえはらからの中身がふわふわした依頼にもかかわらず、最終的に上がってきた表紙の5案はどれもクオリティが高く1つに決めるのが勿体無いくらいでした! 参加者の多数決とうえはらの判断によって、今回の技術書の表紙が選ばれました。 ![表紙](/assets/blog/authors/uehara/2025-10-24-techbookfest19-announcement/cover.webp =300x) 新書「TECH BOOK By KINTO Technologies Vol.01」の表紙。 原稿の締切を設ける こちらは重要です。入稿期限は絶対的な締切なので、それに合わせて余裕を持って設定した方が良いです。 また一発で原稿が揃うのはなかなかないと思った方が良いでしょう。 締切は1個だけではなくバックアップのためさらに2、3個設け、それぞれの締切で達成してほしい最低ラインを設定した方が良いでしょう。 執筆者間でレビューしてもらう 執筆者間でレビューしてもらいました。 レビュー項目は社外への外部発信時のレビュー項目に準じつつ、最終的には物理本にすることを意識して項目を設定しておくと良いでしょう。 原稿が出揃わないとレビューすらできないので、締切は早めに設定しておくことをお勧めします(2回目)。 校正 全員分の原稿を取りまとめた上で、全体の紙面の見栄えを調整していきました。 文字サイズが小さいことに気づいたため少し大きくしたり、目次だけで10ページと多くなってしまったので、目次に出す項目を絞ったりしました。 ページ数を4の倍数に調整しておかないと入稿を受け付けてくれないので、うまいことページ数の調整もしていきました。 この影響で表示が崩れてしまった章もあったので、執筆者に修正をお願いしていました。 時間がない中での作業だったので、締め切りは早めに設定しておきましょう(3回目)。 入稿 入稿用のPDFができたら印刷所に入稿していきます。 日光企画さんでは先に入金しておき、入稿用の表紙と本文データをフォームで送信すればOKでした。 ここでデータの不備があれば指摘があり再提出することになりますが、今回は特に不備もなく無事入稿できました。 ブース設営のシミュレーション ブースの設営に詳しい技術広報の方に協力してもらいながら、前日にシミュレーションを行いました。 事前にブースのイメージを膨らませておきつつ必要なものも洗い出せたので、当日ブースを見て何となく思ってたのと違う...みたいなことにはならなかったと思います。 オフライン会場当日の様子 オフライン会場で出来上がった本を初めてみた時、思ったより分厚いなと感じました。 この分厚い本を無料で頒布したので、参加者からは驚きの声も聞かれました。 約300部印刷したのですが全て頒布できたので、初回参加の結果としては上々なのではないかと思っています! https://x.com/KintoTech_Dev/status/1989983294059168095 国会図書館へ納入 技術書典の翌日、国会図書館へ納本しました。日本国内で頒布を目的として発行した出版物は原則納本の対象になるらしく、今回のような技術同人誌でも納本できるようです。 https://www.ndl.go.jp/jp/collect/deposit/deposit.html 日本国内で頒布を目的として発行された出版物は、原則として、すべて納本の対象となります(「納本制度の概要」参照)。 国立国会図書館に出版物を納本いただくと、その書誌データが「全国書誌」として国立国会図書館サーチで検索できるようになります。また、図書館資料として広く利用されるとともに、国民共有の文化的資産として永く保存され、日本国民の知的活動の記録として後世に継承されます。 納本には以下の記事も参考にさせていただきました。 https://qiita.com/mitsuharu_e/items/850ae6688a94ea3d67f3 いざ納本へ 国の中枢ということもあり、銀座線、丸の内線、半蔵門線といった様々な路線が乗り入れています。 2番出口が国会図書館の最寄りのため、路線によっては多少歩くことになりそうです。 駅周辺の案内。出口2が一番最寄りです。私は銀座線で向かったため、歩く量が多かった。 国立国会図書館の案内。納本の方は通用口(西口)へという案内がある。 国立国会図書館の通用口(西口)から入って、建物の入り口にいる警備員さんに納本したい旨伝えると手続きをしてくれます。 国立国会図書館の通用口(西口) 納本の窓口に着いたら、納本する書籍を渡して書類に記入します。手続きが終わったら受領書を渡してくれます。 資料受領書 納本すると以下のように国立国会図書館サーチの結果に表示されるようになり、また国会図書館で資料として読めるようになります。 https://ndlsearch.ndl.go.jp/books/R100000002-I034410569 終わってみて感じたこと 一人で抱え込まず、助けを借りよう 書籍一冊作るだけでも決めることややるべきタスクが多く、一人だけで全て捌き切るのはだいぶ大変です。 他の人でもできる、むしろ他の人の方がうまくやれるタスクはお願いしていった方が良いです。 技術本によって繋がりが増えた 技術書典のオフライン会場での参加者との交流はもちろん、技術本の制作を通して社内有志で繋がりが深まったと思っています。 締切は多重に早めに入れておく 余裕を持って締切を設定したつもりがやってみると意外と時間がないなという気持ちになったので、次はもう少し余裕を持たせていこうと思ってます。多重で締切を設定することは大事です。 まとめ 技術書典19への参加の道のりには大変なことも多かったですが、終わってみると得られるものも多く本当に楽しかったです。 もしこの記事を読んで興味が湧いた方はぜひ技術本制作にチャレンジしてみてください。 また今後の技術書典でパワーアップした姿を見せられるよう頑張っていきます。 https://techbookfest.org/product/qCPrJpWLmKnLt7eWVd9zJ6
This article is the 12th entry in the KINTO Technologies Advent Calendar 2025 . Introduction I'm Uehara ( @penpen_77777 ), a backend engineer in the FACTORY E-commerce Development Group at KINTO Technologies. I participated in Techbook Fest 19 as part of the KINTO Technologies Writing Club, a circle (a small creator group) formed by volunteer engineers at KINTO Technologies. In this article, I'll share our journey of creating a technical book with company volunteers. Here's the introduction to the new book we created! It's free. If you're interested, please download the digital version. https://blog.kinto-technologies.com/posts/2025-10-31-techbookfest19-announcement/ https://techbookfest.org/product/qCPrJpWLmKnLt7eWVd9zJ6 The Beginning I had written technical books before and had been wanting to write one again after a long break. While tech blogs and presentations are sufficient for getting your writing read by others, there's something deeply satisfying about seeing your writing become a physical book. Since our company had never organized a circle of employee volunteers to write technical books, I decided to take on this challenge. Building the Team Finding Supportive People I started working on this in June, about six months before participating in Techbook Fest. Finding supportive people early on is extremely helpful when moving tasks forward. Our company has a Developer Relations Group that can provide consultation for employees' external technical communications. I truly believe we were able to accomplish this thanks to the Developer Relations Group. I'm very grateful. Finding People Interested in Writing Since participating in Techbook Fest was a first-time endeavor, I was worried about whether we could actually gather participants. Announcing a call for participants company-wide out of the blue felt like a high hurdle. So I decided to reach out to people who seemed interested and gather those who were highly likely to participate in advance. At our company, many people use times (personal update channels) on Slack, which is great for casually expressing your thoughts. By hinting at my desire to exhibit at Techbook Fest, I was able to know who might be interested. About five people gathered at this point, so I felt reassured that even if a company-wide announcement didn't attract more participants, we could still make the project work. Making the Announcement I created a simple slide to recruit writers company-wide. It summarized information about Techbook Fest and the benefits of writing, designed to encourage participation. The official sponsorship materials were helpful for introducing the scale of the event. https://techbookfest.org/assets/tbf18/for-sponsors.pdf Selecting a Printing Company Since we were creating a physical book, we needed to select a printing company. Techbook Fest has designated backup printing companies, and by submitting your manuscript to one of them, they handle everything from printing to delivering it to the venue. It’s a very convenient system. The backup printing companies are Nikko Kikaku and Neko no Shippo, and we chose Nikko Kikaku for this project. Selecting and Configuring the Typesetting System A typesetting system converts manuscripts into a print-ready format. Re:VIEW is commonly used as a typesetting system for technical books. By processing text files written in the proprietary Re:VIEW format through Re:VIEW, they are converted into formats commonly used for e-books such as EPUB and PDF. The benefit is that the separation of page style settings from content allows writers to focus on the essential task of writing without worrying about appearance. For this project, we used Vivliostyle^[It reads "kumihan," but I always mistakenly read it as "soban." https://ja.wikipedia.org/wiki/%E7%B5%84%E7%89%88] as our typesetting system. https://vivliostyle.org/ja/ Vivliostyle's distinguishing feature is the ability to change appearance using CSS, so anyone familiar with frontend technologies should be able to use it without difficulty. Since setting everything up from scratch would be challenging, we utilized a template distributed by YUMEMI. We're very grateful for the distribution of such a template. Thank you! https://github.com/yumemi-inc/daigirin-template Based on the above template, we made the following modifications: Updated the title, publisher, and colophon for our technical book Changed the paper size to B5^[This is when I learned that B5 comes in both JIS B5 and ISO B5. Be careful, as they have different dimensions despite both being called B5.] Enabled automatic table of contents output and adjusted the template for sections that weren't outputting correctly Registering Your Circle for Techbook Fest While there's a lot to prepare, don't forget to submit your circle participation application. It might be a good idea to add it to your calendar. Having Writers to Write I created and shared guidelines so writers wouldn't struggle with the writing process. Overall schedule and what to do in each phase Writing methods (Vivliostyle Flavored Markdown^[A notation that extends common markdown to express book-specific structures. https://vivliostyle.github.io/vfm/#/] syntax, PDF preview methods, etc.) Manuscript Management We managed manuscripts on GitHub, with each writer branching off from the main branch to write. Having each writer create a PR is convenient for tracking progress. Using Slack Lists To prevent topic overlap within the book, I asked writers to add their topics to a Slack list once decided. It's also helpful to include other information you want to track, such as self-introductions for the appendix and writing status. While we could have managed this with tables in Confluence, I personally check Slack more frequently, so I managed it using Slack lists, which can be used similarly to Notion databases. Getting the Book Cover Created When I was wondering whether to create the book cover myself, one of the participants suggested asking designers from the Creative Office for help. Since we wanted to create it in a fun, collaborative way, we decided to hold a Generative AI × Live Visual Creation event where designers would create the cover using generative AI. The event held to create this technical book: Vibe Painting Hour #01 Five designers joined the event and, while participants watched, used generative AI to create covers within a one-hour time limit. Despite my vague request to create a cover with a sense of mobility and futuristic feel, all five final cover proposals were of such high quality that choosing only one seemed like a waste! Through participant voting and my judgment, the cover for this technical book was selected. ![表紙](/assets/blog/authors/uehara/2025-10-24-techbookfest19-announcement/cover.webp =300x) The cover of our new book, TECH BOOK By KINTO Technologies Vol.01. Setting Manuscript Deadlines This is important. The submission deadline is absolute, so you should set it with plenty of buffer time. Also, it's best to assume that manuscripts won't be ready on the first try. You should set not just one deadline but two or three backup deadlines, with minimum requirements for each deadline. Having Writers Review Each Other's Work We had writers review each other's work. The review items followed our external communication review guidelines, while also keeping in mind that the final product would be a physical book. Since you can't even start reviewing without all manuscripts being submitted, I recommend setting the second deadline early. Proofreading After compiling all manuscripts, we adjusted the overall page layout. After noticing the font size was too small, I made it slightly larger. The table of contents had grown to 10 pages, so I narrowed down the items to include. We also had to adjust the page count to be a multiple of four, or the submission wouldn't be accepted. This caused display issues in some chapters, so we asked writers to make corrections. Since we were working under time pressure, we decided to set the third deadline early. Submission Once the PDF file for submission was ready, we submitted it to the printing company. With Nikko Kikaku, we paid in advance and then sent the cover and body data via a form. If there were any data issues, they would point them out and we'd need to resubmit. This time there were no issues and submission went smoothly. Booth Setup Simulation With help from a Developer Relations team member who was experienced with booth setup, we carried out a simulation the day before. By visualizing the booth in advance and identifying what we needed, I think we avoided the situation where we'd look at the actual booth on the day and feel like "hmm, this isn't quite what I imagined..." The Day of the Offline Event When I first saw the finished book at the offline venue, I thought it was thicker than expected. Since we distributed this thick book for free, we heard surprised reactions from attendees. We printed about 300 copies and distributed them all, so I think it was a great result for our first participation! https://x.com/KintoTech_Dev/status/1989983294059168095 Depositing at the National Diet Library The day after Techbook Fest, we deposited the book at the National Diet Library. Apparently, publications issued for distribution within Japan are generally subject to legal deposit, and even technical doujinshi like ours can be deposited. https://www.ndl.go.jp/jp/collect/deposit/deposit.html Publications issued for distribution within Japan are, in principle, all subject to legal deposit (see "Overview of the Legal Deposit System"). When you deposit publications with the National Diet Library, their bibliographic data becomes searchable as the "National Bibliography" through the NDL Search. Additionally, they are widely used as library materials, preserved as cultural assets shared by the nation, and passed down to future generations as records of the Japanese people's intellectual activities. I also referenced the following article for the deposit process. https://qiita.com/mitsuharu_e/items/850ae6688a94ea3d67f3 : Off to Deposit Being a central government location, various train lines converge here, including the Ginza, Marunouchi, and Hanzomon lines. Exit 2 is the closest to the National Diet Library, so depending on your line, you may need to walk a bit. Area directory near the station. Exit 2 is the closest. I took the Ginza Line, so I had to walk quite a bit. National Diet Library sign. There's a notice that those depositing materials should go to the service entrance (west gate). Enter through the National Diet Library's service entrance (west gate) and tell the security guard at the building entrance that you want to deposit books, and they'll handle the procedure. National Diet Library service entrance (west gate) At the deposit counter, hand over the book and fill out the paperwork. Once the procedure is complete, they'll give you a receipt. Material receipt After depositing, the book appears in National Diet Library Search results and becomes available to read as a resource at the National Diet Library. https://ndlsearch.ndl.go.jp/books/R100000002-I034410569 Reflections After Completion Don't Try to Do Everything Alone; Reach Out for Help Even creating just one book involves many decisions and tasks, and handling everything alone is quite difficult. It's better to delegate tasks that others can do, or that others can do better than you. The Technical Book Expanded Our Connections As well as interacting with attendees at the Techbook Fest offline venue, I believe the connections among company volunteers deepened through creating the technical book. Set Multiple Early Deadlines Even though I thought I had set deadlines with plenty of buffer, I still ended up feeling short on time. Next time, I plan to build in an even larger margin. Setting multiple deadlines is important. Summary While there were many challenges on the road to participating in Techbook Fest 19, looking back, we gained a lot and it was truly enjoyable. If this article has piqued your interest, please try taking on the challenge of creating a technical book. We'll keep working hard so that we can show up even stronger at future Techbook Fests! https://techbookfest.org/product/qCPrJpWLmKnLt7eWVd9zJ6
こんにちは、Engineering Officeの守谷(emim)です。 この記事は KINTOテクノロジーズ Advent Calendar 2025 の11日目のものです。 2日目に、 アクセシビリティについての記事 を投稿しましたが、私の主領域はプロダクトデザインです。主軸では、 Engineering Office のメンバーとしてデザイナーの立場でKINTOテクノロジーズ(以下KTC)の状況をとらえ、組織力を上げるための取り組みを行っています。 KTCでは2025年の注力テーマとして、副社長の景山より、2つのテーマ「AIファースト」「リリースファースト」とともに、それを下支えする「ユーザーファースト」と「組織インテンシティ」が掲げられました。 https://blog.kinto-technologies.com/posts/2024-12-25-LookBack2024/ 私はこのうちデザイナーとして、「ユーザーファースト」推進活動に関わっています。私自身は6月入社ですが、このユーザーファーストについての活動は、今年のはじめから様々な方向での組織内の取り組みがおこなわれています。 今回は2025年の総括として、我々の実行した内容をまとめて行きます。 はじめに着手した社内調査から、社内での「ユーザー」の認知にブレがあることがわかった まず初めに行われたのが、ユーザーファースト推進において主軸となる「ユーザー」についての組織内での認知調査です。 ひと口に「ユーザー」と言っても、全員が同じ対象をイメージできているのか?という確認からです。ユーザーが一般的な用語だからゆえの解釈の違いを明確にした後に、具体の推進方法を検討するための調査です。 様々な部署、様々なロールのメンバーを全社から招集し、グループディスカッションを通し現状を把握しました。オンラインホワイトボードツールでの実施や、オンサイトでの付箋でのワークなど、開催形態は様々です。 調査が一通り終わったところで私が参画したこともあり、次に、ビジネスモデルと照らし各階層のユーザーからエンドユーザーまでと製品との関係性を、 Jeff Patton氏の提唱するThe onion model のような形での整理しました。 そこから見えてきたのは、我々の向かう製品とユーザーとの間にかなり距離があることでした。またその距離の遠さからか、事業の複雑さからか、ステークホルダー(チーム内で例えば上下関係のある別職域の人や、取り引きをしている関係会社/グループ会社の担当者、依頼主など)をユーザーと捉えている人も居そうなことがわかりました。 ![ビジネスモデルと照らし各階層のユーザーからエンドユーザーまでとシステムの関係性を表す図と、サービスとユーザーとの距離を表した図](/assets/blog/authors/emim/2025-12-11-userfirst2025/2025-12-11-userfirst2025_img02.png =600x) 「ユーザーのことが見えていない」という課題感からユーザーファーストというテーマが上がってきましたが、開発組織構造も関係していることがわかりました。開発者とユーザーに距離がある場合、どのようにステークホルダーを巻き込み意識付けを行い、ユーザーの要求事項を聞き出すのか、が次のステップになる、と考えました。 これらの情報は、この活動のオーナーである副社長にも共有し、齟齬なく活動を推進していけることの確認にも利用できました。 「UXの成熟度モデル」を参考にした現状分析と推進の次の一手の「共有」 組織課題が明らかになったところで、次に我々が着目したのが 「ユーザー」というワードが開発の現場で出てくるための意識付け 「ユーザー理解」のためのメンバーの巻き込み という2点です。前者については、プロダクト/サービス開発をする以上当たり前のことだと感じるかもしれませんが、全開発者がユーザーに向き合えているかというとまだまだだ不十分という状況です。 このあたりの肌感を探る為、 The 6 Levels of UX Maturity (UXの成熟度モデル)を参考にしながら、現状分析を行いました。このドキュメントには後半に自身で組織の状態を評価(推定)のできるテストが用意されています。 内容及びテストの結果からして、まだ我々は「Stage 2: Limited(限定的)」にいます。現在地が明らかになることで、次レベルの「Stage 3: Emergent(新興)」へ向かうために何をすべきか、という観点の確認が可能となります。 幸いなことに、一般的な組織で次に課題となる「会社側の理解がない(予算がつかない)」という状況にはありません。トップダウンで課題提起がなされている分、動きやすいと感じます。 組織の情報共有の仕組みとしては、他の注力テーマと定期的に情報共有をする機会(定例会議)が設定されています。それにより、例えばリリース分脈でユーザーについての相談をもらえるような関係にあったり、我々からも今後の取り組みとしてAI活用についての相談を上げたりしています。 ただしこれだけでは、限定的な範囲での情報共有となってしまいます。そこで次に、広く全社に向けての情報共有会を行いました。 UXが孤立しないための取り組み 我々の推進活動の共有 まず取り組んだのは、月に一度全社に向けて行われる情報共有会での活動報告です。 事前に各所と合意を得た「現在地」についての改めての報告と、開発者の多い現場でどうしたら「ユーザーの価値」に着目できるのか?という点に絞ってプレゼンを行いました。 「ユーザーの価値」を中心に据えた開発手法として、アジャイル開発と人間中心デザイン(Human Centered Design 、以後HCD)の類似性を引用しながら説明を行いました。 アジャイルの図はよく目にするエンジニアでも、HCDについては初めて耳にしたというリアクションが出ていました。HCDの各プロセスには具体の手法が提供されていることも合わせて提示したことで、この1度の発表だけでエンジニアからでも具体の相談の上がりやすい状況に転換できました。 社内の先行事例の発掘(勉強会の実施) 次に着手したのが、先行事例として取り組まれている方たちをクローズアップし、改めて社内にその活動を共有する勉強会を開催しました。勉強会を通し、「自分達でもできそう」という感覚を持ってもらうことを目的としています。 この勉強会では、具体のHCDプロセスをプロジェクト内で回している事例と、兄弟会社のKINTOの主催のイベントに赴き、ユーザーのサービス利用の状況把握に努めた事例について、改めて発表をしてもらいました。 後者については、過去にこのブログでも本人が記事を起こしてくれています。 https://blog.kinto-technologies.com/posts/2025-08-22-FACTORY_ReportOfRealEvent/ さらに、エンジニアの多い会社であることをふまえ、前述の取り組みをしたフロントエンドのエンジニアや、インタビューを実行したバックエンドのエンジニアを招聘し、パネルディスカッションを通して、具体の心境の変化などを共有してもらいました。 この勉強会以降、具体のユーザーインタビューやカスタマージャーニーマップなど、ユーザーニーズを掘り下げるような具体手法についての相談が上がってくる、という変化が起きました。最近は半月に1件くらいのペースで相談をいただいています。 今後の我々の活動について 現在、この取り組みは私ともう一人、クリエイティブGの大金とで行っています。暫定的に、ユーザーファースト推進活動の社内プロモーションや色々なプロセスの型化/横展開を行う守谷と、プロジェクト内に入ってHCDプロセスを実行していく大金と、という役割分担にしてはいますがもちろん手が足りてはいません。 前述のように、具体のプロセスを実行できる仲間を増やしたり、近い領域の人たちに声を掛け協力を仰いで、この活動を止めない事が最重要ではないかと考えています。また、今回こういった活動を改めて発表をおこなったことで、これまで各領域で埋もれていた活動(=いわゆるサイロ化現象が起きていた)なども、情報として表面化するようになってきました。 冒頭紹介の通り「2025年の」注力テーマのひとつではありますが、ユーザーのことを考えるのはプロダクトデザインの基礎の基礎。せっかくのこの取り組みの火を絶やさないよう、来年以降も研鑽をし続けようと考えています。 最後に。12月23日には KINTOテクノロジーズ Advent Calendar 2025 にて、ともにこの活動を行う大金から彼女自身の挑戦についての記事が公開されます。お楽しみに!
こんにちは!あるいは、まいど! 人事企画G 労務・総務チームのつんつんです。今回は、ついに完成したOsaka Tech Labの新フロアをご紹介します。 正直に言います。以前のオフィスとはもう「全然違う」空間に仕上がりました。 今回のコンセプト KINTOテクノロジーズらしく、車やモビリティを感じさせるデザインに全振りしました。 写真多めで、こだわりのポイントを余すことなくお届けします! エントランス まずエントランスでお出迎えするのは、KINTO Technologiesのロゴ。 これ、ただの看板じゃありません。後ろの骨組みが黒にし、あえてロゴを「白」にして、しかも光らせてます。 そして写真左側この植栽。 「これ本物?」ってよく聞かれますが、一部、フェイクもありますが、殆どリアル(本物)です。 水やり大変そうとか言わないでください。この空間の充実に命かけてるんで。 受付からの廊下の風景 廊下からも緑がいい具合に演出していて一石二鳥 車愛が止まらない 今回のコンセプトの一部でもあり具体化した、「ガレージ」です。 ① こだわりの会議室「ガレージ1・2・3」 会議室エリアは、まさにガレージそのもの。全会議室の床に白いラインを引き駐車場をイメージ、 また核となる3つの会議室には天つりモニターにし、電動ブラインドを設置。 (大事な会議もこれで安心!目線にも気を配りました。) Garage 1: 車の車庫をイメージ 床に白い駐車ラインを引き、有効ボード(ペグボード)を設置。ここに工具とか飾りたい! (予算なくてまだ何もかけてないけど)。 Garage 2: 車の模型をおしゃれに配置。 チップボード風の壁紙にし、無骨なガレージ感を演出。棚を配置しちょっとした小物を置けるようにしました。 Garage 3:西海岸の風を感じる。 ここはちょっとアメリカンな雰囲気。「アメリカンフェンス」というそのまんまな名前の商品を入れて、ヤシの木を導入しました。 廊下もただの廊下じゃない 廊下の天井には道路標識が埋め込まれています。 「大阪ジャンクションまで7m」。これ、適当な数字じゃありません。ちゃんとCADで測って、本当に7mあります。JCTの部屋は後ほど・・・ こういう細かいこだわり、大好きです。 会議室「PIT(ピット)」シリーズ ガレージの次はピットです。ここも部屋ごとに椅子が全部違います。全部変えました。こだわりすぎて記憶飛びそうですが。 写真左からPIT-A, PIT-B, PIT-C PIT-A PIT-B PIT-C 受付と反対側にある4人部屋。受付との一部をガラスにすることにより、ここでも緑が大活躍。癒してくれます。 小会議室の4人部屋。PIT Aと色違いの椅子を入れることで雰囲気がだいぶ変わりました。 机がビンテージ風でかっこいいんですが、真ん中から配線が出せないのが玉に瑕。でも、デザイナーさんの熱意に負けて入れました。 PIT-D ここはプロジェクター投影専用の壁紙を採用。スクリーンを下ろす手間がありません。机は可動式で、スクール形式にも対応。コンセントも爆量で用意してるので、勉強会もやり放題です。 MOTORPOOL 8人用会議部屋。こちらは格式高く設計しており役員会議など行われる設定です。 遊び心満載の「ジャンクション」エリア オフィスの中心にあるのが、みんなが集まる「ジャンクション」。 壁には大阪メンバーのクリエイティブによる巨大アートが! 「この指とまれ」をコンセプトに、大阪らしくたこ焼き、カニ、くいだおれ人形が描かれています。 この指とまれ案のストーリー 技術交流を通じて、部署内や外部の関係者を巻き込みながら、自ら進んで物事を進める力。これが大阪の強み、気質。 この特徴をこの指とまれの指をモチーフに色々な予想外な業種、事、人、技術とコラボしていくことを壁に表現しております。 そしてここには、私がどうしても置きたかった業務用「冷凍庫付き冷蔵庫」があります。 執務エリアからJCTを望む。 コンセプト 情熱のアルゴリズムコード 壁の「この指とまれ」を強調するガラスになっており、 情熱が生まれ広がっていく過程を視覚的にコードで表現してます。 情熱が自分から生まれ → 外部要因と掛け合わさる → 最終的に情熱が 波のように「うねり」になり、社会に大きな影響を与える様子を表現しています。 土禁×リラックスゾーン “PARK” 靴を脱いでくつろげるグリーンカーペットは、まるでオフィス内ピクニック場! 梅田の街並みを眺めながらランチやちょっとしたMTGもOK🍱☕ 謎のこだわり「SUVタイヤ」と「低いホワイトボード」 park部分には、なぜか巨大なタイヤが転がっています。 これ、中身が入った本物のSUVタイヤです。最初はノーマルタイヤだったんですが、「そんなんじゃダメだ!ゴツゴツしたやつがいい!」とわがままを言って変えてもらいました。 こちらは木製モーターベンチ! 足元には本物タイヤを装着!座るだけで車会社らしい遊び心を体感できるミニドライブ気分 2人乗っても大丈夫ですが、めちゃくちゃ重いです。 執務エリアは「広さ」が命 働くデスク周りも妥協してません。 移転前より通路幅、デスク幅を大きくしました。 (デスク幅は1400mm、前後の通路幅は1800mm確保。) 「狭い」とは言わせません。 ストレスフリーで働けます。 まとめ:とにかく「こだわり」がすごい 正直、まだまだ語りきれないこだわりが山ほどあります。 全部書き切れないのですが一部ご紹介 公園のベンチを忠実に再現した木目スラット。 座るだけでほっこりピクニック気分♪ HUBエリア 壁紙はマップ(地図)をイメージ  ファミレス席は移転前の部屋名を踏襲しており歴史も大事にしてます。 サボテンもあります。 オフィスからの風景 大阪駅の真上にあり電車マニアにはたまらない!真ん中より少し右側に線路が見えます。 とにかく、Osaka Tech Labは 「働きたくなるオフィス」 に仕上がりました。 ここまでお付き合い頂きありがとうございました。 現場からは以上です!
こんにちは!あるいは、まいど! 人事企画G 労務・総務チームのつんつんです。今回は、ついに完成したOsaka Tech Labの新フロアをご紹介します。 正直に言います。以前のオフィスとはもう「全然違う」空間に仕上がりました。 今回のコンセプト KINTOテクノロジーズらしく、車やモビリティを感じさせるデザインに全振りしました。 写真多めで、こだわりのポイントを余すことなくお届けします! エントランス まずエントランスでお出迎えするのは、KINTO Technologiesのロゴ。 これ、ただの看板じゃありません。後ろの骨組みが黒にし、あえてロゴを「白」にして、しかも光らせてます。 そして写真左側この植栽。 「これ本物?」ってよく聞かれますが、一部、フェイクもありますが、殆どリアル(本物)です。 水やり大変そうとか言わないでください。この空間の充実に命かけてるんで。 受付からの廊下の風景 廊下からも緑がいい具合に演出していて一石二鳥 車愛が止まらない 今回のコンセプトの一部でもあり具体化した、「ガレージ」です。 ① こだわりの会議室「ガレージ1・2・3」 会議室エリアは、まさにガレージそのもの。全会議室の床に白いラインを引き駐車場をイメージ、 また核となる3つの会議室には天つりモニターにし、電動ブラインドを設置。 (大事な会議もこれで安心!目線にも気を配りました。) Garage 1: 車の車庫をイメージ 床に白い駐車ラインを引き、有効ボード(ペグボード)を設置。ここに工具とか飾りたい! (予算なくてまだ何もかけてないけど)。 Garage 2: 車の模型をおしゃれに配置。 チップボード風の壁紙にし、無骨なガレージ感を演出。棚を配置しちょっとした小物を置けるようにしました。 Garage 3:西海岸の風を感じる。 ここはちょっとアメリカンな雰囲気。「アメリカンフェンス」というそのまんまな名前の商品を入れて、ヤシの木を導入しました。 廊下もただの廊下じゃない 廊下の天井には道路標識が埋め込まれています。 「大阪ジャンクションまで7m」。これ、適当な数字じゃありません。ちゃんとCADで測って、本当に7mあります。JCTの部屋は後ほど・・・ こういう細かいこだわり、大好きです。 会議室「PIT(ピット)」シリーズ ガレージの次はピットです。ここも部屋ごとに椅子が全部違います。全部変えました。こだわりすぎて記憶飛びそうですが。 写真左からPIT-A, PIT-B, PIT-C PIT-A PIT-B PIT-C 受付と反対側にある4人部屋。受付との一部をガラスにすることにより、ここでも緑が大活躍。癒してくれます。 小会議室の4人部屋。PIT Aと色違いの椅子を入れることで雰囲気がだいぶ変わりました。 机がビンテージ風でかっこいいんですが、真ん中から配線が出せないのが玉に瑕。でも、デザイナーさんの熱意に負けて入れました。 PIT-D ここはプロジェクター投影専用の壁紙を採用。スクリーンを下ろす手間がありません。机は可動式で、スクール形式にも対応。コンセントも爆量で用意してるので、勉強会もやり放題です。 MOTORPOOL 8人用会議部屋。こちらは格式高く設計しており役員会議など行われる設定です。 遊び心満載の「ジャンクション」エリア オフィスの中心にあるのが、みんなが集まる「ジャンクション」。 壁には大阪メンバーのクリエイティブによる巨大アートが! 「この指とまれ」をコンセプトに、大阪らしくたこ焼き、カニ、くいだおれ人形が描かれています。 この指とまれ案のストーリー 技術交流を通じて、部署内や外部の関係者を巻き込みながら、自ら進んで物事を進める力。これが大阪の強み、気質。 この特徴をこの指とまれの指をモチーフに色々な予想外な業種、事、人、技術とコラボしていくことを壁に表現しております。 そしてここには、私がどうしても置きたかった業務用「冷凍庫付き冷蔵庫」があります。 執務エリアからJCTを望む。 コンセプト 情熱のアルゴリズムコード 壁の「この指とまれ」を強調するガラスになっており、 情熱が生まれ広がっていく過程を視覚的にコードで表現してます。 情熱が自分から生まれ → 外部要因と掛け合わさる → 最終的に情熱が 波のように「うねり」になり、社会に大きな影響を与える様子を表現しています。 土禁×リラックスゾーン “PARK” 靴を脱いでくつろげるグリーンカーペットは、まるでオフィス内ピクニック場! 梅田の街並みを眺めながらランチやちょっとしたMTGもOK🍱☕ 謎のこだわり「SUVタイヤ」と「低いホワイトボード」 park部分には、なぜか巨大なタイヤが転がっています。 これ、中身が入った本物のSUVタイヤです。最初はノーマルタイヤだったんですが、「そんなんじゃダメだ!ゴツゴツしたやつがいい!」とわがままを言って変えてもらいました。 こちらは木製モーターベンチ! 足元には本物タイヤを装着!座るだけで車会社らしい遊び心を体感できるミニドライブ気分 2人乗っても大丈夫ですが、めちゃくちゃ重いです。 執務エリアは「広さ」が命 働くデスク周りも妥協してません。 移転前より通路幅、デスク幅を大きくしました。 (デスク幅は1400mm、前後の通路幅は1800mm確保。) 「狭い」とは言わせません。 ストレスフリーで働けます。 まとめ:とにかく「こだわり」がすごい 正直、まだまだ語りきれないこだわりが山ほどあります。 全部書き切れないのですが一部ご紹介 公園のベンチを忠実に再現した木目スラット。 座るだけでほっこりピクニック気分♪ HUBエリア 壁紙はマップ(地図)をイメージ  ファミレス席は移転前の部屋名を踏襲しており歴史も大事にしてます。 サボテンもあります。 オフィスからの風景 大阪駅の真上にあり電車マニアにはたまらない!真ん中より少し右側に線路が見えます。 とにかく、Osaka Tech Labは 「働きたくなるオフィス」 に仕上がりました。 ここまでお付き合い頂きありがとうございました。 現場からは以上です!
Hello, I'm Moriya (emim) from the Engineering Office. This article is part of KINTO Technologies Advent Calendar 2025 for Day 11. On Day 2 of the event, I posted an article about accessibility , while my primary job is product design. As a core function, I work as a designer within the Engineering Office , analyzing the situation at KINTO Technologies (KTC) and implementing initiatives to strengthen organizational capabilities. At KTC, our Executive Vice President Kageyama announced the following four key ideas which we focus on in 2025: AI first and release first that are directly related to our product development, as well as user first and organizational intensity to fundamentally support the former two ideas. https://blog.kinto-technologies.com/posts/2024-12-25-LookBack2024-en/ As a designer, I am involved in promoting user-first design among these ideas. Looking back to June 2025 when I joined KTC, user-focused activities have been already underway within the organization in various aspects since the beginning of 2025. As a year-end summary for 2025, I will wrap up what we have accomplished. ##First Internal Survey Revealed Inconsistent Perception of Users Within KTC Our first activity to promote user-first design was a survey to assess internal perception of users. There are so many different types of users that we need to ensure that our members share a common understanding of them. The survey was designed to plan specific methods to promote user-first design through confirming whether everyone has the same understanding of "users." We gathered members from various divisions and roles across the company and conducted group discussions to understand the current circumstances. Group-work sessions were held in various formats, including brainstorming with online whiteboard tools and on-site workshops to map the user perception with sticky notes. I joined my current team after completing the survey, and we then organized the relationship between users at each level—from business model stakeholders to end users—and products, in a format similar to Jeff Patton's onion model . Through this process, we found a considerable gap between our products and users’ needs. Perhaps due to the gap or complexity of our businesses, some people seemed to perceive stakeholders (such as colleagues in different roles with hierarchical relationships, partners at related/group companies, or clients) as users. ![ビジネスモデルと照らし各階層のユーザーからエンドユーザーまでとシステムの関係性を表す図と、サービスとユーザーとの距離を表した図](/assets/blog/authors/emim/2025-12-11-userfirst2025/2025-12-11-userfirst2025_img02.png =600x) While the user-first design is raised as a discussion topic from the concern that we cannot see what users want, we found that our development organization structure is one of the factors contributing to addressing this. When developers are distant from our users, the next step will be how to involve stakeholders, raise their awareness, and draw out users’ needs. We also shared the information with our Executive Vice President, who is responsible for this initiative, confirming alignment for seamless activity promotion. Current Statement Analysis Using Level of UX Maturity and Next Step of Sharing With organizational challenges clarified, we focused on two points: Raising developers’ awareness of the term user to remind them of a user-first mindset Involving members to understand users The former may seem obvious for product/service development, but not all developers sufficiently consider users yet. To measure our developers’ perception on users, we conducted a current state analysis referencing The 6 Levels of UX Maturity . This document includes a quiz in the latter half that allows individuals to self-assess their organizational conditions. Based on the content and quiz results, we are still at Stage 2: Limited. Clarifying our current position enables us to identify what we must do to advance to Stage 3: Emergent, the next level. Fortunately, we do not face the issue common in typical organizations: lack of the company’s understanding (no budget allocation). With problems identified through the top-down process, we find them easier to take action. For organizational information sharing, regular meetings are scheduled to share information with other key topics. This enables relationships where, for example, we receive user-related consultations in release contexts, and we can also had discussions about AI utilization for future initiatives. However, this alone limits information sharing to a specific scope. Therefore, we next conducted a company-wide information sharing session. Initiatives to Prevent UX from Being Isolated Sharing Our Promotion Activities The first step was reporting activities at the monthly company-wide information sharing session. We reconfirmed our current position, which we previously agreed upon with various parties, and mainly presented how developers can put a focus on user value. We explained development methods focusing on user value, citing similarities between agile development and human-centered design (HCD). Even engineers familiar with agile diagrams reacted as if they heard about HCD for the first time. Through the presentation that specific methods are provided for each HCD process, this single presentation created a situation where engineers could easily have discussions on specific topics. Exploring Internal Case Studies (Conducting Study Sessions) Next, we organized study sessions to spotlight those who have been working on running the HCD process before and share their activities on a company-wide basis. Through these sessions, we aimed to give rise to participants’ expectation that they could do it too. In these sessions, we had presenters share examples of implementing specific HCD processes within projects and cases where they attended events hosted by our sister company KINTO to understand how users use our services. Regarding the latter, one of the session attendees previously wrote an article on the following blog. https://blog.kinto-technologies.com/posts/2025-08-22-FACTORY_ReportOfRealEvent/ Furthermore, considering our company's large engineering population, we invited our frontend engineers who implemented the aforementioned initiatives and backend engineers whom we had interviews with to share detailed changes in their mindset through their efforts during the panel discussions in the session. After this study session, we witnessed changes in members’ behavior; for example, they contacted us about specific methods for deeply understanding user needs that include user interviews and customer journey maps. Recently, we received requests for consultations from engineers at a pace of about one every two weeks. Our Future Activities Currently, this initiative is carried out by myself and one of my colleagues Okane-san from the Creative Group. We have roughly divided our roles: I, Moriya, handle internal promotion of user-first activities and standardization/horizontal deployment of various processes, while Okane-san joins projects to execute HCD processes. Of course, we are short-handed, though. As mentioned earlier, we believe the most important thing is to increase the number if colleagues who can execute the processes, reach out to people in related areas for cooperation, and keep this activity going. Additionally, by presenting these activities again, we can spotlight activities that no longer gain traction in various areas once again to learn and leverage them as knowledge. As introduced at the beginning, while this is one of 2025's focus points, thinking about users is the foundation of product design. To keep proceeding with this initiative in a sustainable manner, we plan to continue refining our efforts beyond next year. Finally, on December 23, Okane-san, who works with me on this initiative, will publish an article about her own challenges in the KINTO Technologies Advent Calendar 2025 . Stay tuned!
この記事は KINTOテクノロジーズ Advent Calendar 2025 の10日目の記事です🎅🎄 はじめに KINTOテクノロジーズのCloud Infrastructure G(CIG)でInfrastructure Architectを担当している劉(YOU)です。11月から技術広報 Gも兼務することになりました。 2025年11月、弊社は「 CloudNative Days 2025 Winter 」に、スポンサー企業として参加しました。今回のイベントでは、弊社の社員2名が登壇し、私が所属しているCloud Infrastructure G・技術広報 Gがスポンサーブースを運営し、多くのメンバーが参加者として技術セッションに参加するなど、組織全体で積極的に関わることができました。 CloudNative Daysは、日本国内のクラウドネイティブコミュニティにおいて最大規模のイベントです。今回の参加を通じて、私たちは技術的な知見を深めるだけでなく、CloudNativeという概念そのものについて改めて考える機会を得ることができました。 本記事では、登壇者、ブース運営担当者、そして一般参加者、それぞれの視点から見たイベントの様子と、そこから得られた学びを共有します。 登壇者インタビュー Cloud Infrastructure G、古代さん:「 モビリティプラットフォームの未来を築くクラウド基盤 」 登壇に至った経緯 古代さん :「入社して1年経っていない状態で、組織の歴史を知らない、技術選定の理由を知らない。自分が経験していない、実体験がないことをどう伝えればいいのか、それが一番大変でした」 当初は別のメンバーが登壇予定だったところ、都合により急遽登壇することになりました。2025年1月に入社したばかりで、組織の歴史や技術選定の背景を十分に把握していない状態でのチャレンジです。 テーマ選定の背景 古代さんはCloudNativeというテーマに対して悩みました。CloudNative関連の資料を探したら、多くの登壇者がKubernetesやコンテナなど、技術的に深い内容を発表する中、弊社は主にECSを利用していてKubernetesは限られた所だけ使っていません。しかし、その悩みこそが、同じような状況にいる多くの人々と共有できる価値だと気づきました。 古代さん :「CloudNativeはハイレベルに感じるかもしれませんが、そこに至るまでは組織としての試行錯誤が必要です。技術で尖ることも必要ですが、組織としてCloudNativeな文化を作ることが重要です。ベストプラクティスはありません」 最も伝えたかったのは、 CloudNativeは手段であり、目的ではない ということです。ビジネスに向き合いながら、適切な技術を選定していく。その試行錯誤の歴史をありのまま伝えることで、同じように悩んでいる人たちが前進できるきっかけになればと考えました。 当日の反応 会場Cの66名規模の会場は、ほぼ満席でした。オンラインで他のセッションを聞いていた方が、途中からこのセッションに移動してくるケースも多く見られました。 古代さん :「頷きながら聞いてくださる方がいて、スライドを写真に撮ってXに上げてくれる人もいました。技術がかなり重視されそうなイベントにおいて、自分のテーマに興味を持ってもらえたのは印象的でした」 質問もマイクで2名、「Ask the Speaker」で3名が訪れ、初めての登壇としては大きな手応えを感じることができました。特に印象的だったのは、Terraformの作り方やプラットフォーム組織の意思決定についての質問でした。これらは正解のない問いですが、 みんなそういうところで悩む ということを改めて実感します。 得られた学び 今回の発表は40分に至る長めのことでして、登壇に関する資料作成や発表練習に追われた古代さんは日々のアウトプットの重要性を痛感しました。 古代さん :「日々発表していれば、もっとスライド作りが簡単だったと実感しました。テックブログなどを書いていれば、それを応用して活用できるなと。アウトプットを頑張ろうと決意しました」 また、AIの使い方についても重要な気づきがあります。最初にAIとスクリプトでトークスクリプトを作ろうとして失敗した経験から、「どういうメッセージを伝えたいのかを固めた上で、どう表現すればいいかをAIに聞くのが重要。最初からAIに聞くのは絶対にダメ」という教訓を得ました。 次回への展望 次回は20分程度の短い登壇で回数を重ね、技術を中心にしたネタの発表もチャレンジしたいと考えています。また、せっかくのコミュニティイベントなので、グループワークや相互学習を通じて、参加者とよりネットワークを深めたいという思いも語ってくれました。 古代さん :「来年はCloudNative会議が開催されます。KINTOテクノロジーズはトヨタグループの中でも先進的にクラウド活用を進めている組織です。ハイレベルなものがあるわけではありませんが、ハイレベルのものを一緒に作ることはできるフェーズになっています。一緒にコラボしたり、勉強会をしたりする機会が増えると嬉しいです」 Platform G、李さん:「 AI Agentで切り開くアラート対応の新時代 」 CFP応募の決断 李さんは、採択される可能性は低いと考えながらも、「とりあえず出してみよう」という気持ちでCFPを応募しました。応募理由は明確です。会社の外部発信力を高め、グループ内でのエンジニア採用に貢献し、外部コミュニケーションの機会を得るためです。スポンサーワークとは完全に別枠での応募だったため、採択されたことに驚いたそうです。 資料作成での苦労 李さんが資料作成に苦労したのは、対象者のレベル設定でした。 李さん :「詳しい人もいれば、初心者もいる中で、どのレベルに合わせるか悩みました。知らない人が見ても理解しやすい内容にしたいが、軽すぎる内容では深い知識を求める人に物足りない。このバランスを取ることが最も難しかったです」 特にストーリーテリングにも力を入れました。「こういう課題があって→こう対応して→結果こうなった→現在はこうなっている」という流れを意識し、話の流れが自然になるよう、全体構成を何度も見直しました。資料作成には約1週間以上、継続的に質を上げるために原稿やプレゼンを整えました。 想定外の出来事 当日、最も不安だったのは、PowerPointのスクリプト機能が聴衆側の画面に表示されるかどうかです。40分の発表で台本なしは厳しいため、昼休みに自ら会場に行って確認を依頼しました。 李さん :「登壇者向けの情報提供として、到着時間やHDMI接続などの基本情報はありましたが、リハーサルや台本表示確認などの詳細な案内が必要でした。次回登壇する社内メンバーには、事前に会場で確認することをアドバイスしたいです」 参加者の反応 発表は全体的に好評で、同じ発表者である古代さんからも「今日のセッションで最も印象的だった」とのコメントをいただきました。発表終了後にも4〜5名が質問に来て、AI Agentに対する関心の高さを実感できたと話ました。 特に印象的だったのは、コンテキストエンジニアリングに関する質問です。AIに必要な情報と、人間にだけ必要でAIには不要な情報をどう区別しているか。この質問に対しても、現在検討中の対策を共有してくれました。 李さん :「LLMモデルのインプット制限の問題があり、コンテキストが大きくなりすぎると制限を超えてしまいます。シングルエージェント構成で対応予定で、LangChainの新機能を活用し、履歴を要約・圧縮する方式を検証中です。この改善内容を来年のカンファレンスや技術記事で発表したいと考えています」 得られた学び 李さんにとって、大規模なオープンコミュニティでの登壇は初めてだったので得られた事が多かったそうです。 李さん :「緊張はしましたが、思ったほど恐れる必要はないと感じました。やってみたい人がいれば、積極的にトライすることをお勧めします。他の登壇者や参加者から大きな刺激を受け、技術的なモチベーションが向上しました」 技術的な収穫としては、インシデント管理のSaaSやサイバーエージェント大山さんのLoki・Prometheusに関する発表が参考になったそうです。また、Xのフォロワーも数十人増加し、コミュニティでのつながりが広がりました。 次回への展望 時間管理については反省点があります。練習では台本を見ながら話すため早く終わりすぎないか心配でしたが、本番では緊張して言葉が出てこず、逆に時間が足りなくなり、1ページスキップする必要がありました。 次回は、コンテキストエンジニアリングの改善やAgentの評価方法について発表したいと考えています。 李さん :「Agentの効果をどう評価するか、評価基準の作成が難しい。同じアラートでも原因が異なる場合があり、正解データの作成が困難です。これは業界全体で共通の課題として認識されています。コンテキストエンジニアリングは最近注目されている分野で、ベストプラクティスがまだ確立されていません。多くの人が知りたがっている内容だと思います」 李さんからのアドバイスは明確です。 李さん :「まずは応募してみることが重要。採択されてから、未来の自分が何とかしてくれます。個人的な刺激とモチベーション向上、会社のプレゼンス向上、双方にメリットがある活動です」 インタビュー外の登壇 Cloud Infrastructure G マネージャーの辻さんもTOYOTAグループの技術コミュニティの紹介で登壇しました! Cloud Infrastructure G、辻さん:「 トヨタグループのエンジニアコミュニティ TURTLEの紹介! 」 ブース運営インタビュー 今回のブース運営には、弊社の色んな方々が手を貸してくれました。Cloud Infrastructure G・Platform G・人事 G・技術広報 G、社内の様々なGの協力の上、盛り上がったブース運営を遂行し、無事に終わらせることができました。 ブース運営のインタビューの場合、ディスカッション方式で進みまして、 Cloud Infrastructure G(CIG):古代さん、白井さん、安田さん、松尾さん 技術広報 G:村山さん が参加してくれました。 準備段階での課題 CIGでのブース運営は初めてで何をしたらいいのかわかりませんでしたが、弊社では技術広報 Gが社内外を問わず、発信力を高める組織として今回のようにイベントの企画から振り返りまで全力で手伝ってくれます。 今回も、技術広報 Gの村山さんがブース運営の準備段階からサポートをしてくれました。マネージャの辻さんと一緒に調整して成功的にブースの運営ができたキーポイントでした。 村山さん :「事前にマネージャーの辻さんと相談し、欲しい情報などを軽く伝えました。CIGの定例にて色々話を進めてくれて、シフトもいつの間にかできており大変助かりました。」 村山さん :「また、週末にスポンサーをしたカンファレンスにてシステムアーキテクチャ図のボードを展示したら評判が良く、来場者と多くのコミュニケーションを取ることができていたので、開催日前日ながら『なにか掲載できるアーキテクチャ図とかありませんか?』と提案したところ、すぐにベストなアーキテクチャ図を提供してくれました。印刷もギリギリ間に合いブースに置けましたが、コミュニケーションのきっかけになっていたので用意できてよかったなと思いました!」 どういう物がブースに惹かれることに役立つかは色んなブース運営経験なしでは出来ないことだったので、本当に貴重なアドバイスだと思います。 クラウドインフラGでは今回初めてブース運営参加した人も多く、心構えのような心理的な準備が大半でした。 白井さん :「明るく元気に、ネガティブな印象を抱かせないように意識しました。ブースに来てくれた人に対して良い印象を持ってもらうようにしてほしかったです。」 白井さんが言うようにブースに訪ねてくれる方々にポジティブな姿を見せるために努力を注ぎました。 当日の様子と気づき クラウドインフラGがCloudNative Days 2025 Winterで伝えたかったポイントは2つありました。スポンサーセッションに登壇した古代さんの話を聞くと、 古代さん :「1つ目は、クラウドインフラグループ[^1]が何をやっているかをちゃんと知ってもらうこと。2つ目は、グループの内にあるソリューションチームの活動内容について広報です。弊社は自社サービスだけでなく、トヨタグループ全体に対して多様な活動をやっている。そこを来場者のの皆さんが少しでも知ってもらいたかったです」 具体的には来場者に対して、ブースで用意されていた質問ボードに記載されている、 Q3.KINTOテクノロジーズを知っていますか? この質問を通してコミュニケーションをとりながら、クラウドインフラグループとしての活動と会社の方向性を広く認知してもらうことができました。 また、他にも重要な気づきがありまして、 古代さん :「イベント参加者全員がブースに来てくれるわけではありませんが、ブースに来て話を聞いてくれる人は、少なくともKINTOテクノロジーズに興味を持ってくれています。また、CloudNative自体に関わっていない人も一定数いることに気づきました。イベントタイトルに対してのギャップとして印象的でした」 最初はCloudNativeのイベントなので、CloudNativeエンジニアが多く参加する印象がありましたが、既にCloudNativeな活躍を実施されているエンジニアより、CloudNativeをこれから目指したいと考えている方もたくさんいる事が分かりました。実際、会場ではアプリ開発者や営業・デザイナー・記者・学生などの様々なポジションの方が参加されていました。 安田さん :「もっとたくさんの人にKINTOテクノロジーズを知ってもらおうと思っていましたが、来場していただいた方の半数は既にKINTOテクノロジーズを知ってくれていました。直近実施したイベントの 開発生産性カンファレンス や 技術書典 でKINTOテクノロジーズを知っていただいた方が多くて印象的でした」 また、CloudNativeDaysの参加者の傾向としてインフラ担当者がかなり少ないことも分かりました。アプリ担当者がインフラも兼任していることが多く、アプリコードを書きながらインフラのリソース作成やセキュリティ対応を実施するなど非常に大変だと言っていました。KINTOテクノロジーズは我々のように専門のインフラ組織やSRE/セキュリティ組織が存在しており、役割が細分化されているので、各々の専門領域に注力できているのだなと改めて強く感じてます。 質問ボードを通じて、様々な人の考え方を聞けたことが良かったとの意見もありました。質問の内容についても来場者のバックグラウンドや性格・気になるポイントによって変更したりしました。 Q1.あなたのクラウドスタイルは? → 業務スタイル & 開発スタイル Q2.あなたにとって「良いインフラ」とは? → 「良い仕事」 & 「良いシステム」 松尾さん :「ボードにある質問を深掘りして、人の考え方とか重要視していくことを聞けてよかったなと思ってます。印象に残っているのはAWS以外のクラウドサービスを触ってる人が意外と多くて、自分はAWSしか触ってないからマルチクラウドを少しでもやりたくなりました。」 様々なロールの方や、技術に対して高い興味ある方が多く参加されており、 白井さん :「多種多様なロールの方に来場していただきましたが、やはり私の専門領域以外のロールの方と話を広げるのが難しかったです。今後は幅広いロールの方と話ができるように自分の土台(知識・話術)を作っていきたいと思います」 CloudNativeだけどブース運営に関しては、単純にインフラの専門家のポジションではなくあらゆるロールの来場者を考慮して対応ができるように体制を整える必要があることを感じてます。 成果と改善点 今回の最大の成果として次のような会話があって、 古代さん :「インフラチームとカイゼンチーム、ほぼ全員がグループの運営側としてイベントに参加しました。なかなかない経験です。みんなで同じイベントの経験を共有できたのはありがたいです。イベント運営しながら『こうだよね、ああだよね』という学びを共有できました」 白井さん :「チームのみんなでイベントを開催することによって、よりチームの一体感が増しました。また、他社の人たちが実践している内容を伺うことによって新たな気づき得ることもできました。」 個人でイベントを参加することもいいことだと思いますが、チームとして参加してたらお互いが同じマインドセットを成立することができます。チームの成長と意識の向上、一緒にやることで連続性を持った技術発信の道を改めて整備ができたと思います。 一方で、改善点もありました。今回は参加者として興味あるセッションを聞いて知見を広める目的もありましたので、事前にグループ内でシフトを決めていました。 松尾さん :「シフト表を作成していましたが、自分の番になりブースに向かったらみんなブースにいたので『あれ?』と思いました」 古代さん :「次回ブースをやるときは3人はブース内で、他の人はセッション聴講してインプットできるようにした方がいいかと。セッションでブログのネタを探すなど、効率化を考える必要があります」 課題として認識したことはシフトの問題より、時間の効率化になります。CIGはブース運営者・参加者の二つの立場でイベントに参加したため、ブース運営とセッションを聞いて自らの収穫を得る間のバランス調整が難しかったと思います。 それでも、ちゃんと振り返りをしながら個々で考えていた課題を明確にすることができました。質問ボードでKINTOテクノロジーズを知っていたという答えが多かったことは、長く広報活動を実施した成果であり、イベントの運営は単発で終わることではない証でもあります。クラウドインフラGもKINTOテクノロジーズの一員として技術発信を継続していきますので、今回の参加は今後の活動のエッセンスになりました。 CloudNativeの本質 最後に、みなさんに記載いただいた質問ボードの結果を深掘りしました 白井さん :「『良いインフラとは?』という質問に対して、『愛せること』と回答した人が多かったです。深掘りしてみると、自社サービスを愛せるまで理解することが、CloudNativeという言葉の本質の理解を深めることの1つなのかもしれません」 古代さんからは、登壇でも発表したメッセージを改めて強調しました。 古代さん :「CloudNativeを最初から完璧にできている組織はありません。色々なグラデーションがあります。技術だけでなく、文化や組織も含めて作っていく必要があります。スポンサーブースで色々な企業と話しながら、改めて実感しました」 参加者インタビュー Platform G、島村さん 島村さんは、同じグループの李さんの登壇を見るため、そして自身もCFPを出していたため、どちらにしろ参加する予定でした。そして、最近チームでKubernetesやEKSを触り始めたこともあり、技術的な関心も高まっています。 印象に残ったセッション: 任天堂の事例 島村さんが最も印象に残ったのは、任天堂のセッションでした。 島村さん :「オンプレ環境の事例ですが、この文化を取り込みたいと思いました。真面目に毎日1回フルでリグレッションテストを回していて、バグ報告以外の目的でもテスト結果を使っていることに驚きました。」 特に興味深かったのは、テスト結果の多目的活用です。 島村さん :「UI的な観点で、デザイナーが表面上のデザイン単体ではなく『ビルド結果の画像から考えると、こうした方が(周りなどの雰囲気と)マッチする』という判断材料となるそうです。過去からのイベントの流れがあり、その流れで自然かどうかも分かる。声優のアテレコにも使用しているそうです。自動テストをバグを見つけるだけのものではなく、他の用途にも使う。テストの結果を使ってプロアクティブに多方面で改善点を見つけて改善していく文化です。」 そして、任天堂の事例と弊社との違いについても考察してまして、 島村さん :「KINTOにはこの文化がまだ足りないと思いました。できるようにして、気づいて、直していくという感覚が遠いです。重くなったウェブサイトは改善していく側面でも必要ですし、KINTOのサービスをより良く提供する面もあると感じました」 技術的な収穫 島村さんは、いくつかの技術的な収穫を話してくれまして、 Alloyのログ二重転送の原因の気づき :最近ブルーグリーンデプロイをした時、Alloyのログが二重転送されていた原因だと思われる事象に似ていると気付いて、調査のインプットとしました。 Dockerビルドのセキュリティ :ビルドしたコンテナイメージがマルウェアに汚染されていないか、署名や検証のフレームワークがあることを知りました。昨今の情勢もありましたので、セキュリティチームに情報を共有しました。 RCAの優位点の再確認 :インシデント管理のSaaSは、インシデント管理のやり方だけをAI化していますが、弊社では RCA で一気通貫で作っています。やはり全部統一して一気通貫しないといけないと、RCAの優位点・良かった点を見直せました。 逆に、いくつかのセッションに対して疑問を感じたことも話してくれました。 CloudNative技術が課題を解決する手段ではなく、CloudNative技術を使うための目的になっていることもあった 知識として得られるような内容ではなく、それぞれのケースに基づいた話を聞きたかった 次回への展望 島村さんは、次回への改善点と展望を語りまして、 島村さん :「早めにイベントのセッション登録をして、自分が聞きたいセッションを確実に聞けるようにしたいです。また、参加して得た情報を個人の中に留めず、他のメンバーが見れるようにする。こういうことがある、事例があると知ってもらわないと、参加した時間がもったいない。知識は、広がらないとあまり意味がないと考えています。」 登壇についても意欲を見せてくれました。 島村さん :「CFPを2回落ちているので、次は是非登壇したいです。ただ、ネタが問題です。RCAについては既に喋り、文化論も Platform Engineering Meetup で喋っています。新しいネタを見つける必要があります」 まとめ 我々はCloudNative Days 2025 Winterへの参加を通じて、多くの学びと気づきを得ることができました。 技術と文化の両輪 登壇者の古代さんと李さんは、それぞれ異なるアプローチでCloudNativeを語りました。古代さんは組織文化の観点から、李さんは技術的な実践の観点からです。しかし、両者に共通していたのは、 CloudNativeは手段であり、目的ではない というメッセージです。 ブース運営を通じて、私たちは「CloudNativeを最初から完璧にできている組織はない」ことを再確認しました。技術だけでなく、文化や組織も含めて作っていく必要があります。 参加者の島村さんが任天堂の事例から学んだように、CloudNativeは技術ではなく文化です。プロアクティブに改善点を見つけて改善していく文化、テスト結果を多目的に活用する発想、そして何より、自社サービスを「愛せる」まで理解すること。これらがCloudNativeの本質なのかもしれません。 チームの一体感 今回のイベントで最も大きな成果の一つは、インフラチームと改善チーム、ほぼ全員がグループの運営側としてイベントに参加できたことです。みんなで同じイベントの経験を共有し、学びを共有できたことは、チームの一体感を大きく高めました。他のグループの方も助けてくださり、とても良い時間を過ごす事ができました。 継続的なアウトプットの重要性 登壇者の両名が共通して感じたのは、日々のアウトプットの重要性でした。40分の発表を準備する大変さを経験し、普段からテックブログや勉強会での発表を通じて、継続的にアウトプットする習慣の必要性を実感しました。 また、島村さんが指摘したように、イベントで得た情報を個人の中に留めず、チーム・組織で共有することも重要です。知見を広げることで、組織全体の成長につながると信じてます。 次回への展望 2026年には、CloudNative会議(Platform Engineering Meetup、SRE会議、CloudNativeDaysの合同イベント)が開催されます。また、JAWS Daysへの出展も予定しています。 CloudNativeに悩む皆さんへ、古代さんからのメッセージをお伝えします。 「技術に振り回されないでください。ビジネスの成功、ビジネスの先にあるミッションの達成のために、一緒に悩みながら文化づくり、組織づくりを頑張りましょう。CloudNativeは手段であり、目的ではありません」 そして、李さんからのアドバイスも忘れないでください。 「まずは応募してみることが重要です。恐れずに、まずCFPを出してみる。採択されてから、未来の自分が何とかしてくれます」 今回のイベント参加を通じて得た学びと気づきを、今後の組織づくり、文化づくり、そして技術的な挑戦に活かしていきたいと思います。コミュニティの皆さんとの継続的な交流を通じて、共に成長していけることを楽しみにしています。 [^1]: Cloud Infrastructure Gでは記事を作成する時点で、インフラチームとカイゼンチーム、ソリューションチームの三つのチームが存在します。
この記事は KINTOテクノロジーズアドベントカレンダー2025 の10日目の記事です🎅🎄 目次 はじめに この記事の要約 作ったもの 特徴 前提条件 運用上の工夫 アーキテクチャ 実装のポイント 使い方 導入効果 まとめ はじめに こんにちは。KINTOテクノロジーズの共通サービス開発グループのエンジニア、宮下です。 AWSなどを使う現在の開発環境は、簡単に増やしたり減らしたりできる反面、環境の数が増えていきがちです。 我々の開発環境も、dev、dev2、stg、stg2...stg5、ins、prodのように、とても多くなってしまっています。 そのため、 AWS Systems Manager Parameter Store で管理する値も、環境数 × パラメータ数の組み合わせでどんどん増えていき、ケアレスミスが多発していました。 例えば以下のようなミスです。 devのParameter Storeは最新化したけれど、stgのパラメータを更新し忘れていた KEY, VALUEは正しいけれど、タグを入れ忘れていた デプロイに失敗するので調査したら、新規追加のパラメータを登録し忘れていたのが原因だった devからstgへ手作業でコピペする際、環境ごとに変えるべき値をそのままコピペしてしまった また、現在のParameter Storeの値がどうなっているかも分かりづらく、ブラウザでいちいち各環境に入って確認するのが面倒で、つい後回しになりがちでした。その結果、よりケアレスミスが起きる悪循環に陥っていました。 そこで、「ローカルのYAMLファイルに各環境のパラメータを集約し、そのファイルとAWSを同期する」という方針で自動化の仕組みを作りました。今回はそのアイデアを紹介します。 :::message 本記事では説明を簡潔にするために、代表として dev / stg / prod の3環境を例に説明します。 実際の現場ではこの他に dev2, stg2〜stg5, inte, ins, prodなど、さらに多くの環境があります。 ::: この記事の要約 10環境以上 × 50以上のパラメータ のAWS Parameter Store管理が煩雑すぎたので自動化した YAMLで全パラメータを可視化 + GitHub Actionsでワンクリック同期 更新漏れやケアレスミスをゼロにし、面倒くさい機械的なコピペ作業を無くした 作ったもの 以下の3つを組み合わせてこの仕組みを構築しました: YAMLファイル - 全環境のParameter Storeの値を一元管理 Pythonスクリプト - YAMLとAWS間の同期処理 GitHub Actions - ワンクリックで全環境に反映 特徴 1. YAML可視化 従来は各環境のParameter Storeの値を確認するために、AWSコンソールに各環境ごとにアカウントを切り替えて何度もログインする必要がありました。 今は、リポジトリにある1つのYAMLファイルを開けば、全環境の全パラメータが一覧できます。 parameters: # 環境ごとに値が異なるパラメータ - key: api/endpoint description: "APIエンドポイント" environment_values: dev: "https://dev-api.example.com" stg: "https://stg-api.example.com" prod: "https://prod-api.example.com" # 全環境で共通の値 - key: app/timeout description: "タイムアウト設定(秒)" default_value: "30" # 機密情報(SecureString) # 値はGitHub Secretsから環境変数経由で取得(例: SSM__DB__PASSWORD) - key: db/password description: "データベースパスワード" type: "SecureString" メリット: どの環境でどの値を使っているか一目瞭然 Git管理できるので変更履歴も追える PRレビューで値の間違いを事前に防げる 2. ワンクリック同期 GitHub Actions のワークフローを手動実行するだけで、全環境のParameter Storeが自動的にYAMLの内容と同期されます。 マトリクス・ストラテジー により、複数環境(dev, stg, prod)が並列で実行されるため、環境が増えても実行時間はほぼ変わりません。 AWSコンソールで環境を切り替えながらポチポチする必要がなくなりました。 前提条件 この仕組みは以下の前提で動作します。 AWS CLI がGitHub Actionsランナー上で利用できること Parameter Storeへの ssm:GetParametersByPath , ssm:PutParameter , ssm:AddTagsToResource 権限があること GitHub ActionsからAWSにアクセスできること(Access Keyもしくは OIDC など) Python 3.11 + pyyaml が利用できること :::message 本記事では簡略化のためにIAMユーザーのアクセスキーを使用していますが、本番運用ではセキュリティ向上のため OIDC (OpenID Connect) を使用したキーレス認証を推奨します。 ::: 運用上の工夫 自動化で便利になる一方、誤操作のリスクも考慮が必要です。我々のチームでは以下の工夫をしています。 SecureStringの操作権限を絞る GitHub Secretsを編集できる人を限定し、機密情報を扱える人を最小限にしています。 本番環境への反映はワークフローを分けて承認制に 本番環境のParameter Store更新時は、本番環境専用のワークフローを使い、ワークフローの中でSlackで承認ステップを挟む運用にしています。承認依頼時には更新対象のパラメータ一覧がSlackに表示されるため、「何が変わるのか」を確認してから承認できます。これにより、うっかり本番を更新してしまう事故を防いでいます。 アーキテクチャ graph TB YAML["aws-params.yml"] Secrets["GitHub Secrets (per env)"] subgraph GHA["GitHub Actions"] Workflow["3環境並列実行"] end subgraph Scripts["Python"] Update["update_aws_params.py"] end subgraph AWS["AWS Parameter Store"] dev["/dev/app/config/"] stg["/stg/app/config/"] prod["/prod/app/config/"] end YAML --> Workflow Secrets --> Workflow Workflow --> Update Update --> dev Update --> stg Update --> prod style YAML fill:#e1f5ff style Secrets fill:#fff0f0 style GHA fill:#fff4e1 style Scripts fill:#f0ffe1 style AWS fill:#ffe1e1 実装のポイント ディレクトリ構成 $ tree .github .github ├── aws-params.yml ├── scripts │ ├── aws_param_common.py │ └── update_aws_params.py └── workflows └── sync-parameters.yml YAML設計 全環境のパラメータを .github/aws-params.yml に集約しています(YAMLの例は「特徴」セクションを参照)。 SecureStringの扱い DBのパスワードなどの機密情報をYAMLにベタ書きするのはセキュリティ上NGです。 そこで、 「YAMLにはキーの定義のみ」「実体(値)はGitHub Secrets」 という役割分担を行いました。 Pythonスクリプト側で、YAMLの定義を見て type: SecureString ならば、対応する環境変数を読みに行く設計にしています。 命名規則: YAMLのkey: db/password → 環境変数名: SSM__DB__PASSWORD 環境ごとにSecureStringの値を分ける DBパスワードなどは環境ごとに異なる値を使うことが多いです。GitHub Actionsの Environments 機能を使えば、環境ごとに異なるSecretsを設定できます。 設定手順: GitHubリポジトリの Settings → Environments で環境を作成( dev , stg , prod ) 各環境のSecretsに SSM__DB__PASSWORD などを登録(値は環境ごとに異なる) ワークフローで environment: ${{ matrix.env }} を指定 これにより、DEV環境ではDEV用のDBパスワード、STG環境ではSTG用のDBパスワードが自動的に使われます。 補足:Parameter Store vs Secrets Manager 「機密情報なら Secrets Manager では?」と思う方もいるかもしれません。使い分けの目安は以下の通りです: Parameter Store (SecureString) Secrets Manager 料金 標準パラメータは無料 $0.40/シークレット/月 ローテーション 手動 自動ローテーション可能 向いているケース APIキーなど更新頻度が低いもの DBパスワードの自動ローテーションが必要な場合 多くのケースではParameter Store(SecureString)で十分で、Secrets Managerは「RDSパスワードの自動ローテーション」が必要な場合に検討してください。 :::message 補足:Secrets Managerの値も同様に管理できます。 cmd = [ "aws", "secretsmanager", "put-secret-value", "--secret-id", secret_id, "--secret-string", value ] subprocess.run(cmd, check=True) ::: Pythonスクリプト構成 aws_param_common.py - 共通機能 #!/usr/bin/env python3 """AWS Parameter Store 共通処理""" import os import sys import json import subprocess from typing import Dict, Any, Tuple import yaml def get_env_name() -> str: """環境名を取得""" env = os.environ.get("ENV_NAME") if not env: print("エラー: ENV_NAME 環境変数が設定されていません") sys.exit(1) return env def get_prefix(env: str) -> str: """環境に応じたプレフィックスを返す""" return f"/{env}/app/config/" def load_yaml_config() -> Tuple[Dict[str, Any], set]: """YAMLファイルを読み込む""" yaml_path = os.path.join(os.path.dirname(__file__), "..", "aws-params.yml") with open(yaml_path, "r", encoding="utf-8") as f: config = yaml.safe_load(f) yaml_keys = {param["key"] for param in config.get("parameters", [])} return config, yaml_keys def get_existing_params(env: str) -> Dict[str, Dict[str, Any]]: """AWS SSMから既存のパラメータを取得(ページネーション対応)""" prefix = get_prefix(env) existing_params = {} next_token = None while True: cmd = [ "aws", "ssm", "get-parameters-by-path", "--path", prefix, "--recursive", "--with-decryption", "--output", "json" ] if next_token: cmd.extend(["--next-token", next_token]) try: result = subprocess.run(cmd, check=True, capture_output=True, text=True) data = json.loads(result.stdout) params_data = data.get("Parameters", []) except subprocess.CalledProcessError as e: print(f"警告: パラメータの取得に失敗しました: {e.stderr}") return {} for param in params_data: key = param["Name"].replace(prefix, "") existing_params[key] = { "value": param["Value"], "type": param["Type"], "version": param.get("Version", 1) } next_token = data.get("NextToken") if not next_token: break return existing_params def get_param_value(param: Dict[str, Any], env: str) -> str | None: """パラメータの値を取得(SecureStringは環境変数、それ以外はYAMLの値を使用)""" # SecureStringの場合は環境変数から取得 if param.get("type") == "SecureString": env_var_name = "SSM__" + param["key"].upper().replace("/", "__") value = os.environ.get(env_var_name) if not value: print(f"警告: SecureString {param['key']} の環境変数 {env_var_name} が未設定") return None return value # 環境固有の値 env_values = param.get("environment_values", {}) if env in env_values: return str(env_values[env]) # デフォルト値 if "default_value" in param: return str(param["default_value"]) return None def validate_param(param: Dict[str, Any], env: str) -> Tuple[bool, str, Dict[str, Any] | None]: """パラメータのバリデーション""" key = param.get("key") if not key: return False, "keyが定義されていません", None value = get_param_value(param, env) if value is None: return False, f"{key}: 環境 {env} の値が定義されていません", None param_info = { "key": key, "value": value, "type": param.get("type", "String"), "description": param.get("description", "") } return True, "", param_info def update_parameter(param_info: Dict[str, Any], env: str) -> bool: """パラメータを更新""" prefix = get_prefix(env) full_name = prefix + param_info["key"] cmd = [ "aws", "ssm", "put-parameter", "--name", full_name, "--value", param_info["value"], "--type", param_info["type"], "--overwrite" ] if param_info.get("description"): cmd.extend(["--description", param_info["description"]]) try: subprocess.run(cmd, check=True, capture_output=True, text=True) add_tags(full_name, env) # タグを追加 return True except subprocess.CalledProcessError as e: print(f"エラー: {param_info['key']} の更新に失敗: {e.stderr}") return False def add_tags(parameter_name: str, env: str) -> bool: """パラメータにタグを追加""" cmd = [ "aws", "ssm", "add-tags-to-resource", "--resource-type", "Parameter", "--resource-id", parameter_name, "--tags", f"Key=Environment,Value={env}", "Key=SID,Value=backend-api" ] try: subprocess.run(cmd, check=True, capture_output=True, text=True) return True except subprocess.CalledProcessError as e: print(f"警告: タグの追加に失敗: {e.stderr}") return False ポイント: get_existing_params : ページネーション対応で50件以上のパラメータも取得可能 get_param_value : SecureStringは環境変数から、通常パラメータはYAMLから値を取得 update_parameter : パラメータ更新後に add_tags を呼び出してタグを付与 タグについて パラメータ作成時に、自動でタグを付与します。タグはAWSコンソールでの検索やコスト管理に便利なだけでなく、システムによってはタグがないとパラメータを読み込めない場合もあります。 タグ 値 説明 Environment dev , stg , prod 実行時の環境名が自動で入る SID backend-api サービス識別子(自分のサービス名に置き換えて使用) update_aws_params.py - 更新スクリプト #!/usr/bin/env python3 """AWS Parameter Store 更新スクリプト""" import sys import aws_param_common as common def update_parameters(): """パラメータを更新し、結果をレポートする""" env = common.get_env_name() print(f"=== 環境: {env} ===") print(f"プレフィックス: {common.get_prefix(env)}") print() config, yaml_keys = common.load_yaml_config() existing_params = common.get_existing_params(env) print(f"既存パラメータ数: {len(existing_params)}") print() updated_params = [] skipped_params = [] failed_params = [] for param in config.get("parameters", []): is_valid, error_msg, param_info = common.validate_param(param, env) if not is_valid: print(f"[スキップ] {error_msg}") continue param_key = param_info["key"] value = param_info["value"] # 既存の値と比較 if param_key in existing_params: if existing_params[param_key]["value"] == value: print(f"[スキップ] {param_key}: 値に変更なし") skipped_params.append(param_key) continue print(f"[更新] {param_key}: 値を更新します") else: print(f"[新規] {param_key}: 新規パラメータを追加します") # パラメータを更新 success = common.update_parameter(param_info, env) if success: updated_params.append(param_key) print(f" ✓ 完了") else: failed_params.append(param_key) print(f" ✗ 失敗") # 結果サマリー print() print("=== 結果サマリー ===") print(f"更新: {len(updated_params)} 件") print(f"スキップ(変更なし): {len(skipped_params)} 件") print(f"失敗: {len(failed_params)} 件") if failed_params: print() print("失敗したパラメータ:") for key in failed_params: print(f" - {key}") sys.exit(1) print() print("✓ 正常終了") if __name__ == "__main__": update_parameters() ポイント: 値が変わっていないパラメータはスキップ(無駄な更新を防ぐ) 更新結果を統計情報として出力 失敗時は終了コード1で終了 GitHub Actionsワークフロー name: Sync AWS Parameter Store on: workflow_dispatch: # 手動実行 jobs: sync-parameters: runs-on: ubuntu-latest strategy: matrix: env: [dev, stg, prod] environment: ${{ matrix.env }} # 環境ごとのSecretsを使用 steps: - name: Checkout repository uses: actions/checkout@v4 - name: Setup Python uses: actions/setup-python@v5 with: python-version: '3.11' - name: Install dependencies run: pip install pyyaml - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v4 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ap-northeast-1 - name: Sync Parameters env: ENV_NAME: ${{ matrix.env }} # SecureString用(環境ごとのGitHub Secretsから取得) SSM__DB__PASSWORD: ${{ secrets.SSM__DB__PASSWORD }} SSM__API__SECRET_KEY: ${{ secrets.SSM__API__SECRET_KEY }} run: | cd .github/scripts python update_aws_params.py ポイント: strategy.matrix で複数環境を並列実行 environment: ${{ matrix.env }} で環境ごとのSecretsを使用(devとprodで異なるDBパスワードなど) SecureStringの値は環境変数経由でスクリプトに渡す 値に変更がないパラメータは自動的にスキップされる 使い方 1. パラメータの追加・変更 .github/aws-params.yml を編集してPRを出すだけです。 parameters: # 新しいパラメータを追加 - key: feature/enable_payment_v2 description: "新決済システムの有効化" environment_values: dev: "true" stg: "false" prod: "false" 2. 全環境への反映 GitHub Actionsページを開く Sync AWS Parameter Store を選択 Run workflow ボタンをクリック 全環境に並列で反映される 3. SecureStringパラメータの追加 YAMLに定義を追加: - key: payment/api_key description: "決済APIキー" type: "SecureString" GitHub Environmentsに値を登録: Settings → Environments → 各環境(dev, stg, prod)のSecretsに登録 Secret名: SSM__PAYMENT__API_KEY 値: (環境ごとに異なる実際の値) ワークフローファイルの環境変数セクションに追加: env: SSM__PAYMENT__API_KEY: ${{ secrets.SSM__PAYMENT__API_KEY }} 4. 実演 GitHub Actions画面から今回作ったアクションを選んで、起動します。 アクションが正常終了したことを確認します。各環境が並列で動作した事がわかります。 AWSのパラメータストア画面を開いて確認してみます。パラメータが登録されています。成功です。 導入効果 具体的な効果 作業時間 : 環境数 × 5分 → ワンクリック (10環境なら50分削減) 更新漏れ : 月数回発生 → ゼロ 確認作業 : AWSコンソールを開く → YAMLを見るだけ まとめ クラウド時代の「環境が増えすぎ問題」は、多くの現場で直面している課題だと思います。 今回紹介したアイデアのポイントは: YAML可視化 - 全環境のパラメータを1ファイルで管理 ワンクリック同期 - GitHub Actionsで自動反映 SecureString対応 - 機密情報も安全に管理 特別な技術は使っておらず、 GitHub Actions + Python + AWS CLI だけで実現できます。 Parameter Storeの管理で困っている方、環境が増えて運用が大変になっている方の参考になれば幸いです。 最後までお読みいただき、ありがとうございました🙇‍♂️
This article is Day 10 of the KINTO Technologies Advent Calendar 2025 🎅🎄 Introduction I'm Liu (YOU), an Infrastructure Architect in the Cloud Infrastructure Group (CIG) at KINTO Technologies. Starting in November, I've also taken on responsibilities in the Developer Relations Group. In November 2025, our company participated in " CloudNative Days 2025 Winter " as a sponsor. At this event, two of our colleagues gave presentations, the Cloud Infrastructure Group and the Developer Relations Group that I belong to operated the sponsor booth, and many members attended technical sessions, allowing the entire organization to be actively involved. CloudNative Days is the largest event in Japan's cloud-native community. Through this participation, we not only deepened our technical knowledge but also had the opportunity to reconsider the very concept of cloud-native itself. In this article, I'll share the event experience and learnings from the perspectives of speakers, booth operators, and general attendees. Speaker Interviews Koshiro from Cloud Infrastructure Group: " Building the Cloud Foundation for the Future of Mobility Platforms " How I Came to Speak Koshiro : "Having been with the company for less than a year, I didn't know the organization's history or the reasons behind our technology choices. Conveying things I hadn't experienced firsthand was the biggest challenge." Originally, another member was scheduled to speak, but circumstances led to him stepping in at short notice. Having joined in January 2025, this was a challenge for him without fully understanding the organization's history or the background of our technology decisions. Background on Topic Selection He struggled with cloud‑native as a topic. Looking into available resources, he found that many talks went deep into Kubernetes and container technologies. Since our company mainly uses ECS and only uses Kubernetes in limited areas, he couldn’t fully relate. Eventually, he realized that this struggle itself was worth sharing with others who are in the same situation. Koshiro : "Cloud‑native may feel like a high‑level concept and getting there requires organizational trial and error. Technical excellence is important but building a cloud‑native culture within the organization is more important. There is no single best practice." What I most wanted to convey was that cloud-native is a means, not an end . We select appropriate technologies while facing our business needs. By sharing our history of trial and error as it really happened, I hoped to give others facing similar challenges a chance to move forward. Audience Reactions on the Day Venue C, with a capacity of 66 people, was nearly full. Many attendees who had been watching other sessions online moved to this session midway through. Koshiro : "There were people nodding along as they listened, and some took photos of my slides to post on X. At an event where technology seems heavily emphasized, it was striking to see people show interest in my topic." Two people asked questions at the microphone, and three visited "Ask the Speaker," giving me a strong sense of accomplishment for my first presentation. What stayed with me most were the questions about Terraform structure and the platform organization's decision-making. These are questions without definitive answers and I was reminded that everyone struggles with these things . Lessons Learned This was a substantial 40-minute presentation, and through the intensive preparation and practice, Koshiro-san realized how important regular output truly is. Koshiro : "I realized that if I had been giving a presentation regularly, creating slides would have been much easier. If I'd been writing tech blogs, I could have adapted and utilized that content. I've resolved to work harder on my output." He also gained an important insight about using AI. From his initial failed attempt to create a talk script with AI, he learned this lesson: "First establish what message you want to convey, then ask AI how to express it. Never start by asking AI. It's a recipe for failure." Looking Ahead For next time, he wants to build experience with shorter 20-minute presentations and also challenge himself to present more technology-focused topics. Additionally, since it's a community event, he expressed a desire to deepen connections with participants through group work and mutual learning. Koshiro : "Next year, we'll be hosting a cloud-native conference. KINTO Technologies is one of the most advanced organizations within the Toyota Group when it comes to cloud adoption. While we don't have everything figured out yet, we've reached a stage where we can build high-level solutions together. I'd be happy to see more opportunities for collaboration and study sessions." Lee-san from Platform G: " A New Era of Alert Response Pioneered by AI Agents " The Decision to Submit Proposal to CFP Lee-san submitted a proposal to CFP with a "let's just try" attitude, thinking the chances of acceptance were low. The reasons for applying were clear: to enhance the company's external communication power, contribute to engineer recruitment within the group, and gain opportunities for external communication. Since the submission was completely separate from sponsor work, being accepted came as a surprise. Struggles with Material Preparation He struggled most with determining the right skill level for the audience when creating the materials. Lee : "With both experts and beginners in the audience, I struggled to decide what level to aim for. I wanted the content to be easy to understand even for those unfamiliar with the topic, but if I made it too light, it wouldn’t satisfy people looking for deeper knowledge. Striking that balance was the hardest part." I particularly focused on storytelling. I was conscious of the flow: "there was this challenge → we responded this way → the result was this → now we're at this point," and reviewed the overall structure multiple times to make the narrative flow naturally. Material preparation took over a week, continuously improving the script and presentation. Unexpected Events On the day, his biggest concern was whether PowerPoint's script feature would be visible on the audience's screen. For a 40-minute presentation, going without notes would be tough, so during lunch he went to the venue myself to ask for a quick run‑through. Lee : "They provided basic information for speakers, such as arrival times and HDMI connection details, but there should have been more guidance on things like rehearsals and checking script display. For our members who present at future events, I’d recommend visiting the venue in advance to confirm these details themselves." Audience Response The presentation was well-received overall, with fellow speaker Koshiro-san commenting that it was "the most impressive session of the day." After the presentation, 4-5 people came with questions, and Lee-san said he could feel the high interest in AI Agents. What stood out to him most was a question about context engineering: How do you distinguish between information needed for AI and information needed only by humans but not by AI? He shared the countermeasures currently under consideration for this question as well. Lee : "There's the issue of LLM model input limitations, and if the context gets too large, it exceeds the limits. We plan to address this with a single-agent configuration, verifying a method to summarize and compress history using LangChain's new features. I want to talk about these improvements at next year's conferences or in technical articles." Lessons Learned For him, this was the first time speaking at a large-scale open community event, so there was a lot to gain. Lee : "I was nervous, but I found that there was no need to be as scared as I was. If there are people who want to try, I recommend giving it a shot. I was greatly inspired from other speakers and participants, and my technical motivation increased." In terms of technical takeaways, he found the presentations on incident‑management SaaS and CyberAgent’s Ōyama-san’s talk on Loki and Prometheus particularly insightful. He also gained a few dozen new followers on X, which helped broaden his connections within the community. Looking Ahead There are areas for improvement regarding time management. When he practiced his presentation, he noticed that he finished earlier than expected. However, during the actual presentation, he got nervous and couldn’t get the words out. He ended up running short on time and had to skip a page. Next time, he is thinking of giving a talk on improving context engineering and methods for evaluating agents. Lee : "It’s difficult to evaluate the effectiveness of an agent because creating proper evaluation criteria is challenging. Even when alerts seem to be the same, the underlying causes can differ, which makes it hard to build accurate ground‑truth data. This is widely recognized as a common issue across the industry. Context engineering is a field that has recently been gaining attention, but best practices have yet to be established. I believe this is a topic many people are eager to learn about." His advice is clear. Lee : "What matters most is simply applying. Once you get accepted, your future self will figure it out. It boosts your motivation and inspiration, and it also helps raise your company’s presence, benefiting both sides." Other Speakers Tsuji-san, the Manager of Cloud Infrastructure Group, also gave a talk about the Toyota Group's technical community! Tsuji-san from Cloud Infrastructure Group: " Introducing TURTLE, the Toyota Group Engineer Community! " Booth Operation Interview Many people from our company helped with this booth operation. With cooperation from various groups including Cloud Infrastructure Group, Platform Group, HR Group, and Developer Relations Group, we were able to run an exciting booth operation and complete it successfully. For the booth operation interview, we proceeded in a discussion format, with participation from: Cloud Infrastructure Group (CIG): Koshiro, Shirai, Yasuda, Matsuo Developer Relations Group: Murayama Challenges in the Preparation Stage This was CIG's first time operating a booth, so we didn't know what to do, but our company has the Developer Relations Group that fully supports events like this from planning to reflection, enhancing both internal and external communication power. This time too, Murayama-san from the Developer Relations Group provided support from the booth preparation stage. Her collaboration with Manager Tsuji-san was a key factor in successfully running the booth. Murayama : "I consulted with Manager Tsuji-san in advance and briefly communicated what information we wanted. Things progressed through CIG's regular meetings, and before I knew it, the shift schedule was ready, which was very helpful." Murayama : "Also, at a conference we sponsored over the weekend before the event, we displayed a board featuring our system architecture diagram, which was very well received and helped us have many conversations with attendees. So, even though it was the day before the event, I suggested, "Do you have any architecture diagrams we could display?" and they immediately provided the perfect architecture diagram. We barely made it in time for printing, but we managed to have it at our booth. Since it served as a great conversation starter, I'm really glad we were able to prepare it!" I felt the advice was truly valuable, because understanding what attracts people to a booth is something you can’t really grasp without having run many booths yourself. For Cloud Infrastructure Group, many people participated in booth operation for the first time, so most of it was about preparing ourselves to get into the right mindset. Shirai : "I made a conscious effort to stay cheerful and energetic so as not to give off any negative impression. I wanted visitors to have a good impression of our booth." As Shirai-san said, we put a lot of effort into presenting a positive attitude to the people who visited our booth. Observations and Insights on the Day Cloud Infrastructure Group had two main points they wanted to convey at CloudNative Days 2025 Winter. According to Koshiro-san, who spoke at the sponsor session: Koshiro : "First, we wanted people to know what the Cloud Infrastructure Group[^1] does. Second, it was about publicizing the activities of the Solutions Team within our group. Our company does various activities not only for our own services but for the entire Toyota Group. We wanted visitors to know a little about it." Specifically, we communicated with visitors through the question board prepared at the booth: Q3. Do you know KINTO Technologies? Through this question, we were able to broadly communicate our activities as Cloud Infrastructure Group and the company's direction while engaging in conversation. There were also other important insights: Koshiro : "Not all event participants come to the booth, but those who do come and listen are at least interested in KINTO Technologies. Also, I noticed that a certain number of people aren't involved in cloud-native itself. This gap between the event title and the actual attendees stood out to me." Initially, we had the impression that many cloud-native engineers would participate since it was a cloud-native event, but we found that there were more people who want to pursue cloud-native in the future than engineers already doing cloud-native work. In fact, the venue had people from various backgrounds, including app developers, sales representatives, designers, reporters, and students. Yasuda : "I wanted more people to know about KINTO Technologies, but half of the visitors already knew about our company. It was amazing that many people knew about KINTO Technologies from recent events like the Developer Productivity Conference and Gijutsushoten ." We also found that CloudNativeDays participants include very few infrastructure specialists. Many people said that app developers often also handle infrastructure responsibilities, and it's very challenging to write application code while also creating infrastructure resources and handling security. KINTO Technologies has dedicated infrastructure and SRE/security teams like ours, with clearly divided roles, so I strongly feel once again that we can focus on our respective areas of expertise. There were also opinions that it was good to hear various people's perspectives through the question board. We adjusted our questions depending on visitors' backgrounds, personalities, and points of interest. Q1. What's your cloud style? → Work style & Development style Q2. What is "good infrastructure" to you? → "Good work" or "Good system" Matsuo : "I'm glad we could go beyond the questions on the board and hear about people's perspectives and what they prioritize. What left an impression was that surprisingly many people work with cloud services other than AWS. Since I've only used AWS, it made me want to try multi-cloud." Many people with various roles and a strong interest in technology participated: Shirai : "We had visitors with diverse roles, and it was difficult to have deeper conversations with people in roles outside my area of expertise. Going forward, I want to build my foundation (knowledge and communication skills) so I can talk with people in a wide range of roles." Even for CloudNative booth operations, I feel we need to prepare a system that can handle visitors of all roles, not just infrastructure specialist positions. Results and Improvements As one of the biggest achievements this time, we had this conversation: Koshiro : "Almost everyone in the Infrastructure Team and Kaizen Team participated in the event as our group's operators. It's quite a rare experience. I'm grateful we could share the same event experience. While running the event, we were able to share learnings with each other like 'this is how it works' or 'that's how it should be.'" Shirai : "By holding an event with the whole team, the team's sense of unity increased even more. Also, by hearing about what other companies are practicing, we could gain new insights." Participating individually in events is good, but when participating as a team, you can establish the same mindset with each other. I believe we were able to foster team growth and raise awareness, and by working together, we could once again establish a path for continuous technical outreach. On the other hand, there were also areas for improvement. This time, we also had the purpose of listening to sessions we were interested in as participants to broaden our knowledge, so we created a shift schedule within the group in advance. Matsuo : "We created a shift schedule, but when it was my turn and I headed to the booth, I was surprised that everyone was at the booth." Koshiro : "Next time we run a booth, it would be better to have 3 people at the booth while others attend sessions for input. We need to think about ways to be more efficient, like finding blog topics at sessions." What we recognized as an issue wasn't the shift problem but time efficiency. Since CIG participated as both booth operators and attendees, I think it was difficult to balance between running the booth and gaining our own takeaways by attending sessions. Still, by reflecting properly, we managed to bring clarity to the challenges each of us had in mind. Many visitors indicated on the question board that they already knew KINTO Technologies which is a clear result of our ongoing promotional efforts and proof that events aren't just one-time things. The Cloud Infrastructure Group will keep contributing to KINTO Technologies' technical outreach, and this experience will be a key ingredient for our future endeavors. The Essence of Cloud-native Finally, we explored in detail the results of the question board filled out by everyone. Shirai : "For the question 'What is good infrastructure?', many people answered, 'Something you can be passionate about.' Exploring it further, understanding your own service to the point where you can love it might be one way to deepen the understanding of the essence of cloud native." Koshiro-san re-emphasized the message he delivered in his talk: Koshiro : "No organization has cloud-native perfectly figured out from the start. There are various gradations. It's necessary to build not just the technology, but also the culture and organization. Talking with various companies at the sponsor booths, I felt this anew." Attendee Interview Shimamura from Platform Group Shimamura-san planned to attend to see Lee's presentation from the same group, and also he had submitted a CFP himself. Additionally, his team had recently started working with Kubernetes and EKS, so the team's technical interest was growing. Sessions that stood out: Nintendo's Case Study Shimamura-san was amzaed by Nintendo's session. Shimamura : "It was an on-premise case study and I wanted to incorporate this culture. They run full regression tests once a day, and I was surprised they use test results for purposes other than bug reporting." What was particularly interesting was the multi-purpose use of test results. Shimamura : "From a UI perspective, designers don't just look at surface-level design alone but use it as decision-making material like 'considering the build result images, this would (match the surrounding atmosphere) better.' There's a flow of events from the past, and you can tell if it's natural within that flow. They also use it for voice actor dubbing. Using automated testing not just for finding bugs, but for other purposes too. It's a culture of proactively finding and improving points across multiple fronts using test results." And he also reflected on the differences between Nintendo's case and our company: Shimamura : "I felt that KINTO still lacks this culture. This mindset of making things possible, noticing issues, and fixing them doesn't come naturally to us yet. I felt it's necessary not only for improving websites that have become heavy, but also for delivering KINTO's services better." Technical Gains Shimamura-san shared several technical gains: Realizing the cause of Alloy log double-forwarding : When we recently did blue-green deployment, I noticed something similar to what I thought was the cause of Alloy logs being double-forwarded and used it as input for investigation. Docker build security : I learned there are frameworks for signatures and verification to check if built container images are contaminated with malware. Given recent circumstances, I shared this information with the security team. Reconfirming RCA's advantages : While incident management SaaS solutions only apply AI to incident management processes, our company has built an end-to-end solution with RCA. This reaffirmed the advantages and benefits of RCA: that everything must be unified and handled end-to-end. Conversely, he also shared some questions he felt about certain sessions: In some cases, cloud-native technology was becoming the purpose rather than a means to solve problems I wanted to hear case-specific stories rather than general knowledge Looking Ahead Shimamura-san shared improvement points and outlook for next time: Shimamura : "I want to register for event sessions early so I can make sure I attend the ones I’m interested in. Also, instead of keeping the information I gain to myself, I want to make it accessible to other team members. If people don’t know what happened or what examples I found, then the time I spent participating would feel wasted. I believe knowledge doesn’t mean much unless it’s shared and spread." He also showed interest in giving a talk: Shimamura : "My CFP submission was rejected twice, so I definitely want to give a talk next time. However, topics are the problem. I've already talked about RCA, and culture theory at Platform Engineering Meetup . I need to find new topics." Conclusion Through our participation in CloudNative Days 2025 Winter, we gained many learnings and insights. Technology and Culture as Two Wheels Speakers Koshiro-san and Lee-san each talked about cloud-native from different approaches. Koshiro-san from the perspective of organizational culture, Lee-san from the perspective of technical practice. However, what both had in common was the message that cloud-native is a means, not an end . Through booth operation, we reconfirmed that "no organization deploys cloud-native perfectly from the start." We need to build not just technology, but culture and organization as well. As attendee Shimamura learned from Nintendo's case, cloud-native is a culture, not a technology. A culture of proactively finding and improving points, the idea of using test results for multiple purposes, and above all, understanding your own service to the point where you can "love" it. These might be the essence of cloud native. Team Unity One of the biggest achievements of attending this event was that the Infrastructure Team and Kaizen Team—almost everyone—could participate as group operators. Being able to share the same event experience and learnings together greatly increased the team's sense of unity. People from other groups also helped us, and we were able to have a very good time. The Importance of Continuous Output What both speakers commonly felt was the importance of daily output. Having experienced the difficulty of preparing a 40-minute presentation, they realized the need for a habit of continuous output through tech blogs and study session presentations. Also, as Shimamura-san pointed out, it's important not to keep information gained at events to yourself, but to share it with the team and organization. We believe that spreading knowledge leads to organizational growth as a whole. Looking Ahead In 2026, the cloud-native conference will be held (a joint event of Platform Engineering Meetup, SRE Conference, and CloudNativeDays). We also plan to exhibit at JAWS Days. To everyone struggling with cloud-native, here's a message from Koshiro-san: "Don't be driven by technology. Let's work together on culture-building and organization-building, striving together for business success and achieving the mission beyond business. Cloud-native is a means, not an end." And don't forget Lee-san's advice: "It's important to submit an application first. Don't be afraid. Just submit papers. Once you're accepted, your future self will figure it out somehow." We hope to apply the learnings and insights gained through this event participation to future organization-building, culture-building, and technical challenges. We look forward to growing together through continuous interaction with the community. [^1]: At the time of writing this article, Cloud Infrastructure Group consists of three teams: the Infrastructure Team, Kaizen Team, and Solutions Team.