サーバーレスリレーを作ろうとした話
2025-12-06
この記事は、Nostr Advent Calendar 2025の6日目の記事です。5日目はロクヨウさんより『Nostrに居ない人向けの記事』、7日目はぱぶいさんより『なんか書く』です。
プロローグ
- Apple Watchを買った
- 特に休日、こどもの前でスマホを触る頻度が減って大変満足だが、Nostrが遠くなった
- Watchでも何かしらほどほどにNostrで遊びたいが、NostrクライアントアプリをWatch向けに実装するというのはいろいろと非現実的
- とりあえずリレー立てれば、自前で何かしらできる(やりやすい)んじゃねーの(雑)
- そういえばAWS LambdaのRustサポートがGAになったな
- よし、AWS Lambda + Rustでリレー作ろう(雑)
作り方
$ git submodule add https://github.com/nostr-protocol/nips.git nips
$ git submodule update --init --recursive
$ claude リレー作って注) 嘘です(流石にそんな単純な指示では無理だと思う。でもそこそこイイ線いくかもw)
実際には、cc-sddを使って仕様駆動開発した。要件・設計はガッツリ人間がレビューした。コードは全てclaude codeが書いた。
最初の構成
NIP-01準拠は、以下のサーバーレス構成で作れる。とてもシンプル。イベントもDynamoDBに永続化しており、REQに過去イベントも含めて応答できる。

細かい話をすると、Replaceable/Addressableなイベントを検索する用のGSIは、これらのイベントを受けるために必要。
次の構成
NIP-11に準拠するためには、NIP-01のWebSocketリクエストを受けるものと同じドメイン・パスで(Acceptヘッダーが違う)APIレスポンスする必要がある。このルーティングがAPI Gatewayにはできない。
そこで、API Gatewayの手前にCloudFrontを置き、Lambda@Edgeを使ってヘッダーによるルーティングを実装した。なお、CORSプリフライトにはLambda@Edgeで直接応答してしまっている。

NIP-11にわざわざFunctionで動的に応答する必要は無いんだけど、limitationあたりを環境変数で管理してリレー本体の動的制御と同期しようと思ったらFunctionにしちゃった方がシンプルに済む。
課題
リレー作ったことある人ならわかると思うけど、結局、永続化したイベントを検索する(REQに応答するため)のが一番のボトルネックになる。
↑の構成だとDynamoDBにScanをかけてアプリケーション層でフィルタリングするしかない。GSIを作ってチューニングすることは可能だけど、クライアントが送信できるフィルターの自由度が高いので、Scanをゼロにするのは無理だと思う。
残念・・・・!
ここでサーバーレスを諦めた。
- OpenSearch ServerlessとかAurora Serverlessをサーバーレスに含めて良いなら達成できるだろうが・・・
- これらはミニマム料金が、遊びで使うには高すぎる
- 外部サービスという手もあるが、依存をそんなに増やしたいわけではない
- あと一応EFS経由でSQLiteという手を考えたけど、たぶん厳しい(筋も良くなさそう)
着地
とりあえずOpenSearch Serviceのマネージド版でインスタンスを立てた。
DynamoDB Streamを使って、DynamoDBのイベント格納用テーブルをトリガーにして、イベントをOpenSearchに入れたり消したりする処理をしている。REQを受けたらOpenSearchで検索する。

OpenSearchを使えばそこそこのスケーラビリティも確保できるだろうから、机上論では構成全体でそこそこスケーラビリティがあるはずである。「負荷が上がったらお金を投下するだけでスケールできる」を目指すのであれば悪くない構成になったと思う。
しかし実際には
そもそもNostrの住人数は高々知れてるし、予算も遊びの範囲だから・・・・
OpenSearch Serviceは一番小さいインスタンスを使っても、個人リレーとしてはオーバースペック&オーバーバジェットな気がする。
この記事の公開時はOpenSearchで動いているが、たぶん近々、SQLiteをEC2のもっと小さいインスタンスで動かすと思う(ただし、このあたりで、サーバーレスを目指した意義はほぼなくなる)。
使っていいよ
以下のURLでリレーを稼動させておくので、使ってやってください。
wss://relay.nostr.nisshiee.org一応、ちゃんと免責を主張するための規約だけはあるので気にする人は読んでね。
エピローグ
- Apple Watchのくだりはどこいった?
- さぁ?
- まぁDynamoDBにイベントが貯まるようにはなったから、何かやりやすくはなったんじゃね?
- 来年のアドベントカレンダーに期待しよう