Skip to main content
Back to Projects
ProductDjangoPostgreSQLReactCeleryRedisGoogle Ads API

Rankioz: Designing a Multi-Tenant SEO Platform

Technical Founder & Backend Engineer
11 min read
rankioz.com (opens in new tab)

Rankioz is a multi-tenant SaaS platform that combines AI-powered content generation with end-to-end search engine optimization. I designed and built the entire system: backend architecture, infrastructure, data model, async pipelines, billing, and integrations, taking it from an empty repository to a production deployment serving real users.

19Django Apps
15+API Integrations
30+Database Models
SoloEngineer

Context

The SEO tools market is fragmented. Content teams typically juggle separate tools for keyword research, content writing, rank tracking, competitor analysis, and publishing. Each tool has its own data silo, its own subscription, and its own learning curve. The idea behind Rankioz was to collapse that stack into a single platform, and layer AI on top to automate the most time-consuming parts.

The core product hypothesis: if you crawl a website, extract its brand voice, build a knowledge base from its existing content, and combine that with real-time keyword intelligence, you can generate SEO-optimized articles that actually sound like the brand wrote them.

That required a system that could crawl websites at scale, train brand voice models per domain, run retrieval-augmented generation against a vector knowledge base, orchestrate publishing to external CMS platforms, and track the search performance of everything it produces, all within a multi-tenant architecture where each workspace has its own billing, team, and data boundaries.


My Role

Technical Founder & Backend Engineer

I owned all technical decisions end-to-end:

  • System architecture and data model design
  • Backend implementation (Django REST Framework, PostgreSQL, Celery, Redis)
  • Infrastructure setup and deployment (Railway)
  • External API integration design (Google Ads, Search Console, MOZ, OpenAI, Paddle, and 10+ others)
  • Security model, authentication, and authorization
  • Background processing architecture and task queue design
  • Billing system and subscription lifecycle management

Architecture

System Overview

The platform runs as a Django REST API backed by PostgreSQL, with Celery workers processing heavy workloads asynchronously. The frontend is a separate Next.js application that communicates over HTTPS with token-based authentication.

Multi-Tenant Data Model

Every resource in Rankioz is scoped to a Workspace (the tenant boundary). Each workspace contains websites, team members, a billing subscription, and a credit balance. Users can belong to multiple workspaces with different roles (Owner, Admin, Editor, Viewer), and switch between them within the same session.

The data model follows a strict hierarchy:

Workspace
├── Subscription (1:1)
├── Credit Balance
├── Team Members (with roles)
└── Websites
    ├── Crawled Pages
    ├── Brand Voice Model
    ├── Knowledge Base (embeddings)
    ├── Keyword Universe
    ├── Articles
    ├── Meta Tag Audits
    ├── Rank Tracking Data
    └── CMS Integrations
TEXT

One non-trivial decision was the shared index system. When the same domain appears across multiple workspaces, the system avoids redundant crawling and AI processing by linking dependent websites to a source website via a source_website foreign key. Crawled pages, brand profiles, and embeddings are shared. Articles, rank snapshots, and billing remain independent per workspace.

Backend Structure

The backend is organized into 19 Django apps. The most important ones:

AppResponsibility
coreWorkspace, Website, Membership
billingPaddle subscriptions, credit system
crawlerWebsite crawling and content extraction
aiBrand profiles, embeddings, RAG pipeline
seo_agentAutopilot article generation and publishing
rank_trackingKeyword tracking and GSC integration
page_optimizerAI page optimization with WordPress sync
google_adsKeyword research via Google Ads API

Plus 11 supporting apps covering content management, competitor analysis, backlink opportunities, meta tag auditing, affiliates, and scraping utilities.

Business logic lives in dedicated services.py files within each app, keeping views thin and testable. This service-layer pattern was a deliberate choice to avoid the Django anti-pattern of fat views or fat models.


Key Technical Decisions

1. The Content Generation Pipeline

The most architecturally complex part of the system is the content generation pipeline. It chains multiple async tasks together, each depending on the output of the previous step:

Each step runs as a Celery task. The crawl task chains into brand profile generation, which chains into embedding generation, which chains into meta tag auditing. A single website addition triggers a multi-step async pipeline that can take minutes to complete, with real-time progress updates pushed to the frontend via polling.

The critical design choice was when to deduct credits. Credits are consumed at article generation time, not at publish time. This simplifies the billing model (generation is the expensive operation) but means failed generations still consume a credit, a known trade-off documented for future improvement.

Rankioz SEO Agent dashboard showing the auto-publish schedule configuration with website selection, automation mode, WordPress integration, and multi-step wizard

2. RAG-Based Content Generation

Articles are not generated from a generic prompt. The system uses Retrieval-Augmented Generation (RAG) to ground every article in the website's actual content:

  1. During crawling, pages are chunked into segments of up to 1,500 characters each.
  2. Each chunk receives a vector embedding via OpenAI's text-embedding-3-small model.
  3. When generating an article, the system performs a similarity search against these embeddings to retrieve the most relevant content chunks.
  4. Those chunks, combined with the brand voice profile and real-time keyword data, form the context window for GPT-4.1.

This produces articles that reflect the brand's existing terminology, style, and subject matter expertise, rather than generic AI output.

3. Background Processing Architecture

Not all async work is equal. A crawling job that processes 500 pages has very different resource and latency characteristics than an AI call that generates a meta description. To handle this, I designed a multi-queue Celery architecture:

QueuePurposeCharacteristics
crawlerScrapy + Playwright crawling, brand profile generation, embeddingsHeavy, long-running
ai_shortArticle generation, keyword enrichment, image generationLatency-sensitive
emailTransactional emails, trial lifecycle, rank reportsFire-and-forget
celeryDefault queue for general and scheduled tasksMixed

Celery Beat handles periodic scheduling: nightly keyword tracking (8:00 AM UTC), rank change email reports (8:10 AM UTC), scheduled article publishing (every 5 minutes), trial email lifecycle (9:00 AM UTC), and WebPageTest result polling (every 2 minutes).

For tasks that must not run concurrently, like WebPageTest processing where duplicate requests waste API budget, I implemented distributed locking via Redis SET NX EX with automatic TTL expiry.

4. Multi-Integration Orchestration

The platform integrates with 15+ external APIs. Each integration has its own authentication model, rate limits, error characteristics, and data format.

IntegrationAuth ModelPurpose
Google Ads APIOAuth 2.0 + Developer TokenKeyword research data
Google Search ConsoleOAuth 2.0Rank tracking and analytics
OpenAI APIAPI KeyContent generation, embeddings, meta suggestions
Google GeminiAPI KeyFeatured image generation
Paddle BillingAPI Key + WebhooksSubscriptions and payments
MOZ APIAPI KeyDomain authority metrics
Firecrawl APIAPI KeyWebsite crawling
SerpAPIAPI KeySERP results for competitor analysis
DataForSEO APIBasic AuthBacklink gap analysis
WebPageTest APIAPI KeyCore Web Vitals and performance
WordPress REST APIApplication PasswordContent publishing and sync
Webflow APIBearer TokenContent publishing
PostmarkServer TokenTransactional email

Each integration is encapsulated in its own service layer with caching, retry logic, and error categorization. For example, the Google Ads keyword research service checks a local cache before making API calls and batches uncached keywords to minimize request count. DataForSEO has explicit daily budget controls and request-per-minute rate limiting.

5. Billing and Subscription Lifecycle

Billing is handled through Paddle as the merchant of record, with a credit-based consumption model layered on top:

  • Each plan allocates a monthly credit quota (reset on billing cycle renewal).
  • Generating an article costs 1 credit.
  • Users can purchase additional credit packs (10, 25, or 100) as one-time transactions.
  • Every credit change is recorded in a CreditLedgerEntry audit table with a reason code.

The subscription lifecycle is driven by Paddle webhooks: subscription.created, subscription.updated, subscription.canceled, subscription.past_due, and transaction.completed. Each webhook updates both the Subscription model and the denormalized Workspace.billing_plan field. Plan upgrades take effect immediately with prorated charges; downgrades are scheduled for the end of the billing period.

The trial system gives new users 3 days and 3 article credits with a 500-page crawl limit. Automated lifecycle emails (Welcome, Progress, Trial Ending Soon) are triggered via Celery Beat and tracked in a TrialEmailLog to ensure idempotent delivery.

6. Security Model

Security decisions across the platform:

  • Authentication: Token-based for the API, Google OAuth via allauth for social login, and a separate impersonation token system for admin debugging.
  • Encryption at rest: Sensitive API tokens (Webflow, WordPress credentials) are encrypted using Fernet symmetric encryption derived from Django's SECRET_KEY.
  • Custom security middleware: Blocks known malicious request patterns, including PHP file requests, WordPress admin paths, and config file probes, before they reach the application layer.
  • RBAC: Four-role permission model (Owner, Admin, Editor, Viewer) enforced at the API level through custom permission classes.
  • Subscription gating: Custom permission classes gate feature access based on billing status.

Infrastructure and Deployment

The platform runs on Railway with three process types:

  • Web: Gunicorn serving the Django API
  • Worker: Celery worker consuming all four queues
  • Beat: Celery Beat scheduler for periodic tasks

PostgreSQL 15 handles all relational data. Redis serves as both the Celery message broker and the distributed lock store. Static files are served via WhiteNoise with compressed manifests.


Reflections

Building Rankioz reinforced a few principles I carry into every system I design:

Start with the data model. The multi-tenant workspace → website → resource hierarchy was the single most important design decision. Getting that right early meant every feature built on top of it, including billing, team management, content generation, and rank tracking, had a clear scoping model from day one.

Separate queues for separate workloads. Mixing crawling tasks (minutes-long, CPU-heavy) with AI generation tasks (seconds-long, latency-sensitive) on the same queue creates unpredictable latency. Dedicated queues with different worker configurations solved this cleanly.

Treat external APIs as unreliable by default. With 15+ integrations, something is always degraded. Every integration service has its own caching layer, retry policy, and error categorization. The system should never crash because an external API returns an unexpected response.

Credit systems need an audit trail. A simple counter (credits_remaining -= 1) is not enough. The CreditLedgerEntry table records every credit change with a reason, timestamp, and reference. When a billing dispute arises, and they do, you need to reconstruct exactly what happened.

Shared indexes are worth the complexity. The source_website pattern saves significant compute (no duplicate crawling, no duplicate embedding generation) at the cost of more complex query logic. For a multi-tenant platform where the same domain can appear in many workspaces, the savings compound quickly.


Rankioz is live at rankioz.com (opens in new tab). Try the app at app.rankioz.com (opens in new tab). The platform continues to evolve with features like internal linking automation, content decay detection, and SERP volatility alerts on the roadmap.