DEV Community

Wu Xie
Wu Xie

Posted on

Building a High-Performance SMS Gateway with Python: A Complete Guide

In this comprehensive guide, I'll walk you through building a production-ready SMS gateway using Python and FastAPI. We'll cover everything from basic setup to advanced features like rate limiting, multi-provider support, and delivery tracking.

Why Build Your Own SMS Gateway?

While services like Twilio and Telnyx offer excellent APIs, building your own gateway gives you:

  • Cost control: Route messages through the cheapest provider
  • Redundancy: Automatic failover between providers
  • Customization: Tailor features to your exact needs
  • Analytics: Deep insights into your messaging patterns

Project Architecture

sms-gateway/
├── app/
│   ├── main.py           # FastAPI application
│   ├── providers/        # SMS provider adapters
│   │   ├── twilio.py
│   │   ├── telnyx.py
│   │   └── vonage.py
│   ├── services/
│   │   ├── router.py     # Message routing logic
│   │   └── rate_limiter.py
│   └── models/
│       └── message.py
├── tests/
└── requirements.txt
Enter fullscreen mode Exit fullscreen mode

Getting Started

First, install the required dependencies:

pip install fastapi uvicorn httpx redis
Enter fullscreen mode Exit fullscreen mode

Core Implementation

Here's the main FastAPI application:

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Optional

app = FastAPI(title="SMS Gateway")

class SMSRequest(BaseModel):
    to: str
    message: str
    provider: Optional[str] = None

@app.post("/api/v1/send")
async def send_sms(request: SMSRequest):
    # Validate phone number
    if not validate_phone(request.to):
        raise HTTPException(400, "Invalid phone number")

    # Route to appropriate provider
    provider = select_provider(request.provider)

    # Send message
    result = await provider.send(request.to, request.message)

    return {"status": "sent", "message_id": result.id}
Enter fullscreen mode Exit fullscreen mode

Rate Limiting with Redis

To prevent abuse and respect provider limits:

import redis
from functools import wraps

class RateLimiter:
    def __init__(self, redis_url: str):
        self.redis = redis.from_url(redis_url)

    def check_limit(self, key: str, limit: int, window: int) -> bool:
        current = self.redis.incr(key)
        if current == 1:
            self.redis.expire(key, window)
        return current <= limit
Enter fullscreen mode Exit fullscreen mode

Multi-Provider Support

The key to a robust gateway is supporting multiple providers:

class ProviderRouter:
    def __init__(self):
        self.providers = {
            'twilio': TwilioProvider(),
            'telnyx': TelnyxProvider(),
            'vonage': VonageProvider()
        }

    async def send(self, to: str, message: str) -> dict:
        # Try providers in order of priority
        for name, provider in self.providers.items():
            try:
                return await provider.send(to, message)
            except ProviderError:
                continue
        raise AllProvidersFailedError()
Enter fullscreen mode Exit fullscreen mode

Conclusion

Building your own SMS gateway gives you complete control over your messaging infrastructure. The code shown here is a starting point - you can extend it with features like:

  • Webhook callbacks for delivery status
  • Message queuing with Celery
  • Geographic routing
  • A/B testing for message content

Check out my full implementation on GitHub: cloud-sms-gateway


Found this helpful? Follow me for more Python and API development content!

Top comments (0)