Frequent Service Restarts and High Memory Usage on Free Hosting (Render/Railway)
Context:
I am running a Python web application hosted on either Render using their free-tier plans. The app fetches data from a Supabase database via multiple API calls and processes podcast RSS feed information.
Issue:
The application frequently restarts, and I see logs indicating worker processes are being killed, likely due to exceeding memory limits. Additionally, the app makes a high volume of HTTP requests to Supabase in quick succession. While these requests succeed (HTTP 200 OK
), the hosting platform may not have sufficient resources to handle this load effectively.
Logs:
Some of the logs I encounter:
yaml
Copy code
[2024-11-28 07:59:12 +0000] [1] [ERROR] Worker (pid:5) was sent SIGKILL! Perhaps out of memory?
[2024-11-28 07:59:14,277 - httpx - INFO - HTTP Request: GET https://xhiqvdyqaaowxptzupdf.supabase.co/rest/v1/podcasts?select=...
[2024-11-28 11:30:59,033 - app - INFO - Response status: 302 FOUND
2024-11-28 12:35:03,860 - httpx - INFO - HTTP Request: POST https://xhiqvdyqaaowxptzupdf.supabase.co/rest/v1/episodes "HTTP/2 201 Created"
2024-11-28 12:35:04,383 - httpx - INFO - HTTP Request: POST https://xhiqvdyqaaowxptzupdf.supabase.co/rest/v1/episodes "HTTP/2 201 Created"
2024-11-28 12:35:04,384 - main - INFO - Processed podcast: The Propcast
2024-11-28 12:35:04,633 - httpx - INFO - HTTP Request: GET https://xhiqvdyqaaowxptzupdf.supabase.co/rest/v1/podcasts?select=%2A&rss_feed=eq.https%3A%2F%2Ffeeds.buzzsprout.com%2F1608046.rss&client_id=eq.6 "HTTP/2 200 OK"
2024-11-28 12:35:05,096 - httpx - INFO - HTTP Request: GET https://xhiqvdyqaaowxptzupdf.supabase.co/rest/v1/podcasts?select=%2A&rss_feed=eq.https%3A%2F%2Ffeeds.buzzsprout.com%2F1608046.rss&client_id=neq.6 "HTTP/2 200 OK"
2024-11-28 12:35:05,378 - httpx - INFO - HTTP Request: POST https://xhiqvdyqaaowxptzupdf.supabase.co/rest/v1/podcasts "HTTP/2 201 Created"
2024-11-28 12:35:06,402 - httpx - INFO - HTTP Request: PATCH https://xhiqvdyqaaowxptzupdf.supabase.co/rest/v1/podcasts?id=eq.369 "HTTP/2 200 OK"
[2024-11-28 12:35:08 +0000] [95] [CRITICAL] WORKER TIMEOUT (pid:110)
127.0.0.1 - - [28/Nov/2024:12:35:08 +0000] "POST /upload_podcast HTTP/1.1" 500 0 "-" "-"
[2024-11-28 12:35:08 +0000] [110] [ERROR] Error handling request /upload_podcast
Traceback (most recent call last):
File "/opt/render/project/src/.venv/lib/python3.11/site-packages/gunicorn/workers/sync.py", line 134, in handle
self.handle_request(listener, req, client, addr)
File "/opt/render/project/src/.venv/lib/python3.11/site-packages/gunicorn/workers/sync.py", line 177, in handle_request
respiter = self.wsgi(environ, resp.start_response)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/render/project/src/.venv/lib/python3.11/site-packages/flask/app.py", line 1478, in __call__
return self.wsgi_app(environ, start_response)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/render/project/src/.venv/lib/python3.11/site-packages/flask/app.py", line 1455, in wsgi_app
response = self.full_dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/render/project/src/.venv/lib/python3.11/site-packages/flask/app.py", line 867, in full_dispatch_request
rv = self.dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/render/project/src/.venv/lib/python3.11/site-packages/flask/app.py", line 852, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/render/project/src/routes.py", line 210, in upload_podcast
process_podcast(new_podcast_data, supabase)
File "/opt/render/project/src/main.py", line 109, in process_podcast
episode_embedding = create_embedding(episode_data['Description'])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/render/project/src/utils.py", line 29, in create_embedding
response = openai.Embedding.create(
^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/render/project/src/.venv/lib/python3.11/site-packages/openai/api_resources/embedding.py", line 33, in create
response = super().create(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/render/project/src/.venv/lib/python3.11/site-packages/openai/api_resources/abstract/engine_api_resource.py", line 153, in create
response, _, api_key = requestor.request(
^^^^^^^^^^^^^^^^^^
File "/opt/render/project/src/.venv/lib/python3.11/site-packages/openai/api_requestor.py", line 288, in request
result = self.request_raw(
^^^^^^^^^^^^^^^^^
File "/opt/render/project/src/.venv/lib/python3.11/site-packages/openai/api_requestor.py", line 596, in request_raw
result = _thread_context.session.request(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/render/project/src/.venv/lib/python3.11/site-packages/requests/sessions.py", line 589, in request
resp = self.send(prep, **send_kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/render/project/src/.venv/lib/python3.11/site-packages/requests/sessions.py", line 703, in send
r = adapter.send(request, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/render/project/src/.venv/lib/python3.11/site-packages/requests/adapters.py", line 486, in send
resp = conn.urlopen(
^^^^^^^^^^^^^
File "/opt/render/project/src/.venv/lib/python3.11/site-packages/urllib3/connectionpool.py", line 789, in urlopen
response = self._make_request(
^^^^^^^^^^^^^^^^^^^
File "/opt/render/project/src/.venv/lib/python3.11/site-packages/urllib3/connectionpool.py", line 536, in _make_request
response = conn.getresponse()
^^^^^^^^^^^^^^^^^^
File "/opt/render/project/src/.venv/lib/python3.11/site-packages/urllib3/connection.py", line 507, in getresponse
httplib_response = super().getresponse()
^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/http/client.py", line 1395, in getresponse
response.begin()
File "/usr/local/lib/python3.11/http/client.py", line 325, in begin
version, status, reason = self._read_status()
^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/http/client.py", line 286, in _read_status
line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/socket.py", line 718, in readinto
return self._sock.recv_into(b)
^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/ssl.py", line 1314, in recv_into
return self.read(nbytes, buffer)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/ssl.py", line 1166, in read
return self._sslobj.read(len, buffer)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/render/project/src/.venv/lib/python3.11/site-packages/gunicorn/workers/base.py", line 204, in handle_abort
sys.exit(1)
SystemExit: 1
[2024-11-28 12:35:08 +0000] [110] [INFO] Worker exiting (pid: 110)
[2024-11-28 12:35:09 +0000] [95] [ERROR] Worker (pid:110) was sent SIGKILL! Perhaps out of memory?
[2024-11-28 12:35:09 +0000] [114] [INFO] Booting worker with pid: 114
Key Details:
- Hosting Platform: Render/Railway (free tier)
- Database: Supabase
- Logs suggest successful API responses (
HTTP 200 OK
), but the app restarts frequently.
What I’ve Tried:
- Verified API responses are correct.
- Confirmed that free-tier hosting resources might not limiting me
- Reviewed logs to identify potential memory leaks or inefficient processing.
Questions:
- How can I optimize my application to work within the constraints of free-tier hosting?
- Should I consider batching API calls or implementing a caching mechanism to reduce the load on both the database and hosting server?
- Are there alternative ways to debug or profile the memory usage of my application in this environment?
- Is upgrading to a paid plan the best solution, or are there coding optimizations I can try first?