<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Preston Osoro - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Preston Osoro - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Wed, 06 May 2026 22:13:14 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/author/Preston56/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Deploy Your FastAPI + PostgreSQL App on Render: A Beginner's Guide ]]>
                </title>
                <description>
                    <![CDATA[ This guide is a comprehensive roadmap for deploying a FastAPI backend connected to a PostgreSQL database using Render, a cloud platform that supports hosting Python web apps and managed PostgreSQL databases.   You can find the complete source code he... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/deploy-fastapi-postgresql-app-on-render/</link>
                <guid isPermaLink="false">682f4900bcc94cb9bccbf905</guid>
                
                    <category>
                        <![CDATA[ PostgreSQL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ render.com ]]>
                    </category>
                
                    <category>
                        <![CDATA[ FastAPI ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Preston Osoro ]]>
                </dc:creator>
                <pubDate>Thu, 22 May 2025 15:55:44 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1747923566699/58fc1283-d2f5-4964-acfa-b5dcad0f3d4f.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>This guide is a comprehensive roadmap for deploying a FastAPI backend connected to a PostgreSQL database using <a target="_blank" href="https://render.com/">Render</a>, a cloud platform that supports hosting Python web apps and managed PostgreSQL databases.  </p>
<p>You can find the complete source code <a target="_blank" href="https://github.com/preston-56/FastAPI">here</a>.</p>
<h2 id="heading-deployment-context">Deployment Context</h2>
<p>When deploying a FastAPI app connected to PostgreSQL, you need to select a platform that supports Python web applications and managed databases. This guide uses Render as the example platform because it provides both web hosting and a PostgreSQL database service in one environment, making it straightforward to connect your backend with the database.</p>
<p>You can apply the concepts here to other cloud providers as well, but the steps will differ depending on the platform’s specifics.</p>
<h3 id="heading-heres-what-well-cover">Here’s what we’ll cover:</h3>
<ol>
<li><p><a class="post-section-overview" href="#heading-project-structure">Project Structure for a Real-World FastAPI App</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-youll-need-before-you-start">What You'll Need Before You Start</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-deployment-steps">Deployment Steps</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-step-1-set-up-local-postgresql-database">Step 1: Set Up Local PostgreSQL Database</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-2-set-up-your-database-connection">Step 2: Set Up Your Database Connection</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-3-configure-your-fastapi-main-application">Step 3: Configure Your FastAPI Main Application</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-4-create-a-requirements-file">Step 4: Create a Requirements File</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-5-provision-a-postgresql-database-on-render">Step 5: Provision a PostgreSQL Database on Render</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-6-deploy-your-fastapi-app-on-render">Step 6: Deploy Your FastAPI App on Render</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-7-test-your-api-endpoints">Step 7: Test Your API Endpoints</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-local-development-workflow">Local Development Workflow</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-best-practices-and-tips">Best Practices and Common Troubleshooting Tips</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-common-issues-and-solutions">Common Issues and Solutions</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-project-structure">Project Structure</h2>
<p>If you’re building a real-world API with <a target="_blank" href="https://fastapi.tiangolo.com/">FastAPI</a> you’ll quickly outgrow a single <code>main.py</code> file. That’s when modular project structure becomes essential for maintainability.</p>
<p>Here’s an example structure we’ll use throughout this guide:</p>
<pre><code class="lang-python">FastAPI/
├── database/
│   ├── base.py
│   ├── database.py
│   └── __init__.py
├── fastapi_app/
│   └── main.py
├── items/
│   ├── models/
│   │   ├── __init__.py
│   │   └── item.py
│   ├── routes/
│   │   ├── __init__.py
│   │   └── item.py
│   └── schemas/
│       ├── __init__.py
│       └── item.py
├── models/
│   └── __init__.py
├── orders/
│   ├── models/
│   │   ├── __init__.py
│   │   └── order.py
│   ├── routes/
│   │   ├── __init__.py
│   │   └── order.py
│   └── schemas/
│       ├── __init__.py
│       └── order.py
└── users/
    ├── models/
    │   ├── __init__.py
    │   └── user.py
    ├── routes/
    │   ├── __init__.py
    │   └── user.py
    └── schemas/
        ├── __init__.py
        └── user.py
</code></pre>
<h2 id="heading-what-youll-need-before-you-start">What You'll Need Before You Start</h2>
<p>Before diving in, make sure you've got:</p>
<ul>
<li><p>A free <a target="_blank" href="https://render.com/">Render</a> account (sign up if you don't have one)</p>
</li>
<li><p>A GitHub or GitLab repository for your FastAPI project</p>
</li>
<li><p>Basic familiarity with Python, FastAPI, and Git</p>
</li>
<li><p>Your project structure set up similarly to the example above</p>
</li>
</ul>
<h2 id="heading-deployment-steps">Deployment Steps</h2>
<h3 id="heading-step-1-set-up-local-postgresql-database">Step 1: Set Up Local PostgreSQL Database</h3>
<p>For local development, you'll need to set up PostgreSQL on your machine like this:</p>
<pre><code class="lang-sql"><span class="hljs-comment">-- 1. Log in as superuser</span>
psql -U postgres

<span class="hljs-comment">-- 2. Create a new database</span>
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">DATABASE</span> your_db;

<span class="hljs-comment">-- 3. Create a user with password</span>
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">USER</span> your_user <span class="hljs-keyword">WITH</span> <span class="hljs-keyword">PASSWORD</span> <span class="hljs-string">'your_secure_password'</span>;

<span class="hljs-comment">-- 4. Grant all privileges on the database</span>
<span class="hljs-keyword">GRANT</span> <span class="hljs-keyword">ALL</span> <span class="hljs-keyword">PRIVILEGES</span> <span class="hljs-keyword">ON</span> <span class="hljs-keyword">DATABASE</span> your_db <span class="hljs-keyword">TO</span> your_user;

<span class="hljs-comment">-- 5. (Optional) Allow the user to create tables</span>
<span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">USER</span> your_user CREATEDB;

<span class="hljs-comment">-- 6. Exit</span>
\q
</code></pre>
<p>After setting up your local database, create a <code>.env</code> file in your project root:</p>
<pre><code class="lang-bash">DATABASE_URL=postgresql://your_user:your_secure_password@localhost:5432/your_db
</code></pre>
<h3 id="heading-step-2-set-up-your-database-connection">Step 2: Set Up Your Database Connection</h3>
<p>Create <code>database/database.py</code> to manage your PostgreSQL connection with SQLAlchemy:</p>
<p>This file is crucial as it creates the database engine, defines session management, and provides a dependency function for your routes.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> sqlalchemy <span class="hljs-keyword">import</span> create_engine
<span class="hljs-keyword">from</span> sqlalchemy.orm <span class="hljs-keyword">import</span> sessionmaker
<span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv

load_dotenv()

DATABASE_URL = os.getenv(<span class="hljs-string">"DATABASE_URL"</span>)
<span class="hljs-string">"""
The engine manages the connection to the database and handles query execution.
"""</span>
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=<span class="hljs-literal">False</span>, autoflush=<span class="hljs-literal">False</span>, bind=engine)

<span class="hljs-comment"># Database dependency for routes</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_db</span>():</span>
    db = SessionLocal()
    <span class="hljs-keyword">try</span>:
        <span class="hljs-keyword">yield</span> db
    <span class="hljs-keyword">finally</span>:
        db.close()
</code></pre>
<p>And add <code>database/base.py</code> for the base class:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> sqlalchemy.ext.declarative <span class="hljs-keyword">import</span> declarative_base
Base = declarative_base()
</code></pre>
<h3 id="heading-step-3-configure-your-fastapi-main-application">Step 3: Configure Your FastAPI Main Application</h3>
<p>Create main FastAPI application file <code>fastapi_app/main.py</code> to import all your route modules:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI, APIRouter
<span class="hljs-keyword">from</span> fastapi.openapi.utils <span class="hljs-keyword">import</span> get_openapi
<span class="hljs-keyword">from</span> fastapi.security <span class="hljs-keyword">import</span> OAuth2PasswordBearer
<span class="hljs-keyword">import</span> uvicorn
<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv

<span class="hljs-comment"># Load environment variables</span>
load_dotenv()

<span class="hljs-comment"># Database imports</span>
<span class="hljs-keyword">from</span> database <span class="hljs-keyword">import</span> Base, engine

<span class="hljs-comment"># Import models to ensure they're registered with SQLAlchemy</span>
<span class="hljs-keyword">import</span> models

<span class="hljs-comment"># Import router modules</span>
<span class="hljs-keyword">from</span> items.routes <span class="hljs-keyword">import</span> item_router
<span class="hljs-keyword">from</span> orders.routes <span class="hljs-keyword">import</span> order_router
<span class="hljs-keyword">from</span> users.routes <span class="hljs-keyword">import</span> user_router

<span class="hljs-comment"># Initialize FastAPI app</span>
app = FastAPI(
    title=<span class="hljs-string">"Store API"</span>,
    version=<span class="hljs-string">"1.0.0"</span>,
    description=<span class="hljs-string">"API documentation for Store API"</span>
)

<span class="hljs-comment"># Create database tables on startup</span>
Base.metadata.create_all(bind=engine)

<span class="hljs-comment"># Root endpoint</span>
<span class="hljs-meta">@app.get("/")</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">root</span>():</span>
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"Welcome to FastAPI Store"</span>}

<span class="hljs-comment"># Setup versioned API router and include module routers</span>
api_router = APIRouter(prefix=<span class="hljs-string">"/v1"</span>)
api_router.include_router(item_router)
api_router.include_router(order_router)
api_router.include_router(user_router)

<span class="hljs-comment"># Register the master router with the app</span>
app.include_router(api_router)

<span class="hljs-comment"># Setup OAuth2 scheme for Swagger UI login flow</span>
oauth2_scheme = OAuth2PasswordBearer(tokenUrl=<span class="hljs-string">"/v1/auth/login"</span>)

<span class="hljs-comment"># Custom OpenAPI schema with security configuration</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">custom_openapi</span>():</span>
    <span class="hljs-keyword">if</span> app.openapi_schema:
        <span class="hljs-keyword">return</span> app.openapi_schema

    openapi_schema = get_openapi(
        title=app.title,
        version=app.version,
        description=app.description,
        routes=app.routes,
    )

    <span class="hljs-comment"># Add security scheme</span>
    openapi_schema[<span class="hljs-string">"components"</span>][<span class="hljs-string">"securitySchemes"</span>] = {
        <span class="hljs-string">"BearerAuth"</span>: {
            <span class="hljs-string">"type"</span>: <span class="hljs-string">"http"</span>,
            <span class="hljs-string">"scheme"</span>: <span class="hljs-string">"bearer"</span>,
            <span class="hljs-string">"bearerFormat"</span>: <span class="hljs-string">"JWT"</span>,
        }
    }

    <span class="hljs-comment"># Apply global security requirement</span>
    openapi_schema[<span class="hljs-string">"security"</span>] = [{<span class="hljs-string">"BearerAuth"</span>: []}]

    app.openapi_schema = openapi_schema
    <span class="hljs-keyword">return</span> app.openapi_schema

app.openapi = custom_openapi

<span class="hljs-comment"># Run the app using Uvicorn when executed directly</span>
<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    port = os.environ.get(<span class="hljs-string">"PORT"</span>)
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> port:
        <span class="hljs-keyword">raise</span> EnvironmentError(<span class="hljs-string">"PORT environment variable is not set"</span>)
    uvicorn.run(<span class="hljs-string">"fastapi_app.main:app"</span>, host=<span class="hljs-string">"0.0.0.0"</span>, port=int(port), reload=<span class="hljs-literal">False</span>)
</code></pre>
<h3 id="heading-step-4-create-a-requirements-file">Step 4: Create a Requirements File</h3>
<p>In your project root, create a <code>requirements.txt</code> file that includes all the necessary dependencies:</p>
<pre><code class="lang-python">fastapi&gt;=<span class="hljs-number">0.68</span><span class="hljs-number">.0</span>
uvicorn&gt;=<span class="hljs-number">0.15</span><span class="hljs-number">.0</span>
sqlalchemy&gt;=<span class="hljs-number">1.4</span><span class="hljs-number">.23</span>
psycopg2-binary&gt;=<span class="hljs-number">2.9</span><span class="hljs-number">.1</span>
python-dotenv&gt;=<span class="hljs-number">0.19</span><span class="hljs-number">.0</span>
pydantic&gt;=<span class="hljs-number">1.8</span><span class="hljs-number">.2</span>
</code></pre>
<h3 id="heading-step-5-provision-a-postgresql-database-on-render">Step 5: Provision a PostgreSQL Database on Render</h3>
<p>Log in to your Render dashboard at <a target="_blank" href="https://dashboard.render.com/login">dashboard.render.com</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747782796468/e7564ed7-66cd-4466-a1d0-913b93dc9a77.png" alt="Render dashboard" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Then click "<strong>New +</strong>" in the top right and select "<strong>PostgreSQL</strong>".</p>
<p>Fill in the details:</p>
<ul>
<li><p>Name: <code>your-app-db</code> (choose a descriptive name)</p>
</li>
<li><p>Database: <code>your_app</code> (this will be your database name)</p>
</li>
<li><p>User: leave default (auto-generated)</p>
</li>
<li><p>Region: Choose the closest to your target users</p>
</li>
<li><p>Plan: Free tier</p>
</li>
</ul>
<p>Save and note the Internal Database URL shown after creation, which will look something like this:</p>
<pre><code class="lang-bash">postgres://user:password@postgres-instance.render.com/your_app
</code></pre>
<h3 id="heading-step-6-deploy-your-fastapi-app-on-render">Step 6: Deploy Your FastAPI App on Render</h3>
<p>With your database provisioned, it's time to deploy your API. You can do that by following these steps:</p>
<ol>
<li><p>In Render dashboard, click "<strong>New +</strong>" and select "<strong>Web Service</strong>"</p>
</li>
<li><p>Connect your GitHub/GitLab repository</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747813206325/5338209e-eb5c-4ba2-b28a-511296220935.png" alt="Connect to GitHub/GitLab" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
</li>
<li><p>Name your service</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747813320278/e21998cc-317b-4ea6-8dec-d52493e2969f.png" alt="Naming your service" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
</li>
<li><p><strong>Then configure the build settings</strong>:</p>
<ul>
<li><p>Environment: <code>Python 3</code></p>
</li>
<li><p>Build Command: <code>pip install -r requirements.txt</code></p>
</li>
<li><p>Start Command: <code>python3 -m fastapi_app.main</code></p>
</li>
</ul>
</li>
<li><p><strong>Add your environment variables</strong>:</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747813450598/6b0913b0-3081-44c4-b746-6b28549a2dd0.png" alt="Adding environment variables" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<ul>
<li><p>Click "Environment" tab</p>
</li>
<li><p>Add your database URL:</p>
<ul>
<li><p>Key: <code>DATABASE_URL</code></p>
</li>
<li><p>Value: Paste the <strong>Internal Database URL</strong> from your PostgreSQL service</p>
</li>
</ul>
</li>
<li><p>Add any other environment variables your application needs</p>
</li>
</ul>
</li>
<li><p>Finally, click <strong>Deploy Web Service</strong>.</p>
<ul>
<li><p>Render will start building and deploying your application</p>
</li>
<li><p>This process takes a few minutes. You can monitor logs during build and deployment in real-time</p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-step-7-test-your-api-endpoints">Step 7: Test Your API Endpoints</h3>
<p>Once deployed, access your API’s URL (for example, <a target="_blank" href="https://your-app-name.onrender.com"><code>https://your-app-name.onrender.com</code></a>).</p>
<p>Navigate to <code>/docs</code> to open the interactive Swagger UI, where you can test your endpoints directly:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747783210993/95ea29a5-d2aa-430f-a107-ef25c8ab4e24.png" alt="Test endpoints in Swagger" width="600" height="400" loading="lazy"></p>
<ul>
<li><p>Expand an endpoint</p>
</li>
<li><p>Click <strong>Try it out</strong></p>
</li>
<li><p>Provide any required input</p>
</li>
<li><p>Click <strong>Execute</strong></p>
</li>
<li><p>View the response</p>
</li>
</ul>
<h2 id="heading-local-development-workflow">Local Development Workflow</h2>
<p>While your app is deployed, you'll still need to work on it locally. Here's how to maintain a smooth development workflow:</p>
<p>First, create a local <code>.env</code> file (don't commit this to Git):</p>
<pre><code class="lang-python">DATABASE_URL=postgresql://username:password@localhost:<span class="hljs-number">5432</span>/your_local_db
</code></pre>
<p>Then install your dependencies in a virtual environment:</p>
<pre><code class="lang-bash">python3 -m venv venv
<span class="hljs-built_in">source</span> venv/bin/activate  <span class="hljs-comment"># Windows: venv\Scripts\activate</span>
pip install -r requirements.txt
</code></pre>
<p>Next, run your local server:</p>
<pre><code class="lang-bash">python3 -m fastapi_app.main
</code></pre>
<p>This command triggers the <code>__main__</code> block in <code>fastapi_app/main.py</code>, which starts the FastAPI app using Uvicorn. It reads the <code>PORT</code> from your environment, so ensure it's set (e.g., via a <code>.env</code> file).</p>
<p>Then make changes to your code and test locally before pushing to GitHub/GitLab. You can push your changes to automatically trigger a new deployment on Render.</p>
<h2 id="heading-best-practices-and-tips">Best Practices and Tips</h2>
<ol>
<li><p><strong>Use database migrations</strong>: Add Alembic to your project for managing schema changes</p>
<pre><code class="lang-bash"> pip install alembic
 alembic init migrations
</code></pre>
</li>
<li><p><strong>Separate development and production configurations</strong>:</p>
<pre><code class="lang-python"> <span class="hljs-keyword">if</span> os.environ.get(<span class="hljs-string">"ENVIRONMENT"</span>) == <span class="hljs-string">"production"</span>:
     <span class="hljs-comment"># Production settings</span>
 <span class="hljs-keyword">else</span>:
     <span class="hljs-comment"># Development settings</span>
</code></pre>
</li>
<li><p><strong>Monitor your application</strong>:</p>
<ul>
<li>Render provides logs and metrics for your application. You can set up alerts for errors or high resource usage.</li>
</ul>
</li>
<li><p><strong>Optimize database queries</strong>:</p>
<ul>
<li><p>Use SQLAlchemy's relationship loading options.</p>
</li>
<li><p>Consider adding indexes to frequently queried fields.</p>
</li>
</ul>
</li>
<li><p><strong>Scale when needed</strong>:</p>
<ul>
<li>Render allows you to upgrade your plan as your application grows. Consider upgrading your database plan for production applications.</li>
</ul>
</li>
</ol>
<h2 id="heading-common-issues-and-solutions">Common Issues and Solutions</h2>
<p>When deploying a Python web app on Render, a few issues can commonly occur. Here's a more detailed look at them and how you can resolve each one.</p>
<h3 id="heading-database-connection-errors"><strong>Database connection errors</strong>:</h3>
<p>If your app can’t connect to the database, first double-check that your <code>DATABASE_URL</code> environment variable is correctly set in your Render dashboard. Make sure the URL includes the right username, password, host, port, and database name.</p>
<p>Also, confirm that your SQLAlchemy models match the actual schema in your database. A mismatch here can lead to errors during migrations or app startup. If you're using Postgres, ensure that the database user has permission to read/write tables and perform migrations.</p>
<h3 id="heading-deployment-fails-entirely"><strong>Deployment fails entirely:</strong></h3>
<p>When deployment fails, Render usually provides helpful logs under the “Events” tab. Check there for any error messages. A few common culprits include:</p>
<ul>
<li><p>A missing <code>requirements.txt</code> file or forgotten dependencies.</p>
</li>
<li><p>A bad <code>start</code> command in the Render settings. Double-check that it points to your correct entry point (for example, <code>gunicorn app:app</code> or <code>uvicorn main:app --host=0.0.0.0 --port=10000</code>).</p>
</li>
<li><p>Improper Python version. You can specify this in a <code>runtime.txt</code> file (for example, <code>python-3.11.1</code>).</p>
</li>
</ul>
<h3 id="heading-api-returns-500-internal-server-errors"><strong>API returns 500 Internal Server errors</strong>:</h3>
<p>Internal server errors can happen for several reasons. To debug:</p>
<ul>
<li><p>Open your Render logs and look for Python tracebacks or unhandled exceptions.</p>
</li>
<li><p>Try to reproduce the issue locally using the same request and data.</p>
</li>
<li><p>Add <code>try/except</code> blocks around critical logic to capture and log errors more gracefully.</p>
</li>
</ul>
<p>Even better, set up structured logging or error tracking (for example, with Sentry) to catch these before your users do.</p>
<h3 id="heading-slow-response-times"><strong>Slow response times</strong>:</h3>
<p>If your app is slow or intermittently timing out, check:</p>
<ul>
<li><p>Whether you're still on the free Render tier, which has limited CPU and memory. Consider upgrading if you’re handling production-level traffic.</p>
</li>
<li><p>If you're running heavy or unoptimized database queries, tools like SQLAlchemy’s <code>.explain()</code> or Django Debug Toolbar can help.</p>
</li>
<li><p>If you’re frequently fetching the same data, try caching it using a lightweight in-memory cache like <code>functools.lru_cache</code> or a Redis instance.</p>
</li>
</ul>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>Deploying a FastAPI app connected to PostgreSQL on Render is straightforward with the right structure and setup. While this guide used Render as an example, the concepts apply broadly across cloud platforms.</p>
<p>With this setup, you can develop, test, and deploy robust Python APIs backed by PostgreSQL databases efficiently.</p>
<p>The free tier on Render has some limitations, including PostgreSQL databases that expire after 90 days unless upgraded. For production applications, consider upgrading to a paid plan for better performance and reliability.</p>
<p>Happy coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Set Up Automated GitHub Workflows for Your Python and React Applications ]]>
                </title>
                <description>
                    <![CDATA[ Automating workflows is an essential step in helping you maintain code quality in your applications – especially when working on both frontend and backend code in a single repository. In this guide, we’ll walk through setting up automated GitHub work... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-set-up-automated-github-workflows-for-python-react-apps/</link>
                <guid isPermaLink="false">672cdb23b9bae98eb2d22c19</guid>
                
                    <category>
                        <![CDATA[ CI/CD ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GitHub Actions ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Preston Osoro ]]>
                </dc:creator>
                <pubDate>Thu, 07 Nov 2024 15:22:11 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1730812659785/2975b117-81ee-4c73-ae24-6fb14e369714.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Automating workflows is an essential step in helping you maintain code quality in your applications – especially when working on both frontend and backend code in a single repository.</p>
<p>In this guide, we’ll walk through setting up automated GitHub workflows for a Python backend (using Flask or Django) and a React frontend. These workflows help test and validate code changes automatically, making sure any issues are caught early.</p>
<p>We’ll assume:</p>
<ul>
<li><p>You’ve already written unit tests for your React components and backend routes.</p>
</li>
<li><p>Your project is set up as a monorepo, with separate directories for frontend and backend.</p>
</li>
<li><p>You’re familiar with GitHub Actions, the platform we’ll use for automation, and that you’re using the <code>ubuntu-latest</code> environment provided by GitHub.</p>
</li>
</ul>
<h2 id="heading-step-1-create-github-actions-workflows">Step 1: Create GitHub Actions Workflows</h2>
<p>In this step, we’ll define two GitHub Actions workflows, one for the frontend and another for the backend. These workflows will run tests automatically whenever changes are pushed to the <code>main</code> branch.</p>
<h3 id="heading-what-is-a-github-action-workflow">What is a GitHub Action Workflow?</h3>
<p>A GitHub Action workflow is a set of instructions that tell GitHub how to automatically execute tasks based on certain events.</p>
<p>Here, our workflows will run tests and deploy the app only if the tests pass. Workflows are triggered by events, such as a push to a branch, and consist of jobs that define the tasks we want to automate.</p>
<h3 id="heading-frontend-cicd-pipeline">Frontend CI/CD Pipeline</h3>
<p>Let’s start by creating a new file in your repository at <code>.github/workflows/frontend.yml</code>. This file will set up an automated pipeline to handle the frontend testing and deployment. Then, define the workflow with the following content:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">name:</span> <span class="hljs-string">Frontend</span> <span class="hljs-string">CI/CD</span> <span class="hljs-string">Pipeline</span>

<span class="hljs-attr">on:</span>
  <span class="hljs-attr">push:</span>
    <span class="hljs-attr">branches:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">main</span>  

<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">build:</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>

    <span class="hljs-attr">steps:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Checkout</span> <span class="hljs-string">code</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v3</span>

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Cache</span> <span class="hljs-string">Node.js</span> <span class="hljs-string">modules</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/cache@v3</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">path:</span> <span class="hljs-string">./frontend/node_modules</span>
          <span class="hljs-attr">key:</span> <span class="hljs-string">${{</span> <span class="hljs-string">runner.os</span> <span class="hljs-string">}}-node-${{</span> <span class="hljs-string">hashFiles('./frontend/package-lock.json')</span> <span class="hljs-string">}}</span>
          <span class="hljs-attr">restore-keys:</span> <span class="hljs-string">|
            ${{ runner.os }}-node-
</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Set</span> <span class="hljs-string">up</span> <span class="hljs-string">Node.js</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/setup-node@v3</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">node-version:</span> <span class="hljs-string">'20'</span>

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Install</span> <span class="hljs-string">frontend</span> <span class="hljs-string">dependencies</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">yarn</span> <span class="hljs-string">install</span>
        <span class="hljs-attr">working-directory:</span> <span class="hljs-string">./frontend</span> 

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Run</span> <span class="hljs-string">frontend</span> <span class="hljs-string">tests</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">yarn</span> <span class="hljs-string">test</span>
        <span class="hljs-attr">working-directory:</span> <span class="hljs-string">./frontend</span>
</code></pre>
<p>Here’s a breakdown of what each part does:</p>
<ol>
<li><p><code>on: push</code>: This triggers the workflow whenever there’s a push to the <code>main</code> branch.</p>
</li>
<li><p><strong>Checkout code</strong>: This step uses the GitHub Action to check out the repository code.</p>
</li>
<li><p><strong>Cache Node.js modules</strong>: Caches <code>node_modules</code> to speed up workflow execution on subsequent runs.</p>
</li>
<li><p><strong>Set up Node.js</strong>: Sets up the Node.js environment for dependency installation and testing.</p>
</li>
<li><p><strong>Install dependencies and run tests</strong>: Installs packages with Yarn and then runs the pre-written tests to verify that the frontend works as expected.</p>
</li>
</ol>
<h3 id="heading-backend-cicd-pipeline"><strong>Backend CI/CD Pipeline</strong></h3>
<p>Now, let’s create a separate file for the backend workflow at <code>.github/workflows/backend.yml</code>. This file will automate testing and deployment for the Python backend.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">name:</span> <span class="hljs-string">Backend</span> <span class="hljs-string">CI/CD</span> <span class="hljs-string">Pipeline</span>

<span class="hljs-attr">on:</span>
  <span class="hljs-attr">push:</span>
    <span class="hljs-attr">branches:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">main</span>  

<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">build:</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>

    <span class="hljs-attr">steps:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Checkout</span> <span class="hljs-string">code</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v3</span>

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Cache</span> <span class="hljs-string">Python</span> <span class="hljs-string">packages</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/cache@v3</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">path:</span> <span class="hljs-string">~/.cache/pip</span>
          <span class="hljs-attr">key:</span> <span class="hljs-string">${{</span> <span class="hljs-string">runner.os</span> <span class="hljs-string">}}-pip-${{</span> <span class="hljs-string">hashFiles('./backend/requirements.txt')</span> <span class="hljs-string">}}</span>
          <span class="hljs-attr">restore-keys:</span> <span class="hljs-string">|
            ${{ runner.os }}-pip-
</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Set</span> <span class="hljs-string">up</span> <span class="hljs-string">Python</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/setup-python@v4</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">python-version:</span> <span class="hljs-string">'3.8'</span>  

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Create</span> <span class="hljs-string">Virtual</span> <span class="hljs-string">Environment</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">python3</span> <span class="hljs-string">-m</span> <span class="hljs-string">venv</span> <span class="hljs-string">venv</span>
        <span class="hljs-attr">working-directory:</span> <span class="hljs-string">./backend</span>

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Install</span> <span class="hljs-string">backend</span> <span class="hljs-string">dependencies</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">|
          source venv/bin/activate
          pip install -r requirements.txt  
</span>        <span class="hljs-attr">working-directory:</span> <span class="hljs-string">./backend</span>

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Configure</span> <span class="hljs-string">DATABASE_URL</span> <span class="hljs-string">securely</span>
        <span class="hljs-attr">env:</span>
          <span class="hljs-attr">DATABASE_URL:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.DATABASE_URL</span> <span class="hljs-string">}}</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">|
          if [ -z "$DATABASE_URL" ]; then
            echo "DATABASE_URL is missing" &gt;&amp;2
            exit 1
          fi
</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Run</span> <span class="hljs-string">tests</span> <span class="hljs-string">with</span> <span class="hljs-string">pytest</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">|
          source venv/bin/activate
          pytest tests/ --doctest-modules -q --disable-warnings
</span>        <span class="hljs-attr">working-directory:</span> <span class="hljs-string">./backend</span>  

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Deploy</span> <span class="hljs-string">to</span> <span class="hljs-string">Production</span>
        <span class="hljs-attr">if:</span> <span class="hljs-string">${{</span> <span class="hljs-string">success()</span> <span class="hljs-string">}}</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">|
          echo "Deploying to production..."
</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Notify</span> <span class="hljs-string">on</span> <span class="hljs-string">Failure</span>
        <span class="hljs-attr">if:</span> <span class="hljs-string">${{</span> <span class="hljs-string">failure()</span> <span class="hljs-string">}}</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">|</span>
          <span class="hljs-string">echo</span> <span class="hljs-string">"Build failed! Sending notification..."</span>
</code></pre>
<p>Here’s what this workflow does:</p>
<ol>
<li><p><strong>Checks out code</strong> and <strong>caches Python packages</strong> for faster execution on repeated runs.</p>
</li>
<li><p><strong>Sets up Python</strong> and creates a virtual environment to isolate dependencies.</p>
</li>
<li><p><strong>Installs dependencies</strong> in the virtual environment from <code>requirements.txt</code>.</p>
</li>
<li><p><strong>Configures environment variables</strong> securely with GitHub Secrets. In this example, we’re using a database URL that’s stored in a GitHub secret for secure access.</p>
</li>
<li><p><strong>Runs backend tests</strong> with <code>pytest</code>, which checks that the backend routes and functions work correctly.</p>
</li>
</ol>
<h2 id="heading-step-2-configure-secrets"><strong>Step 2: Configure Secrets</strong></h2>
<p>For security, let’s set up GitHub Secrets to store sensitive information, like database connection strings.</p>
<ol>
<li><p>Go to your GitHub repository and select <strong>Settings</strong>.</p>
</li>
<li><p>In the sidebar, select <strong>"Secrets and variables"</strong> from the sidebar, then click on "<strong>Actions</strong>".</p>
</li>
<li><p>Add a new repository secret:</p>
<ul>
<li><p><strong>Name</strong>: <code>DATABASE_URL</code></p>
</li>
<li><p><strong>Value</strong>: Your actual database connection string.</p>
</li>
</ul>
</li>
</ol>
<p>Using GitHub Secrets keeps sensitive data safe and prevents it from appearing in your codebase.</p>
<h2 id="heading-step-3-commit-and-push-changes">Step 3: Commit and Push Changes</h2>
<p>Once your workflow files are ready, commit and push the changes to the <code>main</code> branch. Each time you push changes to <code>main</code>, GitHub Actions will trigger these workflows automatically, ensuring your code is thoroughly tested.</p>
<h2 id="heading-step-4-monitor-workflow-runs">Step 4: Monitor Workflow Runs</h2>
<p>After pushing your changes, navigate to the <strong>Actions</strong> tab in your GitHub repository to monitor the workflow runs. Here’s what you’ll find:</p>
<ul>
<li><p><strong>Workflow runs</strong>: This page lists each time a workflow is triggered. You can see if the workflow succeeded, failed, or is in progress.</p>
</li>
<li><p><strong>Logs</strong>: Click on a specific workflow run to view detailed logs. Logs are divided by steps, so you can see exactly where an issue occurred if something goes wrong.</p>
</li>
</ul>
<h3 id="heading-identifying-issues-in-logs">Identifying Issues in Logs</h3>
<p>Each step’s log provides insights into any problems:</p>
<ul>
<li><p>If dependencies fail to install, you’ll see error messages specifying which package caused the issue.</p>
</li>
<li><p>If tests fail, logs will list the specific tests and reasons for the failure, helping you debug quickly.</p>
</li>
<li><p>For workflows that use secrets, errors related to missing secrets will appear in the environment setup steps, allowing you to fix any configuration issues.</p>
</li>
</ul>
<p>By understanding how to interpret these logs, you can address issues proactively and ensure smooth, reliable deployments.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>By following these steps, you’ve set up automated GitHub workflows for both the frontend and backend of your application.</p>
<p>This setup ensures your tests run automatically with each push to the <code>main</code> branch, helping maintain high code quality and reliability.</p>
<p>With automated workflows, you can focus more on building features and less on manually testing code, knowing that your workflows will alert you to any issues early on.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
