How to Deploy to Heroku
How to Deploy to Heroku Deploying a web application to Heroku is one of the most accessible and efficient ways for developers to bring their projects live—whether they’re building a personal portfolio, a startup MVP, or a small-scale SaaS product. Heroku, a cloud platform as a service (PaaS) owned by Salesforce, abstracts away the complexities of server management, allowing developers to focus on
How to Deploy to Heroku
Deploying a web application to Heroku is one of the most accessible and efficient ways for developers to bring their projects livewhether theyre building a personal portfolio, a startup MVP, or a small-scale SaaS product. Heroku, a cloud platform as a service (PaaS) owned by Salesforce, abstracts away the complexities of server management, allowing developers to focus on writing code rather than configuring infrastructure. With its intuitive command-line interface, seamless integration with Git, and automatic scaling capabilities, Heroku has become a go-to platform for developers across the globe.
Deploying to Heroku isnt just about uploading filesits about establishing a reliable, scalable, and maintainable deployment pipeline. This tutorial provides a comprehensive, step-by-step guide to deploying applications to Heroku, covering everything from setting up your account to troubleshooting common issues. Whether youre deploying a Node.js app, a Python Flask application, a Ruby on Rails backend, or even a static site, this guide ensures you understand the underlying principles and best practices that lead to successful, production-ready deployments.
By the end of this guide, youll not only know how to deploy to Herokuyoull know how to do it securely, efficiently, and in alignment with industry standards. This is not a surface-level walkthrough. Its a deep dive into the mechanics, tools, and strategies that make Heroku deployments robust and repeatable.
Step-by-Step Guide
Prerequisites: What You Need Before You Start
Before you begin deploying to Heroku, ensure you have the following tools and accounts ready:
- A Heroku account (free tier available at signup.heroku.com)
- Git installed on your local machine
- A terminal or command-line interface (Terminal on macOS/Linux, Command Prompt or PowerShell on Windows)
- A working application (Node.js, Python, Ruby, Java, PHP, Go, or static HTML/CSS/JS)
- A GitHub or GitLab account (optional but recommended for version control)
Heroku supports a wide range of programming languages and frameworks. Your application must be structured to meet Herokus runtime requirements, which well cover in detail later.
Step 1: Create a Heroku Account
Visit https://signup.heroku.com and sign up using your email address. You can also sign up using your Google or GitHub account for faster onboarding. Once registered, verify your email address. Heroku requires email verification to activate your account and unlock full features.
After verification, log in to the Heroku Dashboard. This is your central hub for managing apps, viewing logs, configuring add-ons, and monitoring performance.
Step 2: Install the Heroku CLI
The Heroku Command Line Interface (CLI) is the primary tool for deploying and managing applications. It allows you to interact with Herokus platform directly from your terminal.
Visit the official Heroku CLI download page: https://devcenter.heroku.com/articles/heroku-cli
Follow the installation instructions for your operating system:
- macOS: Use Homebrew:
brew tap heroku/brew && brew install heroku - Windows: Download the installer from the Heroku website and run it
- Linux: Use curl:
curl https://cli-assets.heroku.com/install.sh | sh
After installation, verify the CLI is working by typing:
heroku --version
You should see output like: heroku/7.60.0 linux-x64 node-v14.17.0
Step 3: Log in to Heroku via CLI
Open your terminal and authenticate with Heroku using:
heroku login
This command opens a browser window where youll be prompted to log in to your Heroku account. After successful authentication, your terminal will display: Logged in as your-email@example.com.
Alternatively, if you prefer to log in via the command line without opening a browser, use:
heroku login -i
Then enter your email and password when prompted.
Step 4: Prepare Your Application
Heroku requires specific files to detect and run your application. These files vary by language. Below are the most common configurations:
Node.js Applications
Ensure your project has a package.json file in the root directory. This file must include a start script. Example:
{
"name": "my-node-app",
"version": "1.0.0",
"main": "server.js",
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js"
},
"dependencies": {
"express": "^4.18.0"
}
}
Heroku automatically detects Node.js apps via the presence of package.json. It will run npm install and then npm start during deployment.
Python Applications
For Python apps (Django, Flask, FastAPI, etc.), you need:
- A
requirements.txtfile listing all dependencies - A
Procfilespecifying the command to start your app
Generate requirements.txt using:
pip freeze > requirements.txt
Create a Procfile (no file extension) in the root directory:
web: gunicorn myapp:app
Replace myapp with your main Python module and app with the Flask/Django app instance name.
Ruby on Rails Applications
Rails apps require a Gemfile and a Procfile. Heroku automatically detects Ruby apps via Gemfile.
Ensure your Procfile contains:
web: bundle exec rails server -p $PORT
Static Sites (HTML, CSS, JS)
Heroku supports static sites via the static-buildpack. Create a Procfile with:
web: npx serve -s .
Install serve as a dependency in your package.json:
{
"name": "my-static-site",
"scripts": {
"start": "serve -s ."
},
"dependencies": {
"serve": "^14.2.0"
}
}
Alternatively, use the Heroku Static Buildpack by setting it explicitly:
heroku buildpacks:set heroku/static
Step 5: Initialize a Git Repository
Heroku uses Git for deployment. If your project isnt already under version control, initialize a Git repo:
git init
git add .
git commit -m "Initial commit"
Ensure your .gitignore file excludes unnecessary files like node_modules/, .env, __pycache__/, or venv/.
Step 6: Create a Heroku App
In your terminal, navigate to your project directory and run:
heroku create
This command creates a new app on Heroku with a random name (e.g., radiant-savannah-12345) and adds a remote Git repository named heroku.
To assign a custom name, use:
heroku create your-app-name
Ensure the name is unique across Heroku. If taken, Heroku will return an error.
Verify the remote was added:
git remote -v
You should see:
heroku https://git.heroku.com/your-app-name.git (fetch)
heroku https://git.heroku.com/your-app-name.git (push)
Step 7: Deploy Your Application
Deployment is as simple as pushing your code to Herokus remote:
git push heroku main
If your default branch is master instead of main, use:
git push heroku master
Heroku will automatically detect your apps language, install dependencies, compile assets (if needed), and start your application using the command specified in your Procfile.
During deployment, youll see logs in your terminal like:
Counting objects: 25, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (20/20), done.
Writing objects: 100% (25/25), 3.21 KiB | 1.07 MiB/s, done.
Total 25 (delta 6), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Node.js app detected
remote: -----> Creating runtime environment
remote: -----> Installing Node.js 18.15.0
remote: -----> Installing dependencies
remote: Installing node modules
remote: -----> Build succeeded!
remote: -----> Discovering process types
remote: Procfile declares types -> web
remote:
remote: -----> Compressing...
remote: Done: 35.4M
remote: -----> Launching...
remote: Released v3
remote: https://your-app-name.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/your-app-name.git
* [new branch] main -> main
Once deployment completes, Heroku will provide a URL where your app is live.
Step 8: Open Your App in the Browser
To open your deployed app immediately, run:
heroku open
This command opens your apps live URL in your default web browser.
Step 9: View Logs for Debugging
If your app fails to start or throws errors, check the logs:
heroku logs --tail
This streams real-time logs. Common issues include:
- Missing
Procfile - Incorrect start script in
package.json - Port binding errors (use
process.env.PORTin code) - Missing dependencies in
requirements.txtorGemfile
For example, in Node.js, always use:
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(Server running on port ${port});
});
Heroku dynamically assigns a port via the PORT environment variable. Hardcoding ports like 3000 will cause your app to crash on deployment.
Step 10: Configure Environment Variables
Never commit secrets like API keys, database URLs, or JWT secrets to your codebase. Use Herokus Config Vars instead.
To set an environment variable:
heroku config:set API_KEY=your-secret-key
To view all config vars:
heroku config
To remove a variable:
heroku config:unset API_KEY
In your application code, access these variables using process.env.API_KEY (Node.js), os.getenv('API_KEY') (Python), or ENV['API_KEY'] (Ruby).
Step 11: Scale Your App (Optional)
By default, Heroku runs your app on a single free dyno. To scale up for better performance:
heroku ps:scale web=1
For paid plans, you can scale to multiple dynos:
heroku ps:scale web=2
Or use auto-scaling with add-ons like heroku-autoscale.
Step 12: Connect a Custom Domain (Optional)
To use your own domain (e.g., www.yourdomain.com):
- Go to your apps dashboard on Heroku
- Click Settings ? Add domain
- Enter your domain name
- Follow the DNS setup instructions (typically adding a CNAME or ALIAS record with your domain registrar)
Heroku will provide you with a DNS target (e.g., your-app-name.herokuapp.com) to point your domain to.
Enable HTTPS automatically by clicking Enable HTTPS in the dashboard. Heroku provides free SSL certificates via Lets Encrypt.
Best Practices
Use a Procfile for Explicit Process Control
Always define a Procfile even if your app is detected automatically. It removes ambiguity and ensures consistent behavior across environments. The Procfile must be in the root directory and contain no file extension.
Never Commit Sensitive Data
Use a .env file for local development, but never commit it to Git. Add it to your .gitignore:
.env
.env.local
.env.development
Use the dotenv package for Node.js or python-dotenv for Python to load local variables during development. But in production, rely solely on Heroku Config Vars.
Pin Your Dependencies
Always use exact versions in your dependency files:
- Node.js: Use
package-lock.jsonand commit it - Python: Use
pip freeze > requirements.txt(notpip installwithout versioning) - Ruby: Use
Gemfile.lockand commit it
This ensures reproducible builds. Heroku uses the lockfile to install exact versions, preventing unexpected breakages due to dependency updates.
Use Buildpacks Appropriately
Heroku uses buildpacks to compile and prepare your app. Most apps auto-detect, but you can specify one explicitly if needed:
heroku buildpacks:set heroku/nodejs
For multi-language apps (e.g., React frontend + Node.js backend), use multiple buildpacks:
heroku buildpacks:set heroku/nodejs
heroku buildpacks:add --index 1 heroku/python
Use heroku buildpacks to list current buildpacks.
Monitor Performance and Logs
Enable Herokus Log Drains to send logs to external services like Papertrail, LogDNA, or Datadog for long-term analysis.
Use the Heroku Dashboard to monitor memory usage, response times, and dyno health. Free dynos sleep after 30 minutes of inactivityconsider upgrading to Hobby ($7/month) for 24/7 uptime.
Implement Health Checks
Add a simple health endpoint to your app:
app.get('/health', (req, res) => {
res.status(200).json({ status: 'OK', uptime: process.uptime() });
});
Heroku uses this endpoint to determine if your app is responsive. If your app doesnt respond to HTTP requests within 60 seconds, Heroku restarts the dyno.
Use Git Tags for Versioning
Tag your releases for traceability:
git tag v1.0.0
git push origin v1.0.0
git push heroku v1.0.0:main
This allows you to roll back to a known good version quickly.
Enable Automatic Deploys from GitHub
Connect your GitHub repository to Heroku for continuous deployment:
- In the Heroku Dashboard, go to your app
- Click the Deploy tab
- Under Deployment method, select GitHub
- Connect your GitHub account and search for your repo
- Enable Automatic Deploys for your main branch
Now, every push to GitHub automatically triggers a Heroku deployment. This is ideal for teams practicing CI/CD.
Regularly Update Dependencies
Use tools like npm audit, pip-check, or dependabot to identify vulnerable or outdated dependencies. Herokus build system uses the latest versions of runtimes, but your apps dependencies may lag behind.
Tools and Resources
Heroku CLI
The official Heroku Command Line Interface is indispensable. It allows you to manage apps, view logs, scale dynos, and configure environment variablesall from your terminal. Download and install it at https://devcenter.heroku.com/articles/heroku-cli.
Heroku Dashboard
The web-based dashboard is your control center for monitoring app health, viewing metrics, managing add-ons, and configuring domains. Access it at https://dashboard.heroku.com.
Heroku Dev Center
The official documentation hub for all things Heroku. It includes in-depth guides, language-specific buildpacks, and troubleshooting articles. Visit: https://devcenter.heroku.com.
Heroku Postgres
Herokus managed PostgreSQL database service. It integrates seamlessly with your app and offers a free tier for development. Add it via:
heroku addons:create heroku-postgresql:hobby-dev
Access connection details with:
heroku config:get DATABASE_URL
Heroku Redis
For caching, session storage, or background jobs, use Heroku Redis. Install with:
heroku addons:create heroku-redis:hobby-dev
GitHub Actions for CI/CD
Combine Heroku with GitHub Actions for automated testing and deployment. Example workflow:
name: Deploy to Heroku
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Deploy to Heroku
uses: akhileshns/heroku-deploy@v3.12.12
with:
heroku_api_key: ${{ secrets.HEROKU_API_KEY }}
heroku_app_name: "your-app-name"
heroku_email: "your-email@example.com"
wait: true
Store your Heroku API key as a secret in GitHub Settings ? Secrets.
Heroku Scheduler
For running periodic tasks (e.g., data cleanup, email reports), use Heroku Scheduler (free add-on). It runs cron jobs on a one-off dyno.
Log Management Tools
- Papertrail Real-time log aggregation
- LogDNA Advanced log analysis
- Datadog Full-stack monitoring
Local Testing Tools
- Foreman Test your Procfile locally:
foreman start - Heroku Local Herokus own tool to simulate the Heroku environment:
heroku local
Real Examples
Example 1: Deploying a Node.js Express App
Project Structure:
/my-express-app
??? server.js
??? package.json
??? Procfile
??? .gitignore
server.js:
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.send('Hello from Heroku!');
});
app.listen(PORT, () => {
console.log(Server running on port ${PORT});
});
package.json:
{
"name": "my-express-app",
"version": "1.0.0",
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"dependencies": {
"express": "^4.18.0"
}
}
Procfile:
web: node server.js
Deployment Steps:
git initgit add .git commit -m "Initial commit"heroku creategit push heroku mainheroku open
Result: Your app is live at https://your-app-name.herokuapp.com.
Example 2: Deploying a Python Flask App with PostgreSQL
Project Structure:
/my-flask-app
??? app.py
??? requirements.txt
??? Procfile
??? .gitignore
app.py:
from flask import Flask
import os
app = Flask(__name__)
@app.route('/')
def home():
return "Flask app running on Heroku with PostgreSQL!"
if __name__ == '__main__':
port = int(os.environ.get('PORT', 5000))
app.run(host='0.0.0.0', port=port)
requirements.txt:
Flask==2.3.3
gunicorn==21.2.0
Procfile:
web: gunicorn app:app
Deployment Steps:
pip freeze > requirements.txtheroku creategit add .git commit -m "Deploy Flask app"git push heroku mainheroku addons:create heroku-postgresql:hobby-devheroku open
Now your Flask app is live with a free PostgreSQL database attached.
Example 3: Deploying a React Frontend with Node.js Backend
Many modern apps separate frontend and backend. Heres how to deploy both on Heroku:
- Frontend: React app built in
/client - Backend: Express server in root
Backend (root directory):
package.jsonincludes"start": "node server.js"server.jsserves the React build:
const express = require('express');
const path = require('path');
const app = express();
const PORT = process.env.PORT || 5000;
app.use(express.static(path.join(__dirname, 'client/build')));
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'client/build/index.html'));
});
app.listen(PORT, () => {
console.log(Server running on port ${PORT});
});
Frontend:
- Build React app:
npm run build - Ensure
client/buildfolder exists
Deploy:
- Build React app locally:
cd client && npm run build - Commit both folders
- Push to Heroku:
git push heroku main
Heroku runs the Express server, which serves the React build as static files. No need for two appsthis is a single-app deployment with dual logic.
FAQs
Q: Is Heroku free to use?
A: Yes, Heroku offers a free tier that includes one dyno (web server) with 550 free dyno hours per month. However, free dynos sleep after 30 minutes of inactivity, which means your app will take 510 seconds to wake up on first visit. For production apps, consider upgrading to the Hobby plan ($7/month) for 24/7 uptime.
Q: How do I rollback a deployment?
A: Use the Heroku CLI to rollback to a previous release:
heroku releases
This lists all deployments. Find the version number you want to revert to (e.g., v12), then run:
heroku rollback v12
Heroku will redeploy that version instantly.
Q: Why is my app crashing after deployment?
A: Common causes include:
- Missing or incorrect
Procfile - Hardcoded port (use
process.env.PORT) - Missing dependencies in
package.jsonorrequirements.txt - Environment variables not set in Heroku Config Vars
- Database connection errors (e.g., missing PostgreSQL add-on)
Check logs with heroku logs --tail to identify the exact error.
Q: Can I deploy multiple apps on one Heroku account?
A: Yes. You can create as many apps as you need under a single Heroku account. Each app has its own URL, config vars, and add-ons. Use heroku create --name your-app-name to create additional apps.
Q: Does Heroku support databases?
A: Yes. Heroku offers managed PostgreSQL, Redis, MongoDB (via add-ons), and more. Use heroku addons:create heroku-postgresql:hobby-dev to add a free PostgreSQL database. Connection strings are automatically injected via the DATABASE_URL environment variable.
Q: How do I update my app after the initial deployment?
A: Make changes locally, commit them to Git, and push to Heroku:
git add .
git commit -m "Update homepage"
git push heroku main
Heroku will detect the changes and redeploy automatically.
Q: Can I use Heroku with Docker?
A: Yes. Heroku supports container-based deployments using Docker. Create a Dockerfile in your project root, then use:
heroku container:login
heroku container:push web -a your-app-name
heroku container:release web -a your-app-name
This is ideal for complex applications requiring custom environments.
Q: What happens if I exceed my free dyno hours?
A: Once you exceed 550 free dyno hours in a month, your apps will sleep until the next billing cycle. Youll receive an email notification. To avoid interruption, upgrade to a paid plan or use the free tier only for development/testing.
Q: Is Heroku secure?
A: Yes. Heroku provides SSL certificates by default, network isolation, and regular security updates. However, security is a shared responsibility. You must:
- Use environment variables for secrets
- Keep dependencies updated
- Enable two-factor authentication on your Heroku account
- Use HTTPS for all communications
Conclusion
Deploying to Heroku is more than a technical taskits a gateway to rapid iteration, reliable hosting, and scalable growth. By following the steps outlined in this guide, youve not only learned how to push code to a cloud platform; youve adopted the discipline of modern software deployment: version control, environment separation, automated builds, and continuous monitoring.
Herokus power lies in its simplicity. It removes the friction of infrastructure management so you can focus on what matters: building great software. Whether youre a solo developer shipping your first app or a team iterating on a product, Heroku provides the foundation to move fast and stay reliable.
Remember: deployment is not a one-time event. Its a recurring practice. Embrace automated deploys, monitor your logs, update dependencies, and test in staging before pushing to production. With these habits, your Heroku deployments will become seamless, predictable, and scalable.
Now that you know how to deploy to Heroku, the next step is to deploy something meaningful. Build an app. Break it. Fix it. Deploy it again. Thats how mastery is built.