こんにちは。エンジニアの落合です。
社外でイベントを開催することになり、当日使う投票・アンケートの仕組みが必要になりました。Googleフォームなどの既存サービスでも十分だったのかもしれませんが、これまでアンケートだけだと回答率が低かったので投票システムと一緒にしてみたいという思いや匿名性を保ったまま一人一票に制限したい、結果は開票するまで誰にも見せたくない、というこだわりが出てきたので、今回は自作してみることにしました。
ということで、AWSのサーバーレス構成で、投票・アンケートシステムを一から作ってみました。
構成
作成したアーキテクチャは以下のような構成になります。
- Amplify Hosting:投票用・管理用の2つのSPAを配信
- API Gateway:フロントからのリクエストをHTTP APIとして受け付け
- AWS Lambda:投票の重複チェック・集計・イベントのステータス管理を担当
- Amazon DynamoDB:イベント・投票・アンケートのデータをシングルテーブルで保存
- Systems Manager Parameter Store:管理画面のBasic認証情報を保存

サーバレス構成なので、イベントが動いていない時間はほぼ課金が発生しないのが利点です。
各サービスの詳細設定
DynamoDB
シングルテーブル設計にして、イベント・投票・アンケート・重複防止用のトークンを1つのテーブルにまとめました。
パーティションキーをEVENT#<id>やPOLL#<id>のように使い分けることで、1回のクエリでイベントに紐づく情報をまとめて取得できるようにしています。
API Gateway + Lambda
投票APIは、重複チェックと集計をDynamoDBのAPITransactWriteItemsで1つのトランザクションにまとめています。別々に実装すると整合性が崩れるリスクがあったためです。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
" class=""]<code class="language-typescript">await ddb.send(new TransactWriteCommand({ TransactItems: [ { Put: { TableName: TABLE_NAME, Item: { PK: `POLL#${pollId}`, SK: `TOKEN#${tokenHash}`, optionId, votedAt }, ConditionExpression: "attribute_not_exists(PK)", // 既に投票済みなら失敗 }, }, { Update: { TableName: TABLE_NAME, Key: { PK: `EVENT#${eventId}`, SK: `POLL#${pollId}` }, UpdateExpression: "ADD optionCounts.#opt :one, totalVotes :one", ExpressionAttributeNames: { "#opt": optionId }, ExpressionAttributeValues: { ":one": 1 }, }, }, ], })); |
開票前の結果非公開はLambdaのレスポンス整形で制御しています。
|
1 2 3 4 5 |
" class=""]<code class="language-typescript">const revealed = eventItem.status === "revealed"; return ok({ // ... ...(revealed ? { optionCounts: poll.optionCounts, totalVotes: poll.totalVotes } : {}), }); |
管理画面の認証は、API Gatewayの「Lambdaオーソライザー」という仕組みで実装しています。/admin/*配下のルートにリクエストが来るたびに、まずこの認証用Lambdaが呼ばれ、ここでOKが出たときだけ本来のAPIが実行される、という流れです。
Parameter Storeへの問い合わせは、呼ばれるたびに発生すると地味に遅くなるので、5分間だけ結果をメモリにキャッシュしています。
Amplify Hosting
投票用・管理用でアプリを分けて、どちらもGitを使わずzipを直接アップロードする手動デプロイにしました。今回は試しに作ってみたということもあり上記のデプロイ方法にしています。
CORSの許可オリジンはアプリのドメインが決まってから設定する必要があるので、先にAmplify側をデプロイしてドメインを確定させ、そのあとバックエンドを再デプロイする、という順番で進めています。
おわりに
今回は、社外イベント向けの投票・アンケートシステムを、AWSのサーバーレス構成で自作してみました。
実際に使ってみたところ、今まで50%以下だったアンケートの回答率が90%まで上がりました!投票した直後にそのままアンケートへ誘導できるのが効いていると思います。
また、イベントごとに投票・アンケートを作る時に管理画面からぽちぽち操作するだけで済むので想像していたより使いやすかったです。
次またイベントを開催するときも活用できたらと思います。
- 【Serverless】投票・アンケートシステムを自作してみた - 2026-10-02
- 2025 Japan AWS Jr.Championsの任期を終えたので、この一年間を振り返ってみた - 2026-06-17
- ノーコードでAIワインソムリエをつくってみた - 2025-12-24
- Amazon Connectで理想の相談相手をつくってみた - 2025-12-23
- 【Kiro・Playwright】社内でフルAI開発バトル!!「1行も書かずに」Todoアプリを完成させた話〜落合の場合〜 - 2025-12-02
【採用情報】一緒に働く仲間を募集しています





