🐘 Nile Postgres Admin

Multi-tenant database with advanced extensions

Not configured

📝 Nile DB Configuration

Nile Postgres provides multi-tenant capabilities with built-in extensions.

Features Available:

  • Multi-tenancy - Isolate data by organization/tenant
  • pgvector - Vector similarity search for AI embeddings
  • pg_cron - Schedule database jobs
  • PostGIS - Geographic data support
  • Full-text search - Advanced text search
  • Row-level security - Tenant isolation

Environment Variables Needed:

# Add to .env
NILE_POSTGRES_URL=postgresql://user:password@db.thenile.dev:5432/db_name
NILE_API_KEY=your_nile_api_key_here
        

Database Extensions

🔍 pgvector

Vector similarity search for AI embeddings

Not installed

⏰ pg_cron

Schedule database jobs

Not installed

🗺️ PostGIS

Geographic objects and spatial functions

Not installed

🔎 pg_trgm

Fuzzy string matching

Not installed

Extension Usage Examples

-- pgvector: Store and search embeddings
CREATE TABLE lyrics_embeddings (
  id UUID PRIMARY KEY,
  lyric_text TEXT,
  embedding vector(1536),  -- OpenAI embedding size
  created_at TIMESTAMP DEFAULT NOW()
);

-- Create vector similarity index
CREATE INDEX ON lyrics_embeddings USING ivfflat (embedding vector_cosine_ops);

-- Search similar lyrics
SELECT lyric_text, embedding <=> '[...]'::vector AS distance
FROM lyrics_embeddings
ORDER BY distance LIMIT 10;

-- pg_cron: Schedule airdrop distributions
SELECT cron.schedule(
  'distribute-weekly-airdrops',
  '0 0 * * 1',  -- Every Monday at midnight
  $$SELECT distribute_airdrops('weekly');$$
);

-- PostGIS: Find nearby gardens
SELECT name, ST_Distance(location, ST_Point(-1.5, 36.8)) as distance
FROM gardens
WHERE ST_DWithin(location, ST_Point(-1.5, 36.8), 0.1)
ORDER BY distance;

Multi-Tenant Management

Tenant Isolation

Nile provides built-in multi-tenancy for isolating data by organization or user.

-- Create tenant-aware table
CREATE TABLE battles (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL,  -- Nile automatically filters by this
  challenger_id UUID,
  opponent_id UUID,
  status VARCHAR(20),
  created_at TIMESTAMP DEFAULT NOW()
);

-- Enable RLS for tenant isolation
ALTER TABLE battles ENABLE ROW LEVEL SECURITY;

-- Policy: Users can only see their tenant's data
CREATE POLICY tenant_isolation ON battles
  FOR ALL
  USING (tenant_id = current_setting('app.tenant_id')::UUID);

-- Set tenant context in application
SET app.tenant_id = 'tenant-uuid-here';

-- Now all queries automatically filter by tenant
SELECT * FROM battles;  -- Only returns battles for current tenant
          

Use Cases for WorldBridge One

  • Organizations - Separate data for different refugee camps
  • Communities - Isolate battle leagues or garden groups
  • Events - Separate hackathon or tournament data
  • Privacy - Ensure data doesn't leak between tenants

AI Vector Search

Use Cases

🎤 Lyric Similarity

Find similar rap bars based on meaning, not just keywords

🎵 Music Recommendations

Recommend tracks based on content similarity

📚 Content Discovery

Find related educational content or projects

🤖 Semantic Search

Search by meaning, not exact matches

Implementation Example

-- 1. Create embeddings table for battle submissions
CREATE TABLE battle_submission_embeddings (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  submission_id UUID REFERENCES battle_submissions(id),
  bars_text TEXT,
  embedding vector(1536),
  created_at TIMESTAMP DEFAULT NOW()
);

-- 2. Create index for fast similarity search
CREATE INDEX battle_embedding_idx
  ON battle_submission_embeddings
  USING ivfflat (embedding vector_cosine_ops)
  WITH (lists = 100);

-- 3. Store embedding (generated via OpenAI API)
INSERT INTO battle_submission_embeddings (submission_id, bars_text, embedding)
VALUES (
  'submission-uuid',
  'Your bars here...',
  '[0.123, -0.456, ...]'::vector  -- From OpenAI embeddings API
);

-- 4. Find similar bars
SELECT
  s.bars_text,
  e.embedding <=> $1::vector AS similarity_score
FROM battle_submission_embeddings e
JOIN battle_submissions s ON e.submission_id = s.id
ORDER BY similarity_score
LIMIT 10;

Scheduled Database Jobs

Job Ideas for WorldBridge One

Weekly Airdrop Distribution

Every Monday at 00:00 UTC

SELECT cron.schedule(
  'weekly-airdrops',
  '0 0 * * 1',
  $$SELECT activate_weekly_airdrops();$$
);

Battle Timeout Checker

Every hour, forfeit overdue submissions

SELECT cron.schedule(
  'battle-timeouts',
  '0 * * * *',
  $$SELECT check_battle_timeouts();$$
);

Impact Metrics Update

Daily at 01:00 UTC

SELECT cron.schedule(
  'daily-impact-calc',
  '0 1 * * *',
  $$SELECT calculate_daily_impact();$$
);

Notification Cleanup

Weekly, delete old read notifications

SELECT cron.schedule(
  'notification-cleanup',
  '0 2 * * 0',
  $$DELETE FROM notifications
     WHERE is_read = true
     AND created_at < NOW() - INTERVAL '30 days';$$
);

Manage Jobs

-- List all scheduled jobs
SELECT * FROM cron.job;

-- Unschedule a job
SELECT cron.unschedule('weekly-airdrops');

-- View job run history
SELECT * FROM cron.job_run_details
ORDER BY start_time DESC
LIMIT 10;
        

Geographic Data (PostGIS)

Use Cases

  • Garden Locations - Store and query community garden coordinates
  • Event Venues - Find nearby events based on location
  • Impact Mapping - Visualize Kakuma camp projects on a map
  • Resource Distribution - Optimize delivery routes

Implementation

-- Add location column to gardens
ALTER TABLE gardens
ADD COLUMN location GEOGRAPHY(POINT, 4326);

-- Create spatial index
CREATE INDEX gardens_location_idx
  ON gardens
  USING GIST (location);

-- Insert garden with coordinates (Kakuma Camp)
UPDATE gardens
SET location = ST_SetSRID(ST_MakePoint(34.813, 3.121), 4326)
WHERE name = 'Kakuma Victory Garden';

-- Find gardens within 5km of a point
SELECT
  name,
  ST_Distance(location, ST_SetSRID(ST_MakePoint(34.8, 3.1), 4326)) / 1000 AS distance_km
FROM gardens
WHERE ST_DWithin(
  location,
  ST_SetSRID(ST_MakePoint(34.8, 3.1), 4326),
  5000  -- 5km in meters
)
ORDER BY distance_km;

-- Find nearest garden to a location
SELECT name, location
FROM gardens
ORDER BY location <-> ST_SetSRID(ST_MakePoint(34.813, 3.121), 4326)
LIMIT 1;

🚀 Getting Started with Nile

1. Sign up for Nile

Visit thenile.dev and create an account

2. Create Database

Create a new Nile database from the dashboard

3. Get Connection String

postgresql://user:password@db.thenile.dev:5432/your_db

4. Add to Environment

# .env
NILE_POSTGRES_URL=your_connection_string_here
NILE_API_KEY=your_api_key_here
          

5. Install Extensions

-- Run in Nile SQL console
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS pg_cron;
CREATE EXTENSION IF NOT EXISTS postgis;
          

6. Test Connection

Use this admin panel to verify connection and run queries