ナミスマート合同会社

固定費ゼロで越境ECを動かす Cloudflare スタック

CloudflareAstroECアーキテクチャ

商品数が数十点の小さなショップに、月額数万円の EC プラットフォーム利用料は重すぎます。 あるくとまるでは、Cloudflare の従量課金と Stripe の決済手数料以外に 固定費がかからない構成を採りました。その内訳を書きます。

役割分担

採用技術なぜ
ストアフロントAstro(静的生成)+ React商品ページを完成済み HTML で配信。SEO と初期表示に効く
管理画面Vite + React(SPA)社内向けなので SEO 不要。Cloudflare Access で保護
APIHono / Cloudflare Workersリクエストが来た分だけ課金。アイドル時のコストがない
DBCloudflare D1(SQLite)商品数十点・低トラフィックには十分。専用インスタンス不要
画像Cloudflare R2下り転送(エグレス)が無料
決済Stripe月額固定なし、決済手数料のみ

ポイントは、アイドル時にお金が減る箇所を 1 つも持たないことです。売れない月の インフラ費用は限りなくゼロに近づきます。

静的生成と SPA を混ぜる

全部 SPA にする必要も、全部静的にする必要もありません。判断は単純です。

  • 検索エンジンに読ませたいページ → 静的生成(商品・記事・LP)
  • ログインした人しか見ないページ → SPA(管理画面・マイページ)

商品ページを静的生成にしておくと、クローラは JavaScript の実行を待たずに 完成した HTML を受け取れます。CDN のエッジから返るので、地球の裏側からのアクセスでも 速い。越境 EC では、この差がそのまま機会損失の差になります。

型を API とフロントで共有する

API は REST ですが、フロントからは Hono の型付き RPC クライアント(hc<AppType>)で 呼びます。ハンドラをメソッドチェーンで書いている限り、API の型定義がそのまま フロントに届き、エンドポイントの変更はビルド時に壊れて教えてくれます。

const res = await client.api.products[':id'].$get({ param: { id } });
// res の型は API 側のハンドラから導出される

壊れてはいけない場所だけ、厚くする

固定費を削るからといって、全部を薄く作るわけではありません。EC で最悪なのは 「支払いは通ったのに、その後の処理が落ちた」状態です。

そこで Stripe Webhook 起点の副作用処理だけは厚く作りました。処理はリース獲得方式で 排他し、各ステップが自分専用の永続マーカーを持つ冪等な単位になっています。 途中で失敗しても、再実行すれば残りのステップだけが進む。ここは薄く作ってはいけない 場所だと判断しました。

固定費を持たない構成は、手を抜くことではなく、お金をかける場所を選ぶことです。


ナミスマート合同会社

事業の課題を、いちばん小さく速い形で解決する。開発のご相談はお問い合わせからどうぞ。