Rajandran R Creator of OpenAlgo - OpenSource Algo Trading framework for Indian Traders. Building GenAI Applications. Telecom Engineer turned Full-time Derivative Trader. Mostly Trading Nifty, Banknifty, High Liquid Stock Derivatives. Trading the Markets Since 2006 onwards. Using Market Profile and Orderflow for more than a decade. Designed and published 100+ open source trading systems on various trading tools. Strongly believe that market understanding and robust trading frameworks are the key to the trading success. Building Algo Platforms, Writing about Markets, Trading System Design, Market Sentiment, Trading Softwares & Trading Nuances since 2007 onwards. Author of Marketcalls.in

Flask vs FastAPI: Sync and Async Comparison in Fintech Applications – Python Tutorial

5 min read

When it comes to developing modern web applications, choosing the right framework is crucial. For developers building fintech applications, performance, scalability, and reliability are top priorities. Two popular Python frameworks—Flask and FastAPI—are often compared for their capabilities.

Generated Image

Digital

In this blog, we will explore:

• The fundamental differences between Flask and FastAPI.

• Understand synchronous (sync) and asynchronous (async) processing.

• Practical examples showcasing their performance differences with yfinance data fetching.

• Why async programming is essential in fintech applications.

Why Flask and FastAPI Matter in Fintech

Flask

• Flask is a lightweight, synchronous web framework widely adopted for its simplicity and flexibility.

• It is often chosen for rapid development and when compatibility with legacy systems is a priority.

Synchronous by nature: Flask processes one request at a time per worker. This simplicity makes it great for CPU-bound tasks but limits its scalability for I/O-bound operations.

FastAPI

• FastAPI is a modern, asynchronous web framework built on ASGI and designed for speed.

• It supports both sync and async processing, making it ideal for high-performance, I/O-heavy applications.

Built-in async support: FastAPI can handle thousands of concurrent requests, making it a natural choice for scalable fintech solutions like real-time trading platforms.

Why Async Programming Is Important in Fintech

Fintech Challenges:

Real-time Data Fetching: Fetching live financial data, such as stock prices, exchange rates, and historical data, requires high-speed operations.

Concurrency: Applications often need to serve thousands of users simultaneously without bottlenecks.

I/O-bound Operations: Communicating with external APIs (e.g., Yahoo Finance, Bloomberg) is I/O-heavy, which can block synchronous frameworks like Flask.

Async Programming Benefits:

• Handles multiple I/O-bound tasks concurrently.

• Reduces response time by leveraging non-blocking operations.

• Improves scalability for high-demand scenarios, such as peak trading hours.

How Sync and Async Work

Synchronous Processing

• In a synchronous framework like Flask, each request is handled sequentially.

• If one request involves waiting (e.g., for an external API to respond), the entire worker is blocked, delaying other requests.

Asynchronous Processing

• In an async framework like FastAPI, requests are handled concurrently using event loops.

• Tasks that involve waiting (e.g., I/O operations) do not block other requests, enabling efficient resource usage and faster response times.

Flask Example: Sync Processing

Here’s how Flask handles synchronous requests to fetch financial data using yfinance:

Code:

from flask import Flask, jsonify
import yfinance as yf
import numpy as np
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

# Increase the connection pool size for `requests`
session = requests.Session()
adapter = HTTPAdapter(pool_connections=50, pool_maxsize=50, max_retries=Retry(total=3, backoff_factor=1))
session.mount("http://", adapter)
session.mount("https://", adapter)

# Patch the `requests` session in `yfinance`
yf.utils.requests = session

# Flask app
app = Flask(__name__)

# Hardcoded symbols
SYMBOLS = ["AAPL", "MSFT", "GOOGL", "AMZN", "TSLA", 
           "META", "NFLX", "ADBE", "NVDA", "ORCL", 
           "IBM", "INTC", "AMD", "CRM", "CSCO", 
           "DIS", "TMUS", "V", "MA", "PYPL"]

def fetch_symbol_sync(symbol):
    """Fetch data synchronously for a single symbol."""
    raw_data = yf.Ticker(symbol).history(period="1d")
    data = raw_data.reset_index().to_dict(orient="records")
    for record in data:
        for key, value in record.items():
            if isinstance(value, (np.int64, np.float64)):
                record[key] = value.item()  # Convert numpy types to native Python types
    return {symbol: data}

@app.route("/sync", methods=["GET"])
def get_yfinance_sync():
    """Fetch data for all symbols synchronously."""
    from time import time  # Import inside the route for clarity
    start_time = time()
    data = [fetch_symbol_sync(symbol) for symbol in SYMBOLS]
    end_time = time()

    total_time = end_time - start_time
    print(f"Processed {len(SYMBOLS)} symbols in {total_time:.2f} seconds")
    return jsonify({
        "symbols": SYMBOLS,
        "data": data,
        "total_response_time": f"{total_time:.2f} seconds"
    })

if __name__ == "__main__":
    app.run(host="127.0.0.1", port=5000)

Terminal Output

(venv) openalgo@openalgo testapi % python flask_app.py 
 * Serving Flask app 'flask_app'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:5000
Press CTRL+C to quit
Processed 20 symbols in 5.60 seconds
127.0.0.1 - - [18/Nov/2024 10:59:17] "GET /sync HTTP/1.1" 200 -
Processed 20 symbols in 4.51 seconds
127.0.0.1 - - [18/Nov/2024 10:59:55] "GET /sync HTTP/1.1" 200 -
Processed 20 symbols in 4.61 seconds
127.0.0.1 - - [18/Nov/2024 11:00:09] "GET /sync HTTP/1.1" 200 -

How It Works:

• The /sync endpoint fetches data for each symbol sequentially.

• The server blocks until each request is completed, making it less efficient for large-scale I/O operations.

Performance:

Single request: Takes around 4-6 seconds to process 20 symbols.

Multiple concurrent requests: Performance degrades significantly due to blocking behavior.

FastAPI Example: Async Processing

Here’s the async implementation using FastAPI:

Code:

from fastapi import FastAPI
import yfinance as yf
import asyncio
import numpy as np
import time
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

# Increase the connection pool size
session = requests.Session()
adapter = HTTPAdapter(pool_connections=50, pool_maxsize=50, max_retries=Retry(total=3, backoff_factor=1))
session.mount("http://", adapter)
session.mount("https://", adapter)

# Patch the `requests` session in `yfinance`
yf.utils.requests = session

app = FastAPI()

# Hardcoded symbols
SYMBOLS = ["AAPL", "MSFT", "GOOGL", "AMZN", "TSLA", 
           "META", "NFLX", "ADBE", "NVDA", "ORCL", 
           "IBM", "INTC", "AMD", "CRM", "CSCO", 
           "DIS", "TMUS", "V", "MA", "PYPL"]

async def fetch_symbol(symbol):
    loop = asyncio.get_event_loop()
    raw_data = await loop.run_in_executor(None, yf.Ticker(symbol).history, "1d")
    data = raw_data.reset_index().to_dict(orient="records")
    for record in data:
        for key, value in record.items():
            if isinstance(value, (np.int64, np.float64)):
                record[key] = value.item()
    return {symbol: data}

@app.get("/async")
async def get_yfinance_async():
    start_time = time.time()
    tasks = [fetch_symbol(symbol) for symbol in SYMBOLS]
    data = await asyncio.gather(*tasks)
    end_time = time.time()

    total_time = end_time - start_time
    print(f"Processed {len(SYMBOLS)} symbols in {total_time:.2f} seconds")
    return {
        "symbols": SYMBOLS,
        "data": data,
        "total_response_time": f"{total_time:.2f} seconds"
    }

Terminal Output

(venv) openalgo@openalgo testapi % uvicorn fastapi_app:app --host 127.0.0.1 --port 8000
INFO:     Started server process [64513]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
Processed 20 symbols in 1.44 seconds
INFO:     127.0.0.1:62105 - "GET /async HTTP/1.1" 200 OK
Processed 20 symbols in 0.62 seconds
INFO:     127.0.0.1:62121 - "GET /async HTTP/1.1" 200 OK
Processed 20 symbols in 0.59 seconds
INFO:     127.0.0.1:62125 - "GET /async HTTP/1.1" 200 OK
Processed 20 symbols in 0.58 seconds
INFO:     127.0.0.1:62125 - "GET /async HTTP/1.1" 200 OK

How It Works:

• The /async endpoint uses asyncio.gather() to fetch data concurrently for all symbols.

• Non-blocking operations allow other requests to be processed simultaneously.

Performance:

Single request: Processes 20 symbols in ~0.5-1.5 seconds.

Multiple concurrent requests: Handles requests efficiently with minimal degradation.

Performance Comparison

Framework Request Type 20 Symbols Concurrent Requests

Flask Sync ~4-6 seconds Degrades significantly

FastAPI Async ~0.5-1.5 seconds Efficient with low latency

When to Use Sync vs Async in Fintech Applications

Sync (Flask)

• Suitable for simpler applications or when integrating with legacy systems.

• Works well for CPU-bound tasks like data transformations or calculations.

Async (FastAPI)

• Essential for I/O-heavy operations like fetching financial data, real-time trading, or communicating with external APIs.

• Ideal for scalable, high-concurrency fintech platforms.

Conclusion

In the fintech world, where speed and scalability are paramount, FastAPI with async processing is a game-changer. It allows developers to build high-performance applications that can handle large-scale, concurrent operations efficiently. While Flask remains a reliable framework for simpler use cases, adopting FastAPI for I/O-intensive tasks like fetching financial data is crucial for modern fintech solutions.

Final Thoughts

Choosing the right framework depends on your application’s requirements. For fintech applications dealing with real-time data and high concurrency, FastAPI is the clear winner. However, understanding both sync and async paradigms will make you a better developer equipped to tackle any challenge.

Rajandran R Creator of OpenAlgo - OpenSource Algo Trading framework for Indian Traders. Building GenAI Applications. Telecom Engineer turned Full-time Derivative Trader. Mostly Trading Nifty, Banknifty, High Liquid Stock Derivatives. Trading the Markets Since 2006 onwards. Using Market Profile and Orderflow for more than a decade. Designed and published 100+ open source trading systems on various trading tools. Strongly believe that market understanding and robust trading frameworks are the key to the trading success. Building Algo Platforms, Writing about Markets, Trading System Design, Market Sentiment, Trading Softwares & Trading Nuances since 2007 onwards. Author of Marketcalls.in

How to Speed Up a 1 Billion Iterations Loop…

Python is a versatile and user-friendly programming language, but it’s often criticized for being slow compared to compiled languages like C or C++. A...
Rajandran R
9 min read

Mastering Pydantic for Traders: A Step-by-Step Guide

Trading in India, whether in stocks, commodities, or cryptocurrencies, revolves around data. From NSE tickers to API responses from brokers handling structured and...
Rajandran R
3 min read

SketchMaker AI: Create Stunning AI Visuals and Your Own…

SketchMaker AI is an open-source tool that transforms text into art, allowing you to create stunning AI images, blog banners, Instagram and YouTube thumbnails...
Rajandran R
3 min read

Leave a Reply

Get Notifications, Alerts on Market Updates, Trading Tools, Automation & More