Skip to main content
RapidDev - Software Development Agency
replit-tutorial

How to deploy a Flask app on Replit

Deploying a Flask app on Replit requires binding the server to 0.0.0.0, using gunicorn as the production WSGI server, configuring the .replit file with proper deployment commands, and adding all secrets to the deployment configuration separately. Set the port to use the PORT environment variable, configure the deployment target as cloudrun for Autoscale, and ensure the health check endpoint responds within 5 seconds. The most common deployment failure is binding to localhost instead of 0.0.0.0.

What you'll learn

  • Configure Flask to bind to 0.0.0.0 and use the correct port for Replit
  • Set up gunicorn as the production WSGI server
  • Configure the .replit file with build and deployment commands
  • Troubleshoot the most common Flask deployment errors on Replit
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Advanced8 min read25 minutesReplit Core and Pro plans (Autoscale deployment requires paid plan)March 2026RapidDev Engineering Team
TL;DR

Deploying a Flask app on Replit requires binding the server to 0.0.0.0, using gunicorn as the production WSGI server, configuring the .replit file with proper deployment commands, and adding all secrets to the deployment configuration separately. Set the port to use the PORT environment variable, configure the deployment target as cloudrun for Autoscale, and ensure the health check endpoint responds within 5 seconds. The most common deployment failure is binding to localhost instead of 0.0.0.0.

Deploying Flask on Replit: From Development to Production with Gunicorn and Autoscale

Flask is one of the most popular Python web frameworks, and Replit provides built-in hosting to deploy Flask apps without managing servers. However, Flask's built-in development server is not suitable for production. This tutorial walks through setting up a Flask project, replacing the development server with gunicorn, configuring the .replit file for deployment, handling environment-specific settings, and troubleshooting the most common deployment errors. By the end, your Flask app will be live on a Replit Autoscale deployment with proper error handling and health checks.

Prerequisites

  • A Replit Core or Pro account for production deployments
  • Basic Python knowledge and familiarity with Flask routing
  • Understanding of how pip and requirements.txt work
  • Familiarity with Replit Secrets for storing environment variables
  • Knowledge of the difference between development and production servers

Step-by-step guide

1

Create a Flask project with the correct structure

Start a new Python project on Replit or ask Agent to create a Flask web application. Your project needs at minimum an app.py file, a requirements.txt listing Flask and gunicorn, and a .replit configuration file. Organize larger projects with a standard Flask structure using templates/, static/, and a dedicated config module. Install Flask and gunicorn from the Shell with pip install flask gunicorn, then freeze the dependencies to requirements.txt.

typescript
1# In the Shell terminal
2pip install flask gunicorn
3pip freeze > requirements.txt

Expected result: Your project has Flask and gunicorn installed, and requirements.txt lists all dependencies with version numbers.

2

Write the Flask app with 0.0.0.0 binding

Create your main Flask application file. The critical configuration for Replit is binding the server to 0.0.0.0 instead of the default 127.0.0.1 or localhost. Without this, Replit cannot detect the running server and the deployment fails with 'hostingpid1: an open port was not detected.' Also read the port from the PORT environment variable since Replit assigns it dynamically in production. Add a health check route at the root path that responds quickly, as the deployment health check must complete within 5 seconds.

typescript
1# app.py
2import os
3from flask import Flask, jsonify
4
5app = Flask(__name__)
6
7@app.route('/')
8def health_check():
9 return jsonify({
10 'status': 'ok',
11 'environment': 'production' if os.getenv('REPLIT_DEPLOYMENT') == '1' else 'development'
12 })
13
14@app.route('/api/hello')
15def hello():
16 return jsonify({'message': 'Hello from Flask on Replit!'})
17
18if __name__ == '__main__':
19 port = int(os.getenv('PORT', 5000))
20 debug = os.getenv('REPLIT_DEPLOYMENT') != '1'
21 app.run(host='0.0.0.0', port=port, debug=debug)

Expected result: The Flask app starts, binds to 0.0.0.0, and the preview pane shows the health check JSON response.

3

Configure gunicorn as the production WSGI server

Flask's built-in server handles one request at a time and is not designed for production traffic. Gunicorn is a production-grade WSGI server that runs multiple worker processes to handle concurrent requests. Create a gunicorn configuration file to set the number of workers, bind address, and timeout. The number of workers should typically be 2 to 4 for Replit's resource constraints. Higher counts consume more RAM and may cause out-of-memory errors.

typescript
1# gunicorn.conf.py
2import os
3
4bind = f"0.0.0.0:{os.getenv('PORT', '5000')}"
5workers = 2
6threads = 2
7timeout = 120
8accesslog = '-'
9errorlog = '-'
10loglevel = 'info'

Expected result: The gunicorn configuration file is saved and ready for use in the deployment run command.

4

Configure the .replit file for Flask deployment

Open the .replit file and set up both development and deployment configurations. The run command starts Flask's development server for local testing. The [deployment] section uses gunicorn for production. The build command installs dependencies from requirements.txt. Set the deployment target to cloudrun for Autoscale deployments. Configure the port mapping with localPort matching your Flask port and externalPort set to 80.

typescript
1entrypoint = "app.py"
2run = "python app.py"
3
4modules = ["python-3.11:v18-20230807-322e88b"]
5
6[nix]
7channel = "stable-24_05"
8packages = ["python311", "python311Packages.pip"]
9
10[[ports]]
11localPort = 5000
12externalPort = 80
13
14[deployment]
15build = ["pip", "install", "-r", "requirements.txt"]
16run = ["gunicorn", "--config", "gunicorn.conf.py", "app:app"]
17deploymentTarget = "cloudrun"

Expected result: The .replit file has separate dev and production configurations. Clicking Run starts the dev server, and deploying uses gunicorn.

5

Add secrets to both workspace and deployment configuration

Store all sensitive values like API keys, database credentials, and secret keys in Replit Secrets. Open Tools > Secrets and add each key-value pair. Flask apps commonly need a SECRET_KEY for session security and any external API keys. After adding workspace secrets, open the Deployments pane and add the same secrets there. This is the most common cause of Flask deployment failures: secrets that work in development return None in production because they were not added to the deployment configuration.

typescript
1# app.py - Reading secrets
2import os
3
4app.config['SECRET_KEY'] = os.getenv('FLASK_SECRET_KEY', 'dev-key-change-me')
5
6# Validate required secrets at startup
7required_secrets = ['FLASK_SECRET_KEY', 'DATABASE_URL']
8for secret in required_secrets:
9 if not os.getenv(secret):
10 if os.getenv('REPLIT_DEPLOYMENT') == '1':
11 raise RuntimeError(
12 f'{secret} is not set. Add it in Deployments > Secrets.'
13 )

Expected result: All required secrets are configured in both the workspace Secrets panel and the deployment configuration.

6

Deploy and troubleshoot common errors

Click the Deploy button in the Deployments pane and select Autoscale. Configure CPU and RAM settings, then click Deploy. Watch the deployment logs for errors. The most common errors are: 'hostingpid1: an open port was not detected' (server not bound to 0.0.0.0 or wrong port), health check timeout (root route takes more than 5 seconds), and 'ModuleNotFoundError' (dependency not in requirements.txt). If the deployment fails, check the Logs tab in the Deployments pane for the exact error message. For complex Flask deployments with multiple services, teams can consult RapidDev for architecture guidance.

Expected result: Your Flask app is live on a .replit.app URL. The health check responds with a JSON status message.

Complete working example

app.py
1# app.py
2# Production-ready Flask app for Replit deployment
3
4import os
5from flask import Flask, jsonify, request
6from functools import wraps
7
8app = Flask(__name__)
9app.config['SECRET_KEY'] = os.getenv('FLASK_SECRET_KEY', 'dev-key-change-me')
10
11is_production = os.getenv('REPLIT_DEPLOYMENT') == '1'
12
13# Validate secrets in production
14if is_production:
15 required = ['FLASK_SECRET_KEY']
16 missing = [s for s in required if not os.getenv(s)]
17 if missing:
18 raise RuntimeError(f'Missing secrets: {", ".join(missing)}')
19
20
21def log_request(f):
22 @wraps(f)
23 def decorated(*args, **kwargs):
24 app.logger.info(f'{request.method} {request.path}')
25 return f(*args, **kwargs)
26 return decorated
27
28
29@app.route('/')
30def health_check():
31 return jsonify({
32 'status': 'ok',
33 'environment': 'production' if is_production else 'development',
34 'version': '1.0.0',
35 })
36
37
38@app.route('/api/items', methods=['GET'])
39@log_request
40def get_items():
41 try:
42 items = [
43 {'id': 1, 'name': 'Item One'},
44 {'id': 2, 'name': 'Item Two'},
45 ]
46 return jsonify(items)
47 except Exception as e:
48 app.logger.error(f'Error: {str(e)}')
49 message = 'Internal server error' if is_production else str(e)
50 return jsonify({'error': message}), 500
51
52
53@app.errorhandler(404)
54def not_found(e):
55 return jsonify({'error': 'Not found'}), 404
56
57
58@app.errorhandler(500)
59def server_error(e):
60 return jsonify({'error': 'Internal server error'}), 500
61
62
63if __name__ == '__main__':
64 port = int(os.getenv('PORT', 5000))
65 app.run(host='0.0.0.0', port=port, debug=not is_production)

Common mistakes when deploying a Flask app on Replit

Why it's a problem: Running Flask's built-in server in production instead of gunicorn

How to avoid: Flask's development server handles one request at a time and is not secure. Use gunicorn in the [deployment] run command: gunicorn --config gunicorn.conf.py app:app.

Why it's a problem: Binding to localhost or 127.0.0.1 instead of 0.0.0.0

How to avoid: Replit requires the server to bind to 0.0.0.0 for the port to be detected. Change app.run(host='0.0.0.0') or set bind = '0.0.0.0:PORT' in gunicorn.conf.py.

Why it's a problem: Hardcoding the port number instead of reading from PORT env var

How to avoid: Replit assigns the port dynamically in production. Use port = int(os.getenv('PORT', 5000)) to read the assigned port with a fallback for development.

Why it's a problem: Not including gunicorn in requirements.txt

How to avoid: If gunicorn is not in requirements.txt, the deployment build cannot install it. Run pip freeze > requirements.txt after installing gunicorn.

Why it's a problem: Leaving debug=True enabled in production

How to avoid: Debug mode exposes stack traces and enables the interactive debugger, which is a security risk. Disable it in production: debug = os.getenv('REPLIT_DEPLOYMENT') != '1'.

Best practices

  • Always bind Flask to 0.0.0.0, never localhost or 127.0.0.1, for Replit deployments
  • Use gunicorn with 2 to 4 workers for production instead of Flask's built-in development server
  • Read the port from the PORT environment variable since Replit assigns it dynamically
  • Disable debug mode in production using the REPLIT_DEPLOYMENT environment variable
  • Freeze dependencies with pip freeze > requirements.txt after every package installation
  • Add all secrets to both workspace Secrets and the deployment configuration separately
  • Create a health check endpoint at the root path that responds in under 5 seconds
  • Validate required secrets at startup with clear error messages in production

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I want to deploy a Flask web application on Replit using gunicorn and Autoscale hosting. Show me the app.py, gunicorn configuration, .replit file, and explain how to handle secrets for both development and production environments.

Replit Prompt

Create a Flask web application with gunicorn for production deployment. Configure the .replit file with development and production run commands. Bind the server to 0.0.0.0 and read the port from the PORT environment variable. Add a health check endpoint at the root path. Validate required secrets at startup.

Frequently asked questions

The most common cause is missing secrets. Workspace secrets do not transfer to deployments. Add every secret your app needs in the Deployments pane configuration. The second most common cause is binding to localhost instead of 0.0.0.0.

This error means Replit's health check could not find a listening server. The server is either bound to localhost instead of 0.0.0.0, using the wrong port, or the process crashed before starting to listen.

Start with 2 workers for the Core plan (8 GiB RAM). Each worker duplicates the app in memory. Monitor RAM usage in the Resources panel and increase workers only if you have headroom. Going above 4 workers on Replit is rarely beneficial.

Yes. Serve your React build output from Flask's static file handling or use Flask as an API backend with React running on a separate port. Configure both ports in the .replit file.

The Starter plan supports development but production deployments require Core ($25/month) or Pro ($100/month). Autoscale deployments have a $1/month base fee plus usage-based compute charges.

Enable the PostgreSQL database from the Tools dock. Replit injects DATABASE_URL as an environment variable. Use it with SQLAlchemy or psycopg2 to connect. The database persists across deployments.

The Python version depends on your Nix configuration. Specify the version in .replit under [nix] packages, for example pkgs.python311 for Python 3.11. Check available versions at search.nixos.org/packages.

Yes. Replit supports Django with the same deployment configuration pattern. Replace Flask-specific commands with Django's: use gunicorn project.wsgi:application for the deployment run command and python manage.py migrate in the build step.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.