Skip to main content

第04章:前提② 非同期ってなに?(なんで必要?)⏱️🧩

この章のゴール 🎯✨

  • 「同期(待つ)」と「非同期(待たない)」の違いを、感覚でつかむ🙂
  • 非同期が必要になる理由(遅い・落ちる・混む)を、現実の失敗込みで理解する😇💥
  • 「失敗や遅延がある世界」で壊れにくくするための、基本の考え方を覚える🧯🔁

1) 同期(待つ)と非同期(待たない)って?⚖️

✅ 同期(synchronous)

async 「処理Aが終わるまで、次に進まない」🧍‍♀️⏳ 例:注文確定ボタン → メール送信が終わるまで画面が待つ📩⌛

  • 👍 分かりやすい
  • 👎 遅い処理があると、全部が遅くなる
  • 👎 外部が落ちると、巻き込まれて失敗しやすい

✅ 非同期(asynchronous)

「処理Aは“お願いだけ”して、次に進む」🏃‍♀️💨 例:注文確定ボタン → “送る予定”を記録してすぐ完了 → メール送信は後で📦📤

  • 👍 画面が速い(待たない)✨
  • 👍 外部が落ちても、業務は守りやすい🛡️
  • 👎 “あとでやる”分、設計が必要(ここが腕の見せ所)🧠🔧

2) 「非同期が必要」になる3つの現実 😇🌧️

現実①:外部サービスは遅い(しょっちゅう待たされる)🐢

メール、決済、配送、通知、他社API… 自分のアプリの外は、だいたい遅い&不安定になりがち📡⚠️

現実②:外部サービスは落ちる(たまにじゃない、普通にある)💥

  • 一時的なネットワーク断🌧️
  • 相手側の障害🧯
  • たまたまタイムアウト⌛

「落ちる前提で設計する」が強い💪

現実③:アクセスは波がある(混むと全部が詰まる)🌊

同期で外部呼び出しを抱えると、混雑時にこうなりがち👇

  • リクエストが詰まる🚧
  • タイムアウト増える⌛💥
  • 再試行でさらに混む🔁🔥(地獄ループ)

3) 同期でやると起きやすい“事故”を見てみよう😵‍💫💥

例:注文確定 → 「注文DB更新」+「メール送信」

❌ 同期パターン(巻き込まれやすい)

  • 注文DB更新 ✅
  • メール送信 ❌(タイムアウト)
  • 画面はエラー表示 😭
  • でもDBは更新済み…?(設計次第でねじれる)🌀
[ユーザー] ──注文確定──▶ [API]
[API] ──DB更新(成功)──▶ [DB] ✅
[API] ──メール送信──▶ [外部メール] ❌(遅延/失敗)
[API] ──エラー返す──▶ [ユーザー] 😭

ここで起きるのが、まさにOutboxが防ぎたい世界観📦🛡️ (「業務更新は成功したのに、通知だけ落ちた」みたいなやつ)📭


4) 非同期にすると“何が嬉しい”の?🌈✨

✅ ① 画面が速くなる(待たない)⚡

ユーザー体験が良くなる🙂✨ 「送信」ボタン押して10秒固まるの、つらいよね🥹

✅ ② 業務を守れる(外部の障害から切り離す)🛡️

外部が落ちても、注文確定そのものは成立させやすい✅ 通知は「あとで確実に送る」にできる📦📤

✅ ③ リトライ設計がしやすい(失敗は“あとで回収”)🔁

一時的に失敗したら、あとで再送すればOK🙆‍♀️ この「再送前提」が超重要😇


5) 「非同期=別スレッド?」って思いがち問題🧠🌀

よくある誤解👇

  • 「非同期にしたらCPU処理が速くなる!」🚀(←だいたい違う)
  • 「非同期=並列で勝手に動く!」👯‍♀️(←設計しないと勝手には守ってくれない)

ここでの“非同期”は主にこういう意味🙂

  • 待ち時間(I/O)を抱えない(外部呼び出し・ネットワーク・DBなど)📡
  • 処理を分ける(今やる/あとでやる)✂️
  • 失敗の回収ルートを用意する(リトライ・隔離)🧯

6) リトライ前提の心構え 😇🔁(ここが最重要)

非同期世界では、こう考えるのが強い👇

✅ 失敗は「ゼロにする」より「回収する」🧯

  • 失敗は起きる(前提)
  • 起きたら、再実行できる設計にする
  • それでもダメなら、人が直せる場所に隔離する(後の章でDead Letter)📮

✅ 失敗は大きく3種類で考えるとラク🙂

  1. 一時的:ネットワーク不安定、相手が一瞬落ちた🌧️ → リトライで治る可能性大
  2. 恒久的:データ不正、送信先が存在しない🧱 → 何回やっても無理
  3. 仕様的:その状態では送っちゃダメ🚫 → ロジック修正が必要

7) “Outboxにつながる”非同期の基本パターン📦📨

「今やること」と「あとでやること」を分ける✨

  • 今:注文を確定する🛒✅
  • 今:“送る予定”を保存する📦🧾
  • あとで:保存した“送る予定”を拾って送る📤⏱️
(今)   [API] ──注文DB更新+送る予定を保存──▶ [DB] ✅✅
(今) [API] ──すぐ成功返す──▶ [ユーザー] 🙂✨

(あと) [送信係] ──送る予定を取得──▶ [DB]
(あと) [送信係] ──外部へ送信──▶ [外部] 📩

この「送る予定」こそが Outbox の芯📦🧠 (まだ深掘りしないけど、“非同期の考え方”としてここで覚えるのが大事)✨


8) ミニコードで感覚をつかむ🧪✨(TypeScript)

❌ 同期で外部通知まで待つ例(遅い&落ちると巻き込まれる)😵‍💫

async function placeOrderAndNotify(input: { userId: string; items: string[] }) {
// 1) 注文を保存(成功したとする)
const orderId = await saveOrderToDb(input);

// 2) 外部通知(ここが遅い・落ちる…)
await sendEmailViaExternalService({
toUserId: input.userId,
subject: "注文確定",
body: `注文ID: ${orderId}`,
});

return { orderId };
}

この関数の弱点👇

  • 外部通知が遅いと、注文処理全体が遅い🐢
  • 外部通知が失敗すると、注文自体を失敗扱いにしがち😱
  • “成功したのに失敗に見える”が起きやすい🌀

✅ 非同期で「送る予定」を残す例(“あとで送る”)📦📤

type OutboxEvent = {
id: string; // 例: UUID
eventType: "OrderPlaced";
payload: unknown; // 後の章で「壊れにくいJSON」にする
createdAt: string; // ISO文字列など
};

async function placeOrder(input: { userId: string; items: string[] }) {
// ここでは「注文保存」と「Outbox追加」をセットでやる(後の章で深掘り)
const result = await runInTransaction(async (tx) => {
const orderId = await tx.saveOrder(input);

const evt: OutboxEvent = {
id: crypto.randomUUID(),
eventType: "OrderPlaced",
payload: { orderId, userId: input.userId },
createdAt: new Date().toISOString(),
};

await tx.insertOutbox(evt);

return { orderId };
});

// ここで外部通知はしない!すぐ返す🙂✨
return result;
}

ポイントはこれ👇

  • 「外部に送る」は 別の“送信係” がやる📤
  • 送信係は、Outboxから拾って送る🔁
  • 失敗してもリトライできる(設計できる)🧯

9) “送信係”ってどんなもの?👩‍🏭📤(イメージだけ)

世の中には「非同期実行」のための選択肢が色々あるよ🙂✨

  • Redisを使ったジョブキュー(例:BullMQ)📮⚙️(最近も継続的にリリースあり)(GitHub)
  • ワークフロー基盤(例:Temporal の TypeScript SDK)🧬⏱️(SDKも更新が続いてる)(GitHub)

この教材ではまず「考え方」を固めて、あとで実装に落としていくよ🪜✨


10) 🤖 AI活用ミニコーナー(コピペで使える)✨

✅ 「同期→非同期」に分ける相談プロンプト📝

あるユースケースの処理手順を貼るので、 “今やるべき処理” と “あとでやるべき処理(非同期)” に分けて、理由も添えてください。 さらに、外部失敗時のリトライ方針(回数・間隔・恒久失敗の扱い)も提案してください。

✅ 「失敗パターン洗い出し」プロンプト🧯

この外部連携(メール送信/通知/他社API呼び出し)で起こり得る失敗を、 一時的/恒久的/仕様的 の3種類に分類して、対処案を箇条書きで出してください。


11) 最新事情メモ(この章に関係するところだけ)🗓️✨

  • TypeScript のリリースノートは 5.9 系として更新が続いているよ(ドキュメント更新日が 2026-02-02)(TypeScript)
  • Node.js は 24 系が Active LTS、22/20 系が Maintenance LTS など、複数ラインが並走してる(2026年1月時点のステータス表)(Node.js)

まとめ 🎀✅

  • 非同期は「待たない」だけじゃなく、外部の失敗を業務から切り離すための武器🛡️
  • 失敗は起きる前提で、回収(リトライ・隔離)できる設計にするのが強い🧯🔁
  • Outbox は「あとで送る」を成立させるための、超実用的な土台📦✨