SynfraCore
Synfracore
Start Learning
Navigation

Academies

Platform

RoadmapsLabsCertificationsInterviewPYQsAI AssistantCareer
Start Learning Free🗺️ Learning Roadmaps

PostgreSQLProjects

Portfolio-ready projects to demonstrate your skills

✍️
Written by senior engineers. Reviewed for technical accuracy.· Updated 2025 · SynfraCore PostgreSQL Team
Expert Content

PostgreSQL -- Portfolio Projects

Three PostgreSQL projects from schema design to analytics to production operations.

---

Project 1: E-Commerce Schema with Optimized Queries

Level: Beginner | Time: 2 days | GitHub: postgres-ecommerce-schema

What you build: Complete 8-table e-commerce schema with 50K+ rows of test data and 15 optimized queries covering every common SQL pattern.

Schema highlights

sql
CREATE TABLE users (
    id         BIGSERIAL PRIMARY KEY,
    email      TEXT UNIQUE NOT NULL,
    name       TEXT NOT NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE orders (
    id         BIGSERIAL PRIMARY KEY,
    user_id    BIGINT NOT NULL REFERENCES users(id),
    status     TEXT NOT NULL DEFAULT 'pending'
               CHECK (status IN ('pending','paid','shipped','delivered','cancelled')),
    total      NUMERIC(12,2) NOT NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- Indexes for query patterns
CREATE INDEX idx_orders_user_id ON orders(user_id);
CREATE INDEX idx_orders_status_created ON orders(status, created_at DESC);
CREATE INDEX idx_products_price ON products(price) WHERE stock > 0;  -- Partial index

Key queries to demonstrate

sql
-- Customer lifetime value with rank
SELECT u.name,
    COUNT(o.id) AS orders,
    SUM(o.total) AS lifetime_value,
    RANK() OVER (ORDER BY SUM(o.total) DESC) AS rank
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id, u.name
ORDER BY lifetime_value DESC NULLS LAST;

-- Month-over-month growth
WITH monthly AS (
    SELECT DATE_TRUNC('month', created_at) AS month,
           SUM(total) AS revenue
    FROM orders WHERE status != 'cancelled'
    GROUP BY 1
)
SELECT month, revenue,
    LAG(revenue) OVER (ORDER BY month) AS prev_month,
    ROUND((revenue - LAG(revenue) OVER (ORDER BY month))
          / LAG(revenue) OVER (ORDER BY month) * 100, 1) AS growth_pct
FROM monthly ORDER BY month;

Steps

1.Write schema with ALL constraints (not just PKs)
2.Generate 50K+ rows with Python Faker
3.Write 15 queries -- at least 5 must use window functions
4.EXPLAIN ANALYZE every query, document execution plans
5.Add indexes for slow queries, measure before/after
6.Write performance report with actual timing numbers

---

Project 2: TimescaleDB IoT Analytics

Level: Intermediate | Time: 2 days | GitHub: timescale-iot-analytics

What you build: IoT sensor data pipeline -- ingest 1M data points, query aggregations with continuous aggregates (400x faster than raw queries).

Setup

sql
CREATE EXTENSION IF NOT EXISTS timescaledb;

CREATE TABLE sensor_readings (
    time      TIMESTAMPTZ NOT NULL,
    sensor_id INTEGER NOT NULL,
    metric    TEXT NOT NULL,
    value     DOUBLE PRECISION NOT NULL
);

SELECT create_hypertable('sensor_readings', 'time',
    chunk_time_interval => INTERVAL '1 day');

-- Continuous aggregate (pre-computed, auto-refreshing)
CREATE MATERIALIZED VIEW hourly_averages
WITH (timescaledb.continuous) AS
SELECT time_bucket('1 hour', time) AS hour,
    sensor_id, metric,
    AVG(value) AS avg_value,
    MAX(value) AS max_value
FROM sensor_readings
GROUP BY 1, 2, 3;

Performance result to document

Raw query on 1M rows: ~2000ms
Continuous aggregate: ~5ms
Speedup: 400x

Steps

1.Run TimescaleDB via Docker
2.Create schema and hypertable
3.Load 1M rows with Python COPY command
4.Create continuous aggregate
5.Benchmark: measure raw vs aggregate query time
6.Add data retention policy (keep 1 year)
7.Connect Grafana for visualization

---

Project 3: High-Availability PostgreSQL with pgBouncer

Level: Advanced | Time: 3-4 days | GitHub: postgres-ha-setup

What you build: Primary + replica PostgreSQL with automatic failover using Patroni, connection pooling with pgBouncer, and monitoring with pg_stat_statements.

Docker Compose architecture

yaml
services:
  postgres-primary:
    image: postgres:16
    environment:
      POSTGRES_REPLICATION_MODE: master
      POSTGRES_REPLICATION_USER: replicator

  postgres-replica:
    image: postgres:16
    environment:
      POSTGRES_REPLICATION_MODE: slave
      POSTGRES_MASTER_HOST: postgres-primary

  pgbouncer:
    image: pgbouncer/pgbouncer
    environment:
      DB_HOST: postgres-primary
      POOL_MODE: transaction
      MAX_CLIENT_CONN: 1000
      DEFAULT_POOL_SIZE: 20

Steps

1.Set up primary + replica with streaming replication
2.Verify replication lag: SELECT * FROM pg_stat_replication
3.Install pgBouncer in transaction mode (10x more connections)
4.Enable pg_stat_statements for query performance tracking
5.Simulate primary failure, verify replica promotion
6.Load test: 500 concurrent connections via pgBouncer vs direct

---

Portfolio Checklist

[ ] Schema initialized from migration files (Flyway or plain SQL scripts)
[ ] EXPLAIN ANALYZE output in README for top 5 queries
[ ] Indexes documented: what was added and measured impact
[ ] README answers: "Why NUMERIC not FLOAT for prices?"
[ ] All constraints implemented: NOT NULL, CHECK, UNIQUE, FK
Share:
Join our Community
Daily tips, job alerts, interview help — join engineers learning together
Up Next
💬
PostgreSQLInterview Q&A
Most asked interview questions with detailed answers
Also Worth Exploring
← Back to all PostgreSQL modules
LabsInterview Q&A