Deployment Guide: Deploying to Render

← Back to Main Tutorial

Understanding the Problem

Up to this point, we've been developing and testing our Express authentication application locally on our own computer. While this is perfect for development, eventually we need to make our application available to everyone on the internet. This process of making an application available online is called deployment.

Deployment involves several key challenges:

In this phase, we'll deploy our application to Render, a cloud platform that offers free hosting for web services and databases. Render makes it relatively easy to deploy Express applications, but there are several important steps and considerations we need to address.

Planning the Solution

  1. Set up a package.json file at the project root
  2. Create a Render.com account
  3. Create a PostgreSQL database instance on Render
  4. Create a new web service on Render
  5. Configure build and start commands
  6. Set up environment variables
  7. Deploy the application
  8. Test the deployed application
  9. Understand ongoing maintenance requirements

Implementing the Solution

1. Set Up a package.json File at the Project Root

When deploying to Render, we need a package.json file at the root of our project (outside of both the backend and frontend folders). This file will define scripts that Render will use to install dependencies and start our application.

// Navigate to the project root (outside of backend and frontend)
cd ..
npm init -y

Now, let's modify the package.json to include the necessary scripts:

// package.json (in the project root)
{
  "name": "your-project-name",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "install": "npm --prefix backend install backend",
    "dev:backend": "npm install --prefix backend start",
    "sequelize": "npm run --prefix backend sequelize",
    "sequelize-cli": "npm run --prefix backend sequelize-cli",
    "start": "npm start --prefix backend",
    "build": "npm run --prefix backend build"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

These scripts tell Render:

Commit these changes to your main branch:

git add .
git commit -m "Add root package.json for deployment"
git checkout main
git merge dev
git push origin main

2. Set Up a Render.com Account

If you don't already have a Render.com account, you'll need to create one:

  1. Go to Render.com and click "Get Started"
  2. Sign up with GitHub (recommended) to easily connect your repositories
  3. Follow the instructions to complete your registration and verify your account

3. Create a PostgreSQL Database Instance

Now, let's create a PostgreSQL database that our application will use in production:

  1. From your Render dashboard, click "New +" and select "PostgreSQL"
  2. Give your database a name (e.g., "app-academy-projects")
  3. Choose the region closest to you
  4. Leave the other fields with their default values
  5. Click "Create Database"

After the database is created (which may take a few minutes), Render will display important information about your database, including:

Take note of the "Internal Database URL" - we'll need this later.

4. Create a New Web Service

Next, let's create a web service to host our Express application:

  1. From your Render dashboard, click "New +" and select "Web Service"
  2. Connect your GitHub repository
  3. If you don't see your repository, click "Configure Account" for GitHub in the sidebar to connect your GitHub account
  4. Find your project repository and click "Connect"

5. Configure the Web Service

Now, configure the web service with the following settings:

npm install && npm run build && npm run sequelize --prefix backend db:seed:undo:all && npm run sequelize --prefix backend db:migrate:undo:all && npm run sequelize --prefix backend db:migrate && npm run sequelize --prefix backend db:seed:all

This build command:

  1. Installs dependencies
  2. Runs the build script
  3. Undoes all seed data and migrations
  4. Runs all migrations to set up the database schema
  5. Seeds the database with initial data

Note: This build command is designed for development and testing. For a final production deployment, you might want to remove the "undo" steps to preserve your data:

npm install && npm run build && npm run sequelize --prefix backend db:migrate && npm run sequelize --prefix backend db:seed:all

6. Set Up Environment Variables

Scroll down to the "Environment Variables" section and add the following variables:

Make sure "Auto-Deploy" is set to "Yes" in the Advanced section. This will automatically redeploy your application when you push to the main branch.

7. Deploy the Application

Click "Create Web Service" to start the deployment process. This will take some time (usually 10-15 minutes) as Render:

  1. Builds your application according to the build command
  2. Sets up the environment variables
  3. Starts your application using the start command

You can monitor the progress in the logs. Once the deployment is complete, Render will provide a URL where your application is accessible (e.g., https://your-app-name.onrender.com).

8. Test the Deployed Application

Let's test our deployed API to make sure everything is working correctly:

  1. First, test the CSRF token route: https://your-app-name.onrender.com/api/csrf/restore
  2. You should see a JSON response with a CSRF token
  3. Use this token to test your login endpoint using a tool like Postman or a fetch request in a browser console

Example fetch request to test login:

fetch('https://your-app-name.onrender.com/api/session', {
  method: 'POST',
  headers: {
    "Content-Type": "application/json",
    "XSRF-TOKEN": "your-csrf-token-here"
  },
  body: JSON.stringify({ credential: 'Demo-lition', password: 'password' })
}).then(res => res.json()).then(data => console.log(data));

Test other endpoints similarly to ensure they're all working correctly.

9. Understand Ongoing Maintenance

With Render's free tier, there's an important limitation to be aware of: your PostgreSQL database instance will be deleted after 90 days. To keep your application running, you'll need to create a new database instance before that happens.

Set a calendar reminder for 85 days from now (to give yourself some buffer) with these steps:

  1. Create a new PostgreSQL database instance on Render
  2. Update the DATABASE_URL environment variable in your web service with the new URL
  3. Manually trigger a new deployment

This will ensure your application continues to run smoothly without data loss.

Review the Solution

We've successfully deployed our Express authentication application to Render! Let's review what we've accomplished:

Deployment Architecture

Our deployment architecture consists of two main components:

  1. PostgreSQL Database: Stores our user data and other application information
  2. Web Service: Runs our Express application, handling HTTP requests and interacting with the database

This is a simple but effective architecture for many web applications. As your application grows, you might consider more complex architectures with separate services for different parts of your application, content delivery networks (CDNs) for static assets, and caching layers for improved performance.

Development vs. Production Environments

It's important to understand the key differences between our development and production environments:

Aspect Development (Local) Production (Render)
Database SQLite (file-based) PostgreSQL (server-based)
Environment development production
Hosting Local machine Render cloud platform
Error Visibility Detailed (includes stack traces) Limited (no stack traces)
Security Settings More relaxed (e.g., CORS enabled) Stricter (e.g., secure cookies required)

Real-world Deployment Considerations

In real-world applications, deployment often involves additional considerations:

While our deployment is relatively simple, these principles are still important to consider, especially as your application grows.

Common Issues and Solutions

Debugging in Production

When issues occur in production, you have several tools at your disposal:

  1. Render Logs: Check the logs in your Render dashboard for error messages and application output.
  2. Manual Testing: Use tools like Postman or browser fetch requests to test endpoints directly.
  3. Database Inspection: Connect to your PostgreSQL database to verify data and schema.
  4. Local Replication: Try to replicate the issue locally by setting up similar environment variables.

Remember, debugging in production requires a careful, methodical approach to avoid introducing new issues or causing downtime.

Conclusion

Congratulations! You've successfully built and deployed a complete Express authentication application. This application provides a solid foundation for any web project that requires user authentication. You can now build frontend applications that use this API for authentication, or extend the API with additional features specific to your application.

Throughout this tutorial, you've learned how to:

These skills are fundamental to full-stack web development and will serve you well in building a wide variety of web applications.

Next Steps

Now that you have a working authentication API, here are some ways you might extend or build upon it:

Whatever path you choose, the authentication system you've built provides a solid foundation for your application's security needs.