こんにちは、理系大学生エンジニアのShinonです。

無料でWebアプリを公開できる強力な味方「Render」と「Neon(PostgreSQLデータベース)」。僕も自分のポートフォリオサイト(shinotech78.com)の運用でめちゃくちゃお世話になっています。

しかし先日、この無料構成ならではの思わぬ罠にハマり、サイトが完全にダウンするという冷や汗モノのトラブルに直面しました。

今回は、僕の盛大なやらかし(失敗談)を赤裸々に語りつつ、Renderのスリープ対策に潜む危険性と、その正しい解決策について共有します。

 

1. 突然の「500 Internal Server Error」

ある日のこと。自分のサイト(shinotech78.com)にアクセスすると、真っ白な画面に無慈悲な文字が表示されていました。

「500 Internal Server Error」

昨日までは普通にサイトにアクセスができていました。

原因を特定すべく、大慌てでRenderのダッシュボードを開き、サーバーのログを確認しにいきました。

 

2. 原因究明:犯人は「データベースの通信制限」だった

Renderのログをスクロールしていくと、そこにはこんな赤い文字が残されていました。

 

ERROR: Your project has exceeded the data transfer quota. Upgrade your plan to increase limits. (エラー:プロジェクトのデータ転送量の上限を超えました。制限を増やすにはプランをアップグレードしてください。)

 

これを見た瞬間、「あ、これDjangoのバグじゃなくてインフラ側の問題だ」と悟りました。 実は、エラーの原因はRender本体ではなく、連携させていたデータベース(Neonの無料プラン)にあったのです。

Neonの無料プランには「データ転送量(帯域幅):5GB/月」という上限があります。アプリのバグではなく、この5GBの通信枠を使い切ってしまい、データベース側から「スマホのギガ不足(通信制限)」と同じように接続をシャットアウトされていたのが原因でした。データベースに繋がらないから、Djangoが500エラーを吐いていたわけです。

)

実際のRender画面

(Network transferが 5.59/5 GBとオーバーしている、上部に赤色の警告メッセージ)

 

 

3. なぜ上限を突破したのか?(スリープ対策の罠)

ここで一つの疑問が浮かびます。 「個人開発のポートフォリオサイトに、ひと月で5GBも通信するほど人が来るわけないのに、なんで?」

犯人はなんと、僕自身が設定した「cron-job.org」によるスリープ対策でした。

Renderの無料プランは、アクセスが15分間ないとサーバーが眠ってしまう(スリープ状態になる)仕様があります。それを防ぐため、cron-job.orgなどの外部サービスを使って定期的にアクセスを飛ばし、サーバーを起こし続けるのが定番のハックです。

僕は、「10分おきに24時間、サイトのトップページにアクセスする」という設定にしていました。 しかし、トップページにはブログの最新記事一覧などがあり、表示するたびに「データベースからデータを引っ張ってくる重い処理」が走ります。

つまり、僕が仕掛けたボットが、24時間365日休むことなくデータベースの通信量を爆食いしていたのです。

 

 

4. 解決策1:復旧するまで待つ(Neonのリセット)

原因が分かれば対処はできますが、ギガを使い切ってしまった以上、プランを課金しない限り自力で即座に復旧させることはできません。

しかし、不幸中の幸いだったのは、エラーが起きたのが「月末」だったこと。 Neonの無料枠の通信量は「月ごと」に計算され、UTC時間(協定世界時)の毎月1日にリセットされます。

日本時間(JST)はUTCから9時間進んでいるため、月が変わって1日の午前9時を過ぎたあたりでメーターがリセットされ、サイトは無事に奇跡の自動復活を遂げました。

 

 

5. 解決策2:正しいスリープ対策(再発防止)

サイトが復旧して安心したのも束の間、このままでは来月も必ず同じ悲劇を繰り返してしまいます。二度と「自作自演のDDoS攻撃」をしないために、cron-job.orgの設定をすぐに見直しました。

 

変更点1:アクセス先を超軽量ページにする

これが一番重要です。アクセス先を、データベースを一切叩かない「超軽量なページ」に変更しました。 僕は robots.txt を新たにアクセス先としました。

  • 変更前: https://shinotech78.com/ (重いDB処理あり)

  • 変更後: https://shinotech78.com/robots.txt (ただのテキストファイル)

robots.txt へのアクセスならデータベース通信量は「ゼロ」のまま、Renderのサーバー本体だけを確実に起こし続けることができます。

 

 

変更点2:深夜帯は稼働を止める

そもそも、日本向けのサイトなら深夜に起きている必要はありません。 cron-job.orgの「Custom」スケジュール設定を使い、誰も見ない深夜2時〜5時の間はアクセス(Ping)を飛ばさないように設定しました。

Renderの無料プランは「月に750時間(約31日分)」という稼働時間の制限もあります。深夜にわざとサーバーをスリープさせることで、この稼働時間の節約にもつながります。

 

 

6. まとめ

無料枠(PaaS)を使い倒してWebアプリを運用するのは、お財布に優しくて最高ですが、「サーバーの稼働時間」だけでなく「データベースの通信量(転送量)」にも気を配る必要があるということを、今回の失敗で痛いほど学びました。

現在Renderと外部データベース(NeonやSupabaseなど)を組み合わせて運用していて、cron-job等でスリープ対策をしている方は、今すぐcronのアクセス先(URL)を見直してみてください!

トップページや重いAPIエンドポイントを指定していると、ある日突然、僕と同じように謎の500エラーに泣かされることになりますよ。この記事が、誰かのサーバーダウンを未然に防ぐ助けになれば嬉しいです!