Building REST APIs with Python Flask: From a 2 AM ‘Firefighting’ Shift to Real-World Solutions

Python tutorial - IT technology blog
Python tutorial - IT technology blog

A Real-World Story: When a Python Script Suddenly Goes Silent

It was 2 AM when my phone started vibrating relentlessly. My Telegram bot was flooding with 502 Bad Gateway errors from a partner’s Webhook system. With traffic hitting around 500 requests per minute, the company’s old processing script had collapsed. After 15 minutes of checking logs, I realized the issue: the legacy code was just ‘read file and exit’—it lacked the ability to listen for continuous incoming HTTP requests.

At that moment, I needed an ultra-fast solution to build a ‘gateway’ for receiving JSON data. Rewriting it in Django felt too bloated for such a small task. Using raw sockets would have taken all day just to handle complex HTTP headers. Flask appeared as a timely lifesaver.

Why Can’t a Normal Script Act as a Server?

When starting out, we often write scripts that run from top to bottom and then terminate. But to communicate with a Mobile App or Frontend, your code must act as a Server.

It must always be in a ‘listening’ state, waiting for connections. If you only use basic Python code, you’ll hit a ConnectionRefusedError immediately. Simply put, no port is open to receive data. A proper framework should help you:

  • Open a connection port (like port 5000 or 8080).
  • Parse complex HTTP requests into readable data.
  • Return standard JSON format so other systems can understand it.

Three Popular Choices for Python Backend Developers

That night, I quickly considered three options:

  1. The built-in http.server module: Very fast, no installation needed. However, it is extremely primitive. Parsing data from a POST request with this module is a nightmare.
  2. FastAPI: Modern, with powerful async support. Unfortunately, the company’s old server was still running Python 3.6, while FastAPI requires a higher version for optimization.
  3. Flask: This was the ‘soulmate’ at the time. Flask is a lightweight and flexible micro-framework. The documentation on Stack Overflow is massive, which helped me fix bugs even in a half-asleep state.

Deploying a REST API with Flask in 10 Minutes

Here is how I rebuilt the data gateway. You can apply this immediately to your project.

1. Setting Up a ‘Clean’ Environment

Never install libraries directly into your system Python. I always use a virtual environment (virtualenv) to avoid version conflicts—a common mistake that can crash a system during deployment.

# Create and activate a virtual environment
python -m venv venv
source venv/bin/activate # On Linux/macOS
# venv\Scripts\activate # On Windows

# Install Flask
pip install flask

2. The First API: Listening for Connections

Create an app.py file with the following minimalist structure:

from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/', methods=['GET'])
def home():
    return jsonify({"status": "online", "message": "Server is ready!"})

if __name__ == '__main__':
    app.run(debug=True, port=5000)

Run the command python app.py and visit http://localhost:5000. You will see the returned JSON string immediately.

3. Handling Real-World Data (POST Requests)

Data from partners is usually pushed via the POST method. Here is how I handle it for reception and temporary storage:

from flask import Flask, request, jsonify

app = Flask(__name__)
data_store = []

@app.route('/api/webhook', methods=['POST'])
def handle_webhook():
    # Get JSON data from the incoming request
    incoming_data = request.get_json()
    
    if not incoming_data:
        return jsonify({"error": "Data is empty!"}), 400
    
    # Log data for debugging
    print(f"Received: {incoming_data}")
    data_store.append(incoming_data)
    
    return jsonify({"status": "success", "items_count": len(data_store)}), 201

if __name__ == '__main__':
    # Use host='0.0.0.0' so other machines can access it
    app.run(host='0.0.0.0', port=5000)

Pro-tip: When the code file starts to ‘bloat’

My project initially had only 200 lines of code in a single app.py file. After a few months, requirements for authorization and logging pushed it to 2,000 lines.

At this stage, hunting for bugs in a single file is a disaster. You should split routes using Blueprints as soon as you see signs of growth. Don’t wait until the code is a tangled mess to start refactoring.

4. Fast API Testing via Terminal

Instead of opening the heavy Postman app, I often use curl to test quickly right in the terminal:

curl -X POST http://localhost:5000/api/webhook \
     -H "Content-Type: application/json" \
     -d '{"id": 101, "event": "payment_success"}'

Critical Pitfalls to Avoid When Taking an API to Production

To keep your API running reliably and avoid being called by your boss in the middle of the night, remember these three golden rules:

  • Never use app.run() for production: Flask’s default server is only for development. It cannot handle heavy loads. Use Gunicorn or uWSGI to run the application in a real-world environment.
  • Don’t trust user data: Always use libraries like pydantic to validate JSON formats. A missing field can crash your entire downstream logic.
  • Tighten error handling: Always wrap code in try...except blocks. Never let an API return a blank error page along with Python source code (traceback). That is bait for hackers.

Building a REST API with Flask isn’t hard, but making it ‘survive’ during peak traffic requires attention to detail. From a quick script written for a 2 AM emergency, I turned it into a stable system by structuring it correctly from the start.

Share: