You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
RFC: Database Index Schema Optimizations & Standardized Asynchronous Task Scheduling
Status: Draft
Author: Antigravity (AI Contributor) Target Repository:AOSSIE-Org/Devr.AI Date: June 26, 2026
1. Executive Summary
As an AI-powered Developer Relations Assistant, Devr.AI is built to process high-throughput event streams from platforms like Discord, Slack, and GitHub in real-time. To maintain high responsiveness, sub-second latency, and horizontal scalability under high workloads, the backend infrastructure must be optimized both at the data persistence layer and the asynchronous task scheduling layer.
This RFC proposes two major system enhancements:
Database Index Schema Optimizations: Proactive B-Tree, GIN, and Partial indexes for PostgreSQL (Supabase) targeting high-read, high-write tables like interactions and repositories to eliminate Sequential Scans (Seq Scan).
Standardized Asynchronous Task Scheduling: Migrating ad-hoc cron scripts to a unified, database-backed, clustered task scheduling framework utilizing APScheduler with a PostgreSQL Job Store integrated into our existing FastAPI/Lifespan event loop.
2. Part 1: Database Index Schema Optimizations
2.1 The Problem
An audit of the current database schema file (create_db.sql) reveals several index gaps:
The interactions Table: This is the most active table in the system, storing every message, comment, and PR event. However, no indexes are defined on user_id, repository_id, platform, created_at, or topics_discussed. Any query listing user interactions, filtering by platform, searching topics, or sorting by time forces a costly Seq Scan (O(N) search complexity).
The repositories Table: Frequently searched by full_name (owner/repo) or owner/name to look up indexing state or retrieve metadata. Lack of index coverage on these columns degrades performance of LLM tool retrievals.
The organization_integrations Table: Frequently queried by the Discord/Slack bots to verify which active organizations to serve. While it has single-column indexes, it lacks optimal composite index coverage for active platforms.
2.2 Proposed SQL Indexing Schema
We propose executing a database migration containing the following index declarations:
-- ====================================================================-- DATABASE INDEX OPTIMIZATIONS FOR DEVR.AI-- ====================================================================-- ---------------------------------------------------------------------- 1. Optimizations for 'interactions' table (High-Write/High-Read)-- ---------------------------------------------------------------------- Optimize foreign key joins and user history queriesCREATEINDEXIF NOT EXISTS idx_interactions_user_id
ON interactions(user_id);
CREATEINDEXIF NOT EXISTS idx_interactions_repository_id
ON interactions(repository_id)
WHERE repository_id IS NOT NULL;
-- Optimize temporal/activity-stream sorting (recent activities first)CREATEINDEXIF NOT EXISTS idx_interactions_created_at_desc
ON interactions(created_at DESC);
-- Optimize lookup queries combining platform and platform-specific IDs (e.g. webhook deduplication)CREATEINDEXIF NOT EXISTS idx_interactions_platform_lookup
ON interactions(platform, platform_specific_id);
-- Optimize thread and channel context retrieval (conversational memory queries)CREATEINDEXIF NOT EXISTS idx_interactions_channel_thread
ON interactions(channel_id, thread_id)
WHERE channel_id IS NOT NULL;
-- Optimize classification and intent analyticsCREATEINDEXIF NOT EXISTS idx_interactions_classification
ON interactions(interaction_type, intent_classification)
WHERE interaction_type IS NOT NULLOR intent_classification IS NOT NULL;
-- Optimize search across topics_discussed array using GIN index (Generalized Inverted Index)CREATEINDEXIF NOT EXISTS idx_interactions_topics_discussed_gin
ON interactions USING GIN (topics_discussed);
-- ---------------------------------------------------------------------- 2. Optimizations for 'repositories' table (Metadata Lookups)-- ---------------------------------------------------------------------- Optimize fast case-insensitive full-name lookups from tools and agentsCREATEINDEXIF NOT EXISTS idx_repositories_full_name_lower
ON repositories(LOWER(full_name));
-- Optimize composite lookups by owner/name separatelyCREATEINDEXIF NOT EXISTS idx_repositories_owner_name
ON repositories(owner, name);
-- Optimize partial index for indexing queues (fetching pending/failed repos)CREATEINDEXIF NOT EXISTS idx_repositories_indexing_state
ON repositories(is_indexed, indexing_status)
WHERE is_indexed = false;
-- ---------------------------------------------------------------------- 3. Optimizations for 'organization_integrations' table-- ---------------------------------------------------------------------- Optimize high-frequency active platform status checks by integrationsCREATEINDEXIF NOT EXISTS idx_org_integrations_platform_active
ON organization_integrations(platform, is_active)
WHERE is_active = true;
2.3 Query Performance Breakdown (Before & After)
Query 1: Fetching the latest 20 interactions for a user within a specific repository
SELECT*FROM interactions
WHERE user_id ='c1234567-89ab-cdef-0123-456789abcdef'AND repository_id ='98765432-10fe-dcba-ba09-876543210fed'ORDER BY created_at DESCLIMIT20;
Without Optimization: PostgreSQL performs a full Seq Scan on interactions, filtering out rows that do not match user_id and repository_id, then performs an in-memory or on-disk sort (Quick Sort) on created_at. Cost: O(N) where N is total interactions.
With Optimization: PostgreSQL performs an Index Scan on idx_interactions_user_id or idx_interactions_repository_id, intersecting the two bitmap indexes, and uses the pre-sorted temporal index idx_interactions_created_at_desc to retrieve the rows immediately. Cost: O(log N) + constant lookup.
Query 2: Searching interactions discussing a specific array of topics (e.g. 'auth', 'database')
SELECT*FROM interactions
WHERE topics_discussed @> ARRAY['auth', 'database']::TEXT[];
Without Optimization: Forces a Sequential Scan and evaluates the array containment operator (@>) on every single row. Highly CPU intensive.
With Optimization: Performs a Bitmap Index Scan on the GIN index idx_interactions_topics_discussed_gin, instantly pinpointing the matching rows without touching any unrelated disk pages. Performance gain is 100x to 1000x as data scales.
3. Part 2: Standardizing Asynchronous Task Scheduling
3.1 The Problem
Devr.AI needs to run scheduled background jobs:
Periodic synchronization of repository metrics (stars, forks, open issues).
Weekly compiler/cleanup of conversation summaries (conversation_context aggregation).
Automated health-checks of linked Discord and Slack integrations.
Token expiration monitoring for OAuth tokens.
Currently, Devr.AI uses aio-pika (RabbitMQ) for real-time reactive event handling, but lacks a centralized, reliable background scheduler. Writing infinite while True: await asyncio.sleep(86400) loops inside the web server is an anti-pattern:
If the FastAPI process restarts, the sleep timer is reset.
If multiple worker instances are scaled horizontally, each worker will run the same background task simultaneously, causing race conditions and database locks.
There is no visibility, error logging, or manual trigger capabilities for scheduled jobs.
3.2 Proposed Architecture: APScheduler with PostgreSQL (Supabase) Job Store
We propose standardizing on APScheduler 3.x/4.x with a SQLAlchemy/PostgreSQL Job Store. This integrates perfectly with Devr.AI's Supabase-backed database layer.
flowchart TD
subgraph FastAPI Web Process
A[FastAPI App Lifespan] -->|Initializes| B(AsyncScheduler)
B -->|Configures| C[(PostgreSQL Job Store)]
end
subgraph PostgreSQL Database
C --- D[Table: apscheduler_jobs]
end
subgraph Cluster Deployment
E[FastAPI Worker Instance 1] -->|Row Lock| D
F[FastAPI Worker Instance 2] -->|Row Lock| D
end
B -->|Triggers Job| G[Execute Sync Job]
G -->|Optionally Publishes Event| H[RabbitMQ Event Bus]
Loading
Key Benefits:
Persistence: Scheduled tasks are stored in a database table. If the servers crash, the scheduler picks up exactly where it left off, catching up on missed triggers (coalesce=True).
Distributed Locking (Cluster-Safe): If we scale to 3 FastAPI worker containers, APScheduler uses PostgreSQL's row-locking mechanisms to ensure that only one instance executes a scheduled job at a given time.
Async Native: Fully supports async/await syntax, allowing jobs to query databases or invoke agents using non-blocking I/O.
3.3 Database Table Definition for Jobs
APScheduler automatically generates its required table, but for completeness and integration with migrations, the underlying table structure in our PostgreSQL/Supabase DB is:
-- DDL for APScheduler persistence (if manually managed or audited)CREATETABLEIF NOT EXISTS apscheduler_jobs (
id VARCHAR(191) PRIMARY KEYNOT NULL,
next_run_time DOUBLE PRECISION,
job_state BYTEANOT NULL
);
COMMENT ON TABLE apscheduler_jobs IS 'Stores persistent scheduled tasks and their execution states for Devr.AI';
3.4 Pydantic Model for Job Declarations
To expose job states on our admin dashboards or monitor them programmatically, we declare a Pydantic representation:
frompydanticimportBaseModel, FieldfromtypingimportOptionalfromdatetimeimportdatetimeclassScheduledJobResponse(BaseModel):
"""Schema representing a registered background task in Devr.AI."""id: str=Field(..., description="Unique identifier of the background job")
name: str=Field(..., description="Human-readable name of the function being executed")
next_run_time: Optional[datetime] =Field(None, description="Timestamp of the next planned execution")
trigger: str=Field(..., description="Type of trigger (interval, cron, or date)")
coalesce: bool=Field(True, description="Whether to merge multiple missed executions into a single run")
is_paused: bool=Field(False, description="Indicates if the job is temporarily suspended")
3.5 Python Implementation: Centralized Scheduler Service
We propose adding a centralized scheduler module under backend/app/core/scheduler.py:
To start and stop the scheduler automatically with our API server:
fromcontextlibimportasynccontextmanagerfromfastapiimportFastAPIfromapp.core.schedulerimportget_scheduler, register_standard_jobs@asynccontextmanagerasyncdeflifespan(app: FastAPI):
# Startuplogger.info("Initializing system scheduler...")
sched=get_scheduler()
register_standard_jobs(sched)
sched.start()
logger.info("Background scheduler started successfully.")
yield# Shutdownlogger.info("Shutting down background scheduler...")
sched.shutdown()
logger.info("Scheduler shutdown complete.")
app=FastAPI(lifespan=lifespan)
4. Implementation Steps & Feedback
We request the community's and maintainers' feedback on:
Index Coverage: Are there other high-frequency lookups performed by our LangGraph agents (e.g., Weaviate/FalkorDB sync scripts) that we should include in the SQL index migration?
Scheduler Store: Is SQLAlchemy/PostgreSQL preferred for the persistent Job Store, or should we consider Redis if Devr.AI scales towards a larger event-driven topology? Using Supabase/PostgreSQL is currently the most lightweight path as we already run it.
Upon agreement, we will provide a Pull Request containing:
RFC: Database Index Schema Optimizations & Standardized Asynchronous Task Scheduling
Status: Draft
Author: Antigravity (AI Contributor)
Target Repository: AOSSIE-Org/Devr.AI
Date: June 26, 2026
1. Executive Summary
As an AI-powered Developer Relations Assistant, Devr.AI is built to process high-throughput event streams from platforms like Discord, Slack, and GitHub in real-time. To maintain high responsiveness, sub-second latency, and horizontal scalability under high workloads, the backend infrastructure must be optimized both at the data persistence layer and the asynchronous task scheduling layer.
This RFC proposes two major system enhancements:
interactionsandrepositoriesto eliminate Sequential Scans (Seq Scan).2. Part 1: Database Index Schema Optimizations
2.1 The Problem
An audit of the current database schema file (create_db.sql) reveals several index gaps:
interactionsTable: This is the most active table in the system, storing every message, comment, and PR event. However, no indexes are defined onuser_id,repository_id,platform,created_at, ortopics_discussed. Any query listing user interactions, filtering by platform, searching topics, or sorting by time forces a costlySeq Scan(O(N) search complexity).repositoriesTable: Frequently searched byfull_name(owner/repo) orowner/nameto look up indexing state or retrieve metadata. Lack of index coverage on these columns degrades performance of LLM tool retrievals.organization_integrationsTable: Frequently queried by the Discord/Slack bots to verify which active organizations to serve. While it has single-column indexes, it lacks optimal composite index coverage for active platforms.2.2 Proposed SQL Indexing Schema
We propose executing a database migration containing the following index declarations:
2.3 Query Performance Breakdown (Before & After)
Query 1: Fetching the latest 20 interactions for a user within a specific repository
Seq Scanoninteractions, filtering out rows that do not matchuser_idandrepository_id, then performs an in-memory or on-disk sort (Quick Sort) oncreated_at. Cost: O(N) where N is total interactions.Index Scanonidx_interactions_user_idoridx_interactions_repository_id, intersecting the two bitmap indexes, and uses the pre-sorted temporal indexidx_interactions_created_at_descto retrieve the rows immediately. Cost: O(log N) + constant lookup.Query 2: Searching interactions discussing a specific array of topics (e.g. 'auth', 'database')
@>) on every single row. Highly CPU intensive.Bitmap Index Scanon the GIN indexidx_interactions_topics_discussed_gin, instantly pinpointing the matching rows without touching any unrelated disk pages. Performance gain is 100x to 1000x as data scales.3. Part 2: Standardizing Asynchronous Task Scheduling
3.1 The Problem
Devr.AI needs to run scheduled background jobs:
conversation_contextaggregation).Currently, Devr.AI uses
aio-pika(RabbitMQ) for real-time reactive event handling, but lacks a centralized, reliable background scheduler. Writing infinitewhile True: await asyncio.sleep(86400)loops inside the web server is an anti-pattern:3.2 Proposed Architecture: APScheduler with PostgreSQL (Supabase) Job Store
We propose standardizing on APScheduler 3.x/4.x with a SQLAlchemy/PostgreSQL Job Store. This integrates perfectly with Devr.AI's Supabase-backed database layer.
flowchart TD subgraph FastAPI Web Process A[FastAPI App Lifespan] -->|Initializes| B(AsyncScheduler) B -->|Configures| C[(PostgreSQL Job Store)] end subgraph PostgreSQL Database C --- D[Table: apscheduler_jobs] end subgraph Cluster Deployment E[FastAPI Worker Instance 1] -->|Row Lock| D F[FastAPI Worker Instance 2] -->|Row Lock| D end B -->|Triggers Job| G[Execute Sync Job] G -->|Optionally Publishes Event| H[RabbitMQ Event Bus]Key Benefits:
coalesce=True).async/awaitsyntax, allowing jobs to query databases or invoke agents using non-blocking I/O.3.3 Database Table Definition for Jobs
APScheduler automatically generates its required table, but for completeness and integration with migrations, the underlying table structure in our PostgreSQL/Supabase DB is:
3.4 Pydantic Model for Job Declarations
To expose job states on our admin dashboards or monitor them programmatically, we declare a Pydantic representation:
3.5 Python Implementation: Centralized Scheduler Service
We propose adding a centralized scheduler module under
backend/app/core/scheduler.py:FastAPI Lifespan Integration (
backend/app/main.py):To start and stop the scheduler automatically with our API server:
4. Implementation Steps & Feedback
We request the community's and maintainers' feedback on:
Upon agreement, we will provide a Pull Request containing:
02_optimize_indexes_and_jobs.sql.apschedulerandsqlalchemy).app/core/scheduler.pyand integration in the FastAPI lifespan.