Halloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix NowHalloween DealsAmazon USOctober picks are moving - compare before checkoutAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk11 min

How to Run Multiple Flask Applications on One Server

Deploy multiple Flask applications safely by giving each its own environment and Gunicorn service, then routing them through one private-backend reverse proxy. Learn when to use nginx, Apache/mod_wsgi or DispatcherMiddleware, plus configuration, testing and recovery steps.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Run each Flask application as its own production WSGI service, usually with Gunicorn, and put one nginx or Apache reverse proxy in front. Give every service a separate project directory, virtual environment, configuration, log stream and restart policy. The proxy routes requests by hostname or URL path to each private Gunicorn socket or port. Use Werkzeug’s DispatcherMiddleware only when the applications can safely share one Python interpreter and the same dependency environment.

Choose the architecture before deploying

There are three practical ways to host several Flask applications on one machine. The right choice depends on how independently the applications must be deployed, how much dependency isolation they need and whether they can share a process failure domain.

As an Amazon Associate I earn from qualifying purchases.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Separate Gunicorn services behind one reverse proxy

This is the default production design for unrelated applications. Each app has its own virtual environment and Gunicorn process. Gunicorn listens only on localhost or a Unix socket, while nginx or Apache accepts public HTTP and HTTPS traffic.

  • A dependency change in one application does not alter the other application’s environment.
  • Each service can be restarted, rolled back and scaled independently.
  • A crash or memory leak is less likely to take every application down.
  • The reverse proxy can route different hostnames, such as app-one.example and app-two.example, to different backends.

Flask’s production guidance describes Flask as a WSGI application and recommends a dedicated WSGI server or a managed hosting platform. It also warns: “Do not use the development server when deploying to production.”

#1 Best Overall
Sale
TOZO A1 Wireless Earbuds Bluetooth 5.3 Light Weight in Ear Headphones | IPX5 Waterproof,2 Mics for AI Calls,Immersive Premium Sound Bass Headset with Charging Case,32 EQ via App Black
  • [Ultra-Lightweight Ear Buds Designed for Small Ears] Each earbud weighs only 3.7g and features a compact, ergonomic in-ear design made especially for small ears. Secure, low-profile, and comfortable for workouts, all-day wear or overnight sleeping.The ultra-slim profile sits flush in your ear with no hard edges poking or rubbing, so you can even sleep on your side without discomfort.
  • [Immersive Stereo Sound with TOZO OrigX Technology] TOZO OrigX tuning delivers clear vocals, balanced mids, and natural stereo sound for music, podcasts, and videos.
  • [Long Battery Life for Daily Use] Get up to 7 hours of playtime on a single charge, with up to 32 hours total using the charging case—ideal for workdays, commuting, and extended listening sessions.
  • [Bluetooth 5.3 & Stable Connection] Bluetooth 5.3 provides fast pairing, stable wireless performance, and reduced dropouts as you move around home or office.
  • [Deep Bass with Clear Vocals] High-performance drivers produce punchy bass while keeping vocals clean and detailed for everyday listening.

One WSGI process with DispatcherMiddleware

Werkzeug’s DispatcherMiddleware combines multiple WSGI applications and selects one from the request path. This can be convenient when the applications are maintained together and can use the same Python interpreter, dependency versions and configuration conventions.

The trade-off is tight coupling. One process lifecycle, memory space and failure domain cover every mounted application. A dependency upgrade or process restart affects all of them, and the applications cannot be scaled independently.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Apache with mod_wsgi

Apache’s mod_wsgi maps requests to WSGI callables inside Apache-managed processes. By default, each WSGI application receives its own application group and sub-interpreter. Compatible applications can share an application group with WSGIApplicationGroup to reduce duplicate imported-module memory, but compatibility must be tested first.

Daemon mode with separate process groups provides stronger isolation than putting every application into one shared group. This is a valid alternative when Apache is already the operational standard, but it requires careful process, interpreter and virtual-environment configuration.

Design Routing Isolation Deployment and scaling Resource behavior
Separate Gunicorn services nginx or Apache routes hostnames or paths to private sockets or ports Separate dependencies, processes and restart boundaries Deploy, roll back and scale each application independently More duplicate interpreter and import memory, but clearer failure boundaries
DispatcherMiddleware WSGI path-prefix dispatch inside one composed application Shared interpreter, process and failure domain One process definition; all mounted apps restart and scale together Can avoid duplicate imports, but one application’s load affects the shared process
Apache/mod_wsgi Apache virtual-host, URL and WSGI mapping rules Daemon process groups can isolate applications; shared groups reduce isolation Managed through Apache and mod_wsgi process settings Sub-interpreters are separate by default; compatible shared groups can reduce duplicate memory

Organize projects and identities

Give every application a stable directory and an operating-system identity. A simple layout might look like this:

/srv/flask/
  catalog/
    .venv/
    wsgi.py
    requirements.txt
    app/
  reports/
    .venv/
    wsgi.py
    requirements.txt
    app/

Create one virtual environment per project, then install only that application’s pinned dependencies into it. Keep secrets outside source control, preferably in environment files readable only by the service account or in the host’s secret-management system. Do not let one application’s writable upload or cache directory overlap another’s.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Separate Unix users are useful when applications handle untrusted uploads or have different trust levels. At minimum, make the project files readable by the service account and writable only where the application genuinely needs to write.

Rank #2
Sale
Smart Watch for Men Women Compatible with iPhone Samsung Android Phone 1.69 inch Full Touch Screen IP68 Waterproof Bluetooh Fitness Tracker Heart Rate/Sleep Monitor (Black)
  • 【IP68 Waterproof Multifunctinal Smart Watch】Torjalph fitness activity tracker smart watch is IP68 waterproof technology ,you can wear it when swimming,handwashing,it's rain-proof which means that you perform multiple exercise modes outside without worrying about sweat or rain corroding your fitness smart watch,and this watch equipped with a 230 mAh large capacity battery magnetic charging ,and this sports activity tracker watch can be used 5-7 days If fully charged.
  • 【Larger 1.83'' Full Screen Watch & Multi-dial Selection】1.83 inch full HD color touch screen smart watch for men / women provides excellent 240*284 resolution image quality ,This Bluetooth smart watch offers a better touch experience and remarkable immersion and ,more than 200 watch faces for you to choose from App"Da Fit ", you can change the dial style according to your mood to wear keeping the world on your wrist
  • 【Accurate Activity Tracker Smart Watch 】sports watch activity tracker uses sweat and dust resistant breathable silicone strap, our Fitness Tracker Smart Watch for Android iOS Phones supports 12 sports modes,walking,running,bicycle,swimming,badminton,basketball,football,rope skipping. This bluetooth calls smart watch for men women is lightweight and stylish, bringing more convenient and relaxing sports experience while also providing more protection.
  • 【Your 24 Hour Personal Daily Health Monitor】Fitness watch for women men full touch screen IP67 waterproof bluetooth smartwatch for Android iOS Phones with heart rate blood pressure monitor multifunction Andriod smart watch with steps counter sleep monitor sports fitness watch, monitoring blood oxygen saturation allows you to understand your physical condition in real time to track fitness progress ,to know your health status in time.
  • 【More Functions Bluetooth Call Smart Watch】This fitness activity smart watch full screen for iPhone and Android phones includes a bunch of new features including:The bluetooth smart watch can hang up the phone, receive and display WhatsAPP /Text /Facebook /Twitter /Messenger reminder.Support sedentary reminder, alarm clock, stopwatch, timer,weather information,music control, remote camera control compatible with Android 5.0 and above or iOS 9.0 and above smartphones.

Make each Flask application WSGI-ready

Expose a module-level application

Gunicorn needs an importable WSGI callable. A minimal wsgi.py can expose an application object:

from app import create_app

application = create_app()

Alternatively, expose a Flask object directly:

from app import app

The Gunicorn target uses the Python module name followed by the callable name, such as wsgi:application. Gunicorn also supports an application-factory call such as module:create_app().

Keep configuration app-specific

Read each application’s database URL, secret key, allowed hosts, external API credentials and feature flags from its own environment. Do not assume that importing one project will activate the other project’s configuration. Factory-based applications make this separation explicit and are easier to test with different settings.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Handle static files deliberately

Decide whether nginx or the application serves static assets. A reverse proxy is generally better suited to cacheable CSS, JavaScript and images, while Flask handles dynamic requests. Whichever arrangement you choose, test the generated asset URLs under the final hostname or path prefix; a deployment that works at / can break when mounted below a prefix.

Run every application with its own Gunicorn service

Start with private bindings

From the first application’s directory, activate its virtual environment and test the import:

cd /srv/flask/catalog
. .venv/bin/activate
gunicorn --bind 127.0.0.1:8001 wsgi:application

For a second application:

cd /srv/flask/reports
. .venv/bin/activate
gunicorn --bind 127.0.0.1:8002 wsgi:application

Unix sockets are another option:

gunicorn --bind unix:/run/catalog.sock wsgi:application
gunicorn --bind unix:/run/reports.sock wsgi:application

Use private bindings when a reverse proxy is present. The proxy should be the public HTTP/TLS entry point; do not expose the backend Gunicorn listeners directly to the internet.

Use an application factory when appropriate

gunicorn --bind 127.0.0.1:8001 'app:create_app()'

Quote the target when shell characters such as parentheses are present. Confirm that the factory does not perform one-time work, such as starting a scheduler, every time a worker imports it.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #3
New Bee Guitar Cable 10ft Electric Instrument Bass AMP Cord
  • [Low Noise High Fidelity] New bee guitar cord with 22AWG oxygen-free-copper center conductors provides enhanced signal transfer, the PVC insulation material and the high-density stranded copper double shield provide noise rejection for quiet operation
  • [Ideal for Choice] New bee 1/4 straight and right angle metal connectors, ensures a secure connection in any instrument, pedal, or amp jack. L shape great fro on stage guitar stands
  • [Wide Compatible] Suitable for mixer, power amplifier, microphone, effector, decoder, equalizer, electoronic organ, electric guitar, electric bass and other electronic equipments. Widely used in the installation of smart home, karaoke speaker, professional stage audio, etc
  • [Easy Disassemble] Making incidental repairs quick and easy! Very nice, flexible cable
  • [Dont Hesite to Order] 24 hours customer services and professional technology team are standing by

Choose workers from measurements

There is no universal worker count that fits every Flask application. Measure memory use, request latency, concurrency and error rates under a representative workload. Start conservatively, observe the host and increase workers only when the data shows that additional concurrency helps without exhausting memory. Size each service separately; a reporting app and a low-latency API may need different settings.

Define independent service lifecycles

A process supervisor such as systemd can start each Gunicorn service at boot, restart it after failure and keep its environment separate. A service definition should specify the project directory, virtual-environment executable, bind address, application target, user and environment file.

[Unit]
Description=Catalog Flask application
After=network.target

[Service]
User=catalog
Group=catalog
WorkingDirectory=/srv/flask/catalog
EnvironmentFile=/etc/catalog/catalog.env
ExecStart=/srv/flask/catalog/.venv/bin/gunicorn --bind unix:/run/catalog.sock wsgi:application
Restart=on-failure

[Install]
WantedBy=multi-user.target

Create a separate unit for the reports application with its own user, directory, environment file and socket. Then reload units, enable them at boot and inspect their status and logs:

sudo systemctl daemon-reload
sudo systemctl enable --now catalog.service reports.service
sudo systemctl status catalog.service
sudo journalctl -u catalog.service -f

Separate units make an application restart a targeted operation rather than a server-wide event. They also make deployment automation safer: update one virtual environment, restart one unit and verify one health check before touching the next application.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Route hostnames with nginx

With separate subdomains, create one server block per hostname. The following example sends requests to Unix sockets:

server {
    listen 80;
    server_name catalog.example.com;

    location / {
        proxy_pass http://unix:/run/catalog.sock;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

server {
    listen 80;
    server_name reports.example.com;

    location / {
        proxy_pass http://unix:/run/reports.sock;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

The forwarded headers preserve the original host, client address and protocol so Flask extensions can generate correct URLs and enforce secure-cookie behavior. Configure trusted proxy handling in the application according to the number of proxies in front of it; never trust arbitrary client-supplied forwarding headers on a public backend.

After syntax validation, reload nginx without stopping existing connections:

Rank #4
BSIMB 15.6" Digital Family Calendar & Chore Chart, No Subscription Fees
  • Digital Family Calendar: BSIMB digital calendar wall touch screen puts an end to your chaotic life. Designed for busy families, the digital calendar keeps you organised and in step with your family. Assign different colours and tasks to each family member to make family scheduling easier and more intuitive.
  • Easy Setup and Auto-Sync: Plug in, connect to WLAN and auto-syn your electric calendar in minutes. Digital wall calendar compatible with Google calendar, iCloud calendar, Outlook calendar, Cozi calendar and Yahoo calendar. Add events directly on the device or through the ecalendar app. Electronic calendar stays current whether you're at work or traveling—no manual updates needed.
  • All-In-One Home Assistant: Smart calendar builds habits and encourage independence with personalised chores. Display daily meal plan to reduce the daily ‘What's for dinner?’ stress. To-do lists keep track of everything you want. Turning chores into valuable achievements with stars and rewards, making life easier and more enjoyable.
  • Manage Anytime Anywhere: BSIMB electronic calendar for family stay connected with the powerful ecalendar app. Access and manage your digital wall calendar anytime, anywhere with free features like stars & rewards, photo screensaver, chore charts, meals plans, to-do lists etc. Electronic planner paid features like Magic Import tailor advanced tools for users with special needs.
  • Stay in Touch with Loved Ones: Share photos or videos from your phone to electronic wall calendar with app, instantly update your life moment, and keep in touch with your family, especially those who are far away; you can also surprise your smart calendar digital wall by sending him a wish card; it's also great for keeping tech-illiterate elders in touch with the youngsters.
sudo nginx -t
sudo systemctl reload nginx

Terminate TLS at nginx or another controlled edge and forward only the required headers to Gunicorn. Ensure DNS records for every hostname point to the server and that the certificate covers each name.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Route applications below URL prefixes

Path routing is useful when DNS names are limited, but it requires more application awareness. An nginx configuration can send /catalog/ and /reports/ to different backends:

location /catalog/ {
    proxy_pass http://127.0.0.1:8001/;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Prefix /catalog;
    proxy_set_header X-Forwarded-Proto $scheme;
}

location /reports/ {
    proxy_pass http://127.0.0.1:8002/;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Prefix /reports;
    proxy_set_header X-Forwarded-Proto $scheme;
}

Whether the prefix is removed before the request reaches Flask depends on the trailing slash and proxy configuration. Test both routing and generated links. If the application must know its external prefix, configure its URL generation or use the appropriate proxy-fix middleware. Check redirects, form actions, static assets, cookies and WebSocket or streaming endpoints individually.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Use DispatcherMiddleware when shared execution is intentional

DispatcherMiddleware mounts valid WSGI applications under path prefixes:

from werkzeug.middleware.dispatcher import DispatcherMiddleware
from frontend_app import application as frontend
from backend_app import application as backend

application = DispatcherMiddleware(frontend, {
    '/backend': backend,
})

Run the composed callable with one Gunicorn target, for example gunicorn wsgi:application. The dispatcher chooses backend for requests beginning with /backend and sends other paths to frontend.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Use compatible versions of Flask, Werkzeug and every shared dependency.
  • Make sure configuration, extensions and logging do not rely on conflicting global state.
  • Expect one deployment and restart to affect every mounted application.
  • Monitor the combined process rather than assuming each application has an independent resource budget.

This arrangement is operationally simpler than multiple services, but it is not equivalent to independent hosting. Choose it because the applications are intentionally coupled, not merely because mounting them is quick.

Use Apache and mod_wsgi when Apache is the platform

mod_wsgi can run WSGI callables in Apache’s process model. Configure each application with the correct Python environment and WSGI entry point. Daemon mode with separate process groups is the safer default when applications have different dependencies or reliability requirements.

WSGIApplicationGroup controls the interpreter group used by an application. The default arrangement gives each WSGI application its own application group and sub-interpreter. A shared group can reduce duplicate imported-module memory, but only use it after verifying that every extension and dependency works correctly with that interpreter arrangement.

Do not mix Apache and nginx casually. Pick one public reverse proxy, document which component owns TLS and access logs, and ensure only one layer rewrites paths or applies authentication headers.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Secure the multi-application boundary

  • Bind Gunicorn to localhost or a Unix socket, not a public interface, when a reverse proxy fronts it.
  • Use separate service accounts and file permissions where applications have different trust levels.
  • Keep secrets in per-application environment files or a secret manager, with restrictive permissions.
  • Limit upload, cache and temporary directories so one application cannot write into another application’s tree.
  • Validate the original host and forwarded protocol before using them for redirects, absolute URLs or security decisions.
  • Apply request-size, timeout and rate limits at the proxy where appropriate, then set application-level timeouts for expensive work.
  • Keep access logs and application logs identifiable by service name so failures can be traced to the correct app.

Test routing and independent failure recovery

  1. From the server, call each private backend directly with a health endpoint and confirm the expected status and response body.
  2. Call every public hostname and path through nginx or Apache, checking redirects, cookies, static assets and error pages.
  3. Verify that Flask sees the intended host and HTTPS scheme when requests arrive through the proxy.
  4. Stop one Gunicorn service and confirm that the other application remains available.
  5. Restart one service and confirm that its logs, socket ownership and health check recover without changing the other service.
  6. Perform a deployment rollback for one application and verify that its virtual environment and configuration return to the previous known-good version.
  7. Load-test applications separately enough to observe memory and latency before selecting worker counts.

Troubleshoot common failures

502 Bad Gateway

Check that the Gunicorn service is running, that the socket or port matches the proxy configuration and that the proxy user can access the socket. Read the Gunicorn and proxy error logs together; a stale socket after a failed restart is a common clue.

404 responses under a prefix

Determine whether the proxy removed the prefix before forwarding. Confirm the Flask routes, trailing slashes and any configured script name or prefix middleware. Test a direct backend request and a public prefixed request separately.

Redirects point to the wrong scheme or hostname

Pass the original Host and X-Forwarded-Proto headers, then configure Flask’s trusted-proxy handling correctly. Do not blindly trust forwarding headers when clients can reach the backend directly.

Static files or cookies fail only in production

Inspect the browser’s requested URL and response headers. Prefix routing, secure-cookie settings, incorrect host handling and proxy path rewriting can all produce an application that renders HTML while its assets or sessions fail.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

One app starves the others

Inspect per-service memory, CPU, request latency and worker behavior. Reduce concurrency for the heavy service, move expensive work out of request handlers or split the workload onto another host when the machine cannot provide a safe margin. Shared DispatcherMiddleware processes require particular caution because all mounted applications compete inside the same process model.

When managed hosting is a better fit

Flask’s deployment documentation lists PythonAnywhere, Google App Engine, Google Cloud Run, AWS Elastic Beanstalk and Microsoft Azure as common hosting platforms. These services can remove server patching, proxy configuration and some process-management work. Evaluate their current pricing, regional availability, networking model, logging, deployment workflow and limits for your applications before choosing one. The same architectural decision still applies: deploy applications as independently managed services when they need separate lifecycles, or deliberately compose them when shared execution is acceptable.

Recommended default

For most teams, create one virtual environment and one Gunicorn service per Flask application, bind each privately, and route traffic through a single nginx or Apache reverse proxy. Use hostname routing when applications should behave as independent sites; use path routing only after testing prefix-aware URLs, redirects and static files. Reserve DispatcherMiddleware for applications that are intentionally coupled, and use mod_wsgi when Apache process management is already a deliberate platform choice.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.