OOKNET                             [ /  search the index  ]  
──────────────────────────────────────────────────────────────────────────────────────
══════════════════════════════════════════════════════════════════════════════════════
OOKNET   [ /  search  ]  
────────────────────────────────────────────────
════════════════════════════════════════════════
 
HASH      f3faba3ee50f
DATE      2025-11-17
SUBJECT   ookstats: fetch based on seasons
FILES     10 CHANGED
HASH      f3faba3ee50f
DATE      2025-11-17
SUBJECT   ookstats: fetch based on seasons
FILES     10 CHANGED
 

diff --git a/nix/pkgs/ookstats/src/cmd/analyze.go b/nix/pkgs/ookstats/src/cmd/anal
yze.go
index 551b305..6a30341 100644
--- a/nix/pkgs/ookstats/src/cmd/analyze.go
+++ b/nix/pkgs/ookstats/src/cmd/analyze.go
@@ -2,6 +2,7 @@ package cmd
 
 import (
     "context"
+    "database/sql"
     "encoding/json"
     "errors"
     "fmt"
@@ -14,6 +15,7 @@ import (
 
     "github.com/spf13/cobra"
     "ookstats/internal/blizzard"
+    "ookstats/internal/database"
 )
 
 // analyzeCmd performs a quick multi-period sweep to summarize latest runs per re
alm
@@ -29,6 +31,13 @@ var analyzeCmd = &cobra.Command{
         rng, _ := cmd.Flags().GetString("range")
         concurrency, _ := cmd.Flags().GetInt("concurrency")
 
+        // Connect to database (needed for period fetching from seasons)
+        db, err := database.Connect()
+        if err != nil {
+            return fmt.Errorf("db connect: %w", err)
+        }
+        defer db.Close()
+
         client, err := blizzard.NewClient()
         if err != nil {
             return fmt.Errorf("blizzard client: %w", err)
@@ -71,7 +80,7 @@ var analyzeCmd = &cobra.Command{
             periodsSpec = strings.Join(periodParts, ",")
         }
 
-        return runAnalyze(client, realms, dungeons, periodsSpec, outPath, statusD
ir)
+        return runAnalyze(db, client, realms, dungeons, periodsSpec, outPath, sta
tusDir)
     },
 }
 
@@ -85,7 +94,8 @@ func init() {
     analyzeCmd.Flags().Int("concurrency", 20, "Max concurrent API requests")
 }
 
-func runAnalyze(client *blizzard.Client, realms map[string]blizzard.RealmInfo, du
ngeons []blizzard.DungeonInfo, periodsSpec string, outPath, statusDir string) erro
r {
+func runAnalyze(db *sql.DB, client *blizzard.Client, realms map[string]blizzard.R
ealmInfo, dungeons []blizzard.DungeonInfo, periodsSpec string, outPath, statusDir 
string) error {
+        dbService := database.NewDatabaseService(db)
         fmt.Printf("Analyze: %d realms, %d dungeons\n", len(realms), len(dungeons
))
 
         type latest struct{
@@ -153,13 +163,27 @@ func runAnalyze(client *blizzard.Client, realms map[string]b
lizzard.RealmInfo, d
                 }
                 fmt.Printf("Using user-specified periods: %v (%d periods)\n", per
iods, len(periods))
             } else {
-                // Fetch periods dynamically from Blizzard API for this region
-                fmt.Printf("Fetching period list dynamically from Blizzard API fo
r %s...\n", strings.ToUpper(region))
-                periods, err = client.GetDynamicPeriodList(region)
+                // Fetch periods from database (populated by season sync)
+                fmt.Printf("Fetching period list from database for %s...\n", stri
ngs.ToUpper(region))
+                periodInts, err := dbService.GetPeriodsForRegion(region)
                 if err != nil {
-                    fmt.Printf("Failed to fetch period list for %s: %v - skipping
 region\n", strings.ToUpper(region), err)
+                    fmt.Printf("Failed to fetch periods from database for %s: %v 
- skipping region\n", strings.ToUpper(region), err)
                     continue
                 }
+
+                // Convert []int to []string for compatibility
+                periods = make([]string, len(periodInts))
+                for i, p := range periodInts {
+                    periods[i] = fmt.Sprintf("%d", p)
+                }
+
+                if len(periods) == 0 {
+                    fmt.Printf("No periods found in database for %s (run season s
ync first) - skipping region\n", strings.ToUpper(region))
+                    continue
+                }
+
+                fmt.Printf("[OK] Fetched %d periods from database for %s (newest:
 %s, oldest: %s)\n",
+                    len(periods), strings.ToUpper(region), periods[0], periods[le
n(periods)-1])
             }
 
             if len(periods) == 0 {

diff --git a/nix/pkgs/ookstats/src/cmd/analy
ze.go b/nix/pkgs/ookstats/src/cmd/analyze.go
index 551b305..6a30341 100644
--- a/nix/pkgs/ookstats/src/cmd/analyze.go
+++ b/nix/pkgs/ookstats/src/cmd/analyze.go
@@ -2,6 +2,7 @@ package cmd
 
 import (
     "context"
+    "database/sql"
     "encoding/json"
     "errors"
     "fmt"
@@ -14,6 +15,7 @@ import (
 
     "github.com/spf13/cobra"
     "ookstats/internal/blizzard"
+    "ookstats/internal/database"
 )
 
 // analyzeCmd performs a quick multi-period
 sweep to summarize latest runs per realm
@@ -29,6 +31,13 @@ var analyzeCmd = &cobra.C
ommand{
         rng, _ := cmd.Flags().GetString("ra
nge")
         concurrency, _ := cmd.Flags().GetIn
t("concurrency")
 
+        // Connect to database (needed for 
period fetching from seasons)
+        db, err := database.Connect()
+        if err != nil {
+            return fmt.Errorf("db connect: 
%w", err)
+        }
+        defer db.Close()
+
         client, err := blizzard.NewClient()
         if err != nil {
             return fmt.Errorf("blizzard cli
ent: %w", err)
@@ -71,7 +80,7 @@ var analyzeCmd = &cobra.Co
mmand{
             periodsSpec = strings.Join(peri
odParts, ",")
         }
 
-        return runAnalyze(client, realms, d
ungeons, periodsSpec, outPath, statusDir)
+        return runAnalyze(db, client, realm
s, dungeons, periodsSpec, outPath, statusDir
)
     },
 }
 
@@ -85,7 +94,8 @@ func init() {
     analyzeCmd.Flags().Int("concurrency", 2
0, "Max concurrent API requests")
 }
 
-func runAnalyze(client *blizzard.Client, re
alms map[string]blizzard.RealmInfo, dungeons
 []blizzard.DungeonInfo, periodsSpec string,
 outPath, statusDir string) error {
+func runAnalyze(db *sql.DB, client *blizzar
d.Client, realms map[string]blizzard.RealmIn
fo, dungeons []blizzard.DungeonInfo, periods
Spec string, outPath, statusDir string) erro
r {
+        dbService := database.NewDatabaseSe
rvice(db)
         fmt.Printf("Analyze: %d realms, %d 
dungeons\n", len(realms), len(dungeons))
 
         type latest struct{
@@ -153,13 +163,27 @@ func runAnalyze(client
 *blizzard.Client, realms map[string]blizzar
d.RealmInfo, d
                 }
                 fmt.Printf("Using user-spec
ified periods: %v (%d periods)\n", periods, 
len(periods))
             } else {
-                // Fetch periods dynamicall
y from Blizzard API for this region
-                fmt.Printf("Fetching period
 list dynamically from Blizzard API for %s..
.\n", strings.ToUpper(region))
-                periods, err = client.GetDy
namicPeriodList(region)
+                // Fetch periods from datab
ase (populated by season sync)
+                fmt.Printf("Fetching period
 list from database for %s...\n", strings.To
Upper(region))
+                periodInts, err := dbServic
e.GetPeriodsForRegion(region)
                 if err != nil {
-                    fmt.Printf("Failed to f
etch period list for %s: %v - skipping regio
n\n", strings.ToUpper(region), err)
+                    fmt.Printf("Failed to f
etch periods from database for %s: %v - skip
ping region\n", strings.ToUpper(region), err
)
                     continue
                 }
+
+                // Convert []int to []strin
g for compatibility
+                periods = make([]string, le
n(periodInts))
+                for i, p := range periodInt
s {
+                    periods[i] = fmt.Sprint
f("%d", p)
+                }
+
+                if len(periods) == 0 {
+                    fmt.Printf("No periods 
found in database for %s (run season sync fi
rst) - skipping region\n", strings.ToUpper(r
egion))
+                    continue
+                }
+
+                fmt.Printf("[OK] Fetched %d
 periods from database for %s (newest: %s, o
ldest: %s)\n",
+                    len(periods), strings.T
oUpper(region), periods[0], periods[len(peri
ods)-1])
             }
 
             if len(periods) == 0 {
 

diff --git a/nix/pkgs/ookstats/src/cmd/build.go b/nix/pkgs/ookstats/src/cmd/build.
go
index 9bee107..eb19768 100644
--- a/nix/pkgs/ookstats/src/cmd/build.go
+++ b/nix/pkgs/ookstats/src/cmd/build.go
@@ -177,7 +177,7 @@ var buildCmd = &cobra.Command{
         // Get realms and dungeons for analyze
         _, dungeons := blizzard.GetHardcodedPeriodAndDungeons()
         allRealms := blizzard.GetAllRealms()
-        if err := runAnalyze(client, allRealms, dungeons, periodsCSV, outPath, st
atusDir); err != nil {
+        if err := runAnalyze(db, client, allRealms, dungeons, periodsCSV, outPath
, statusDir); err != nil {
             return fmt.Errorf("analyze status: %w", err)
         }
 
@@ -308,76 +308,88 @@ func summarizeBuild(db *sql.DB, outParent string) {
     }
 }
 
-// syncSeasons syncs season metadata from Blizzard API
+// syncSeasons syncs season metadata from Blizzard API for all regions
 func syncSeasons(db *sql.DB, client *blizzard.Client, regionsCSV string) error {
 	dbService := database.NewDatabaseService(db)
 
-	// Only need one region since seasons are global
-	region := "us"
+	// Parse regions from CSV (seasons and periods are region-specific)
+	var regions []string
 	if strings.TrimSpace(regionsCSV) != "" {
-		parts := strings.Split(regionsCSV, ",")
-		if len(parts) > 0 {
-			region = strings.TrimSpace(parts[0])
+		for _, r := range strings.Split(regionsCSV, ",") {
+			if trimmed := strings.TrimSpace(r); trimmed != "" {
+				regions = append(regions, trimmed)
+			}
 		}
 	}
 
-	fmt.Printf("Fetching season metadata from %s...\n", strings.ToUpper(region))
-
-	// Fetch season index
-	seasonIndex, err := client.FetchSeasonIndex(region)
-	if err != nil {
-		return fmt.Errorf("failed to fetch season index: %w", err)
-	}
-
-	if len(seasonIndex.Seasons) == 0 {
-		fmt.Println("No seasons found in API")
-		return nil
+	// Default to all regions if none specified
+	if len(regions) == 0 {
+		regions = []string{"us", "eu", "kr", "tw"}
 	}
 
-	fmt.Printf("Found %d seasons\n", len(seasonIndex.Seasons))
+	fmt.Printf("Fetching season metadata from %d regions...\n", len(regions))
 
-	// Process each season
-	for _, seasonRef := range seasonIndex.Seasons {
-		seasonID := seasonRef.ID
-		fmt.Printf("  Season %d: ", seasonID)
+	// Process each region
+	for _, region := range regions {
+		fmt.Printf("\n=== Region: %s ===\n", strings.ToUpper(region))
 
-		// Fetch season details
-		seasonDetail, err := client.FetchSeasonDetail(region, seasonID)
+		// Fetch season index for this region
+		seasonIndex, err := client.FetchSeasonIndex(region)
 		if err != nil {
-			fmt.Printf("error fetching details - %v\n", err)
+			fmt.Printf("Failed to fetch season index for %s: %v - skipping region\n", stri
ngs.ToUpper(region), err)
 			continue
 		}
 
-		// Upsert season
-		err = dbService.UpsertSeason(seasonDetail.ID, seasonDetail.SeasonName, seasonDe
tail.StartTimestamp)
-		if err != nil {
-			fmt.Printf("error upserting - %v\n", err)
+		if len(seasonIndex.Seasons) == 0 {
+			fmt.Printf("No seasons found for %s\n", strings.ToUpper(region))
 			continue
 		}
 
-		// Link periods to season
-		if len(seasonDetail.Periods) > 0 {
-			firstPeriod := seasonDetail.Periods[0].ID
-			lastPeriod := seasonDetail.Periods[len(seasonDetail.Periods)-1].ID
+		fmt.Printf("Found %d seasons in %s\n", len(seasonIndex.Seasons), strings.ToUppe
r(region))
+
+		// Process each season for this region
+		for _, seasonRef := range seasonIndex.Seasons {
+			seasonID := seasonRef.ID
+			fmt.Printf("  Season %d: ", seasonID)
 
-			// Update period range
-			err = dbService.UpdateSeasonPeriodRange(seasonDetail.ID, firstPeriod, lastPeri
od)
+			// Fetch season details
+			seasonDetail, err := client.FetchSeasonDetail(region, seasonID)
 			if err != nil {
-				fmt.Printf("error updating period range - %v\n", err)
+				fmt.Printf("error fetching details - %v\n", err)
+				continue
 			}
 
-			// Link each period
-			for _, periodRef := range seasonDetail.Periods {
-				err = dbService.LinkPeriodToSeason(periodRef.ID, seasonDetail.ID)
+			// Upsert season with region
+			dbSeasonID, err := dbService.UpsertSeason(seasonDetail.ID, region, seasonDetai
l.SeasonName, seasonDetail.StartTimestamp)
+			if err != nil {
+				fmt.Printf("error upserting - %v\n", err)
+				continue
+			}
+
+			// Link periods to season
+			if len(seasonDetail.Periods) > 0 {
+				firstPeriod := seasonDetail.Periods[0].ID
+				lastPeriod := seasonDetail.Periods[len(seasonDetail.Periods)-1].ID
+
+				// Update period range
+				err = dbService.UpdateSeasonPeriodRange(dbSeasonID, firstPeriod, lastPeriod)
 				if err != nil {
-					fmt.Printf("error linking period %d - %v\n", periodRef.ID, err)
+					fmt.Printf("error updating period range - %v\n", err)
+				}
+
+				// Link each period
+				for _, periodRef := range seasonDetail.Periods {
+					err = dbService.LinkPeriodToSeason(periodRef.ID, dbSeasonID)
+					if err != nil {
+						fmt.Printf("error linking period %d - %v\n", periodRef.ID, err)
+					}
 				}
 			}
+			fmt.Printf("%s (%d periods)\n", seasonDetail.SeasonName, len(seasonDetail.Peri
ods))
 		}
-		fmt.Printf("%s (%d periods)\n", seasonDetail.SeasonName, len(seasonDetail.Perio
ds))
 	}
 
-	fmt.Println("[OK] Season metadata synced")
+	fmt.Println("\n[OK] Season metadata synced for all regions")
 	return nil
 }
 

diff --git a/nix/pkgs/ookstats/src/cmd/build
.go b/nix/pkgs/ookstats/src/cmd/build.go
index 9bee107..eb19768 100644
--- a/nix/pkgs/ookstats/src/cmd/build.go
+++ b/nix/pkgs/ookstats/src/cmd/build.go
@@ -177,7 +177,7 @@ var buildCmd = &cobra.Co
mmand{
         // Get realms and dungeons for anal
yze
         _, dungeons := blizzard.GetHardcode
dPeriodAndDungeons()
         allRealms := blizzard.GetAllRealms(
)
-        if err := runAnalyze(client, allRea
lms, dungeons, periodsCSV, outPath, statusDi
r); err != nil {
+        if err := runAnalyze(db, client, al
lRealms, dungeons, periodsCSV, outPath, stat
usDir); err != nil {
             return fmt.Errorf("analyze stat
us: %w", err)
         }
 
@@ -308,76 +308,88 @@ func summarizeBuild(db
 *sql.DB, outParent string) {
     }
 }
 
-// syncSeasons syncs season metadata from B
lizzard API
+// syncSeasons syncs season metadata from B
lizzard API for all regions
 func syncSeasons(db *sql.DB, client *blizza
rd.Client, regionsCSV string) error {
 	dbService := database.NewDatabaseService(d
b)
 
-	// Only need one region since seasons are 
global
-	region := "us"
+	// Parse regions from CSV (seasons and per
iods are region-specific)
+	var regions []string
 	if strings.TrimSpace(regionsCSV) != "" {
-		parts := strings.Split(regionsCSV, ",")
-		if len(parts) > 0 {
-			region = strings.TrimSpace(parts[0])
+		for _, r := range strings.Split(regionsCS
V, ",") {
+			if trimmed := strings.TrimSpace(r); trim
med != "" {
+				regions = append(regions, trimmed)
+			}
 		}
 	}
 
-	fmt.Printf("Fetching season metadata from 
%s...\n", strings.ToUpper(region))
-
-	// Fetch season index
-	seasonIndex, err := client.FetchSeasonInde
x(region)
-	if err != nil {
-		return fmt.Errorf("failed to fetch season
 index: %w", err)
-	}
-
-	if len(seasonIndex.Seasons) == 0 {
-		fmt.Println("No seasons found in API")
-		return nil
+	// Default to all regions if none specifie
d
+	if len(regions) == 0 {
+		regions = []string{"us", "eu", "kr", "tw"
}
 	}
 
-	fmt.Printf("Found %d seasons\n", len(seaso
nIndex.Seasons))
+	fmt.Printf("Fetching season metadata from 
%d regions...\n", len(regions))
 
-	// Process each season
-	for _, seasonRef := range seasonIndex.Seas
ons {
-		seasonID := seasonRef.ID
-		fmt.Printf("  Season %d: ", seasonID)
+	// Process each region
+	for _, region := range regions {
+		fmt.Printf("\n=== Region: %s ===\n", stri
ngs.ToUpper(region))
 
-		// Fetch season details
-		seasonDetail, err := client.FetchSeasonDe
tail(region, seasonID)
+		// Fetch season index for this region
+		seasonIndex, err := client.FetchSeasonInd
ex(region)
 		if err != nil {
-			fmt.Printf("error fetching details - %v\
n", err)
+			fmt.Printf("Failed to fetch season index
 for %s: %v - skipping region\n", strings.To
Upper(region), err)
 			continue
 		}
 
-		// Upsert season
-		err = dbService.UpsertSeason(seasonDetail
.ID, seasonDetail.SeasonName, seasonDetail.S
tartTimestamp)
-		if err != nil {
-			fmt.Printf("error upserting - %v\n", err
)
+		if len(seasonIndex.Seasons) == 0 {
+			fmt.Printf("No seasons found for %s\n", 
strings.ToUpper(region))
 			continue
 		}
 
-		// Link periods to season
-		if len(seasonDetail.Periods) > 0 {
-			firstPeriod := seasonDetail.Periods[0].I
D
-			lastPeriod := seasonDetail.Periods[len(s
easonDetail.Periods)-1].ID
+		fmt.Printf("Found %d seasons in %s\n", le
n(seasonIndex.Seasons), strings.ToUpper(regi
on))
+
+		// Process each season for this region
+		for _, seasonRef := range seasonIndex.Sea
sons {
+			seasonID := seasonRef.ID
+			fmt.Printf("  Season %d: ", seasonID)
 
-			// Update period range
-			err = dbService.UpdateSeasonPeriodRange(
seasonDetail.ID, firstPeriod, lastPeriod)
+			// Fetch season details
+			seasonDetail, err := client.FetchSeasonD
etail(region, seasonID)
 			if err != nil {
-				fmt.Printf("error updating period range
 - %v\n", err)
+				fmt.Printf("error fetching details - %v
\n", err)
+				continue
 			}
 
-			// Link each period
-			for _, periodRef := range seasonDetail.P
eriods {
-				err = dbService.LinkPeriodToSeason(peri
odRef.ID, seasonDetail.ID)
+			// Upsert season with region
+			dbSeasonID, err := dbService.UpsertSeaso
n(seasonDetail.ID, region, seasonDetail.Seas
onName, seasonDetail.StartTimestamp)
+			if err != nil {
+				fmt.Printf("error upserting - %v\n", er
r)
+				continue
+			}
+
+			// Link periods to season
+			if len(seasonDetail.Periods) > 0 {
+				firstPeriod := seasonDetail.Periods[0].
ID
+				lastPeriod := seasonDetail.Periods[len(
seasonDetail.Periods)-1].ID
+
+				// Update period range
+				err = dbService.UpdateSeasonPeriodRange
(dbSeasonID, firstPeriod, lastPeriod)
 				if err != nil {
-					fmt.Printf("error linking period %d - 
%v\n", periodRef.ID, err)
+					fmt.Printf("error updating period rang
e - %v\n", err)
+				}
+
+				// Link each period
+				for _, periodRef := range seasonDetail.
Periods {
+					err = dbService.LinkPeriodToSeason(per
iodRef.ID, dbSeasonID)
+					if err != nil {
+						fmt.Printf("error linking period %d -
 %v\n", periodRef.ID, err)
+					}
 				}
 			}
+			fmt.Printf("%s (%d periods)\n", seasonDe
tail.SeasonName, len(seasonDetail.Periods))
 		}
-		fmt.Printf("%s (%d periods)\n", seasonDet
ail.SeasonName, len(seasonDetail.Periods))
 	}
 
-	fmt.Println("[OK] Season metadata synced")
+	fmt.Println("\n[OK] Season metadata synced
 for all regions")
 	return nil
 }
 
 

diff --git a/nix/pkgs/ookstats/src/cmd/fetch.go b/nix/pkgs/ookstats/src/cmd/fetch.
go
index 0432389..8e6daed 100644
--- a/nix/pkgs/ookstats/src/cmd/fetch.go
+++ b/nix/pkgs/ookstats/src/cmd/fetch.go
@@ -259,7 +259,7 @@ var fetchSeasonsCmd = &cobra.Command{
 				}
 
 				// Upsert season
-				err = dbService.UpsertSeason(seasonDetail.ID, seasonDetail.SeasonName, season
Detail.StartTimestamp)
+				dbSeasonID, err := dbService.UpsertSeason(seasonDetail.ID, region, seasonDeta
il.SeasonName, seasonDetail.StartTimestamp)
 				if err != nil {
 					fmt.Printf("Error upserting season %d: %v\n", seasonID, err)
 					continue
@@ -276,14 +276,14 @@ var fetchSeasonsCmd = &cobra.Command{
 					lastPeriod := seasonDetail.Periods[len(seasonDetail.Periods)-1].ID
 
 					// Update period range
-					err = dbService.UpdateSeasonPeriodRange(seasonDetail.ID, firstPeriod, lastPe
riod)
+					err = dbService.UpdateSeasonPeriodRange(dbSeasonID, firstPeriod, lastPeriod)
 					if err != nil {
 						fmt.Printf("Error updating season period range: %v\n", err)
 					}
 
 					// Link each period
 					for _, periodRef := range seasonDetail.Periods {
-						err = dbService.LinkPeriodToSeason(periodRef.ID, seasonDetail.ID)
+						err = dbService.LinkPeriodToSeason(periodRef.ID, dbSeasonID)
 						if err != nil {
 							fmt.Printf("Error linking period %d to season %d: %v\n", periodRef.ID, sea
sonDetail.ID, err)
 						} else {
@@ -294,10 +294,7 @@ var fetchSeasonsCmd = &cobra.Command{
 				}
 			}
 
-			// Note: We only need to sync from one region since season IDs and periods are
 global
-			// Breaking after first successful region to avoid redundant work
-			fmt.Printf("\n[OK] Synced seasons from %s (seasons are global across regions)\
n", strings.ToUpper(region))
-			break
+			fmt.Printf("\n[OK] Synced seasons for %s\n", strings.ToUpper(region))
 		}
 
 		fmt.Printf("\n=== Sync Complete ===\n")

diff --git a/nix/pkgs/ookstats/src/cmd/fetch
.go b/nix/pkgs/ookstats/src/cmd/fetch.go
index 0432389..8e6daed 100644
--- a/nix/pkgs/ookstats/src/cmd/fetch.go
+++ b/nix/pkgs/ookstats/src/cmd/fetch.go
@@ -259,7 +259,7 @@ var fetchSeasonsCmd = &c
obra.Command{
 				}
 
 				// Upsert season
-				err = dbService.UpsertSeason(seasonDeta
il.ID, seasonDetail.SeasonName, seasonDetail
.StartTimestamp)
+				dbSeasonID, err := dbService.UpsertSeas
on(seasonDetail.ID, region, seasonDetail.Sea
sonName, seasonDetail.StartTimestamp)
 				if err != nil {
 					fmt.Printf("Error upserting season %d:
 %v\n", seasonID, err)
 					continue
@@ -276,14 +276,14 @@ var fetchSeasonsCmd = 
&cobra.Command{
 					lastPeriod := seasonDetail.Periods[len
(seasonDetail.Periods)-1].ID
 
 					// Update period range
-					err = dbService.UpdateSeasonPeriodRang
e(seasonDetail.ID, firstPeriod, lastPeriod)
+					err = dbService.UpdateSeasonPeriodRang
e(dbSeasonID, firstPeriod, lastPeriod)
 					if err != nil {
 						fmt.Printf("Error updating season per
iod range: %v\n", err)
 					}
 
 					// Link each period
 					for _, periodRef := range seasonDetail
.Periods {
-						err = dbService.LinkPeriodToSeason(pe
riodRef.ID, seasonDetail.ID)
+						err = dbService.LinkPeriodToSeason(pe
riodRef.ID, dbSeasonID)
 						if err != nil {
 							fmt.Printf("Error linking period %d 
to season %d: %v\n", periodRef.ID, seasonDet
ail.ID, err)
 						} else {
@@ -294,10 +294,7 @@ var fetchSeasonsCmd = &
cobra.Command{
 				}
 			}
 
-			// Note: We only need to sync from one r
egion since season IDs and periods are globa
l
-			// Breaking after first successful regio
n to avoid redundant work
-			fmt.Printf("\n[OK] Synced seasons from %
s (seasons are global across regions)\n", st
rings.ToUpper(region))
-			break
+			fmt.Printf("\n[OK] Synced seasons for %s
\n", strings.ToUpper(region))
 		}
 
 		fmt.Printf("\n=== Sync Complete ===\n")
 

diff --git a/nix/pkgs/ookstats/src/internal/blizzard/client.go b/nix/pkgs/ookstats
/src/internal/blizzard/client.go
index 3407c4a..28b2e7e 100644
--- a/nix/pkgs/ookstats/src/internal/blizzard/client.go
+++ b/nix/pkgs/ookstats/src/internal/blizzard/client.go
@@ -489,94 +489,6 @@ type PlayerInfo struct {
 	Region    string
 }
 
-// FetchPeriodIndex fetches the list of available periods for a region
-func (c *Client) FetchPeriodIndex(region string) (*PeriodIndexResponse, error) {
-	namespace := fmt.Sprintf("dynamic-classic-%s", region)
-	url := fmt.Sprintf(
-		"https://%s.api.blizzard.com/data/wow/mythic-keystone/period/index?namespace=%s
&locale=en_US",
-		region, namespace,
-	)
-
-	const maxRetries = 3
-	const baseDelay = 1 * time.Second
-
-	var lastErr error
-	for attempt := 0; attempt < maxRetries; attempt++ {
-		if attempt > 0 {
-			delay := time.Duration(1<<uint(attempt-1)) * baseDelay
-			time.Sleep(delay)
-		}
-
-		result, err := c.fetchPeriodIndexOnce(url)
-		if err == nil {
-			return result, nil
-		}
-
-		lastErr = err
-
-		// don't retry on 4xx errors
-		if strings.Contains(err.Error(), "status 4") {
-			break
-		}
-	}
-
-	return nil, fmt.Errorf("failed to fetch period index after %d attempts: %w", max
Retries, lastErr)
-}
-
-// fetchPeriodIndexOnce performs a single period index fetch attempt
-func (c *Client) fetchPeriodIndexOnce(url string) (*PeriodIndexResponse, error) {
-	time.Sleep(50 * time.Millisecond)
-
-	req, err := http.NewRequest("GET", url, nil)
-	if err != nil {
-		return nil, fmt.Errorf("failed to create request: %w", err)
-	}
-
-	req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.Token))
-	req.Header.Set("User-Agent", "WoWStatsDB/1.0")
-
-	resp, err := c.HTTPClient.Do(req)
-	if err != nil {
-		return nil, fmt.Errorf("HTTP request failed: %w", err)
-	}
-	defer resp.Body.Close()
-
-	if resp.StatusCode != http.StatusOK {
-		bodyBytes, _ := io.ReadAll(resp.Body)
-		return nil, fmt.Errorf("API request failed with status %d: %s", resp.StatusCode
, string(bodyBytes))
-	}
-
-	var result PeriodIndexResponse
-	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
-		return nil, fmt.Errorf("failed to decode response: %w", err)
-	}
-
-	return &result, nil
-}
-
-// GetDynamicPeriodList fetches the period list from the API and returns it in re
verse order (newest first)
-func (c *Client) GetDynamicPeriodList(region string) ([]string, error) {
-	index, err := c.FetchPeriodIndex(region)
-	if err != nil {
-		return nil, fmt.Errorf("failed to fetch period list for %s: %w", region, err)
-	}
-
-	if len(index.Periods) == 0 {
-		return nil, fmt.Errorf("period index returned empty list for %s", region)
-	}
-
-	// Extract period IDs and reverse the list (newest first)
-	periods := make([]string, len(index.Periods))
-	for i, p := range index.Periods {
-		periods[len(index.Periods)-1-i] = fmt.Sprintf("%d", p.ID)
-	}
-
-	fmt.Printf("[OK] Fetched %d periods dynamically for %s (newest: %s, oldest: %s)\
n",
-		len(periods), strings.ToUpper(region), periods[0], periods[len(periods)-1])
-
-	return periods, nil
-}
-
 // FetchSeasonIndex fetches the list of available seasons for a region
 func (c *Client) FetchSeasonIndex(region string) (*SeasonIndexResponse, error) {
 	namespace := fmt.Sprintf("dynamic-classic-%s", region)

diff --git a/nix/pkgs/ookstats/src/internal/
blizzard/client.go b/nix/pkgs/ookstats/src/i
nternal/blizzard/client.go
index 3407c4a..28b2e7e 100644
--- a/nix/pkgs/ookstats/src/internal/blizzar
d/client.go
+++ b/nix/pkgs/ookstats/src/internal/blizzar
d/client.go
@@ -489,94 +489,6 @@ type PlayerInfo struct 
{
 	Region    string
 }
 
-// FetchPeriodIndex fetches the list of ava
ilable periods for a region
-func (c *Client) FetchPeriodIndex(region st
ring) (*PeriodIndexResponse, error) {
-	namespace := fmt.Sprintf("dynamic-classic-
%s", region)
-	url := fmt.Sprintf(
-		"https://%s.api.blizzard.com/data/wow/myt
hic-keystone/period/index?namespace=%s&local
e=en_US",
-		region, namespace,
-	)
-
-	const maxRetries = 3
-	const baseDelay = 1 * time.Second
-
-	var lastErr error
-	for attempt := 0; attempt < maxRetries; at
tempt++ {
-		if attempt > 0 {
-			delay := time.Duration(1<<uint(attempt-1
)) * baseDelay
-			time.Sleep(delay)
-		}
-
-		result, err := c.fetchPeriodIndexOnce(url
)
-		if err == nil {
-			return result, nil
-		}
-
-		lastErr = err
-
-		// don't retry on 4xx errors
-		if strings.Contains(err.Error(), "status 
4") {
-			break
-		}
-	}
-
-	return nil, fmt.Errorf("failed to fetch pe
riod index after %d attempts: %w", maxRetrie
s, lastErr)
-}
-
-// fetchPeriodIndexOnce performs a single p
eriod index fetch attempt
-func (c *Client) fetchPeriodIndexOnce(url s
tring) (*PeriodIndexResponse, error) {
-	time.Sleep(50 * time.Millisecond)
-
-	req, err := http.NewRequest("GET", url, ni
l)
-	if err != nil {
-		return nil, fmt.Errorf("failed to create 
request: %w", err)
-	}
-
-	req.Header.Set("Authorization", fmt.Sprint
f("Bearer %s", c.Token))
-	req.Header.Set("User-Agent", "WoWStatsDB/1
.0")
-
-	resp, err := c.HTTPClient.Do(req)
-	if err != nil {
-		return nil, fmt.Errorf("HTTP request fail
ed: %w", err)
-	}
-	defer resp.Body.Close()
-
-	if resp.StatusCode != http.StatusOK {
-		bodyBytes, _ := io.ReadAll(resp.Body)
-		return nil, fmt.Errorf("API request faile
d with status %d: %s", resp.StatusCode, stri
ng(bodyBytes))
-	}
-
-	var result PeriodIndexResponse
-	if err := json.NewDecoder(resp.Body).Decod
e(&result); err != nil {
-		return nil, fmt.Errorf("failed to decode 
response: %w", err)
-	}
-
-	return &result, nil
-}
-
-// GetDynamicPeriodList fetches the period 
list from the API and returns it in reverse 
order (newest first)
-func (c *Client) GetDynamicPeriodList(regio
n string) ([]string, error) {
-	index, err := c.FetchPeriodIndex(region)
-	if err != nil {
-		return nil, fmt.Errorf("failed to fetch p
eriod list for %s: %w", region, err)
-	}
-
-	if len(index.Periods) == 0 {
-		return nil, fmt.Errorf("period index retu
rned empty list for %s", region)
-	}
-
-	// Extract period IDs and reverse the list
 (newest first)
-	periods := make([]string, len(index.Period
s))
-	for i, p := range index.Periods {
-		periods[len(index.Periods)-1-i] = fmt.Spr
intf("%d", p.ID)
-	}
-
-	fmt.Printf("[OK] Fetched %d periods dynami
cally for %s (newest: %s, oldest: %s)\n",
-		len(periods), strings.ToUpper(region), pe
riods[0], periods[len(periods)-1])
-
-	return periods, nil
-}
-
 // FetchSeasonIndex fetches the list of ava
ilable seasons for a region
 func (c *Client) FetchSeasonIndex(region st
ring) (*SeasonIndexResponse, error) {
 	namespace := fmt.Sprintf("dynamic-classic-
%s", region)
 

diff --git a/nix/pkgs/ookstats/src/internal/blizzard/types.go b/nix/pkgs/ookstats/
src/internal/blizzard/types.go
index 25f338c..0932f7c 100644
--- a/nix/pkgs/ookstats/src/internal/blizzard/types.go
+++ b/nix/pkgs/ookstats/src/internal/blizzard/types.go
@@ -242,22 +242,6 @@ type MediaAsset struct {
 	Value string `json:"value"`
 }
 
-// PeriodIndexResponse represents the response from the mythic keystone period in
dex API
-type PeriodIndexResponse struct {
-	Periods []struct {
-		Key struct {
-			Href string `json:"href"`
-		} `json:"key"`
-		ID int `json:"id"`
-	} `json:"periods"`
-	CurrentPeriod struct {
-		Key struct {
-			Href string `json:"href"`
-		} `json:"key"`
-		ID int `json:"id"`
-	} `json:"current_period"`
-}
-
 // PeriodDetailResponse represents the response from a specific period detail API
 type PeriodDetailResponse struct {
 	ID             int   `json:"id"`

diff --git a/nix/pkgs/ookstats/src/internal/
blizzard/types.go b/nix/pkgs/ookstats/src/in
ternal/blizzard/types.go
index 25f338c..0932f7c 100644
--- a/nix/pkgs/ookstats/src/internal/blizzar
d/types.go
+++ b/nix/pkgs/ookstats/src/internal/blizzar
d/types.go
@@ -242,22 +242,6 @@ type MediaAsset struct 
{
 	Value string `json:"value"`
 }
 
-// PeriodIndexResponse represents the respo
nse from the mythic keystone period index AP
I
-type PeriodIndexResponse struct {
-	Periods []struct {
-		Key struct {
-			Href string `json:"href"`
-		} `json:"key"`
-		ID int `json:"id"`
-	} `json:"periods"`
-	CurrentPeriod struct {
-		Key struct {
-			Href string `json:"href"`
-		} `json:"key"`
-		ID int `json:"id"`
-	} `json:"current_period"`
-}
-
 // PeriodDetailResponse represents the resp
onse from a specific period detail API
 type PeriodDetailResponse struct {
 	ID             int   `json:"id"`
 

diff --git a/nix/pkgs/ookstats/src/internal/database/client.go b/nix/pkgs/ookstats
/src/internal/database/client.go
index 469e4f1..2a94fa6 100644
--- a/nix/pkgs/ookstats/src/internal/database/client.go
+++ b/nix/pkgs/ookstats/src/internal/database/client.go
@@ -324,13 +324,15 @@ func EnsureCompleteSchema(db *sql.DB) error {
 
 		// Season tables
 		`CREATE TABLE IF NOT EXISTS seasons (
-			id INTEGER PRIMARY KEY,
-			season_number INTEGER UNIQUE,
+			id INTEGER PRIMARY KEY AUTOINCREMENT,
+			season_number INTEGER NOT NULL,
+			region TEXT NOT NULL,
 			start_timestamp INTEGER,
 			end_timestamp INTEGER,
 			season_name TEXT,
 			first_period_id INTEGER,
-			last_period_id INTEGER
+			last_period_id INTEGER,
+			UNIQUE(season_number, region)
 		)`,
 
 		`CREATE TABLE IF NOT EXISTS period_seasons (
@@ -353,6 +355,11 @@ fmt.Printf("[OK] All tables created\n")
         return err
     }
 
+    // Migrate seasons schema if needed (add region column)
+    if err := migrateSeasonsAddRegion(db); err != nil {
+        return err
+    }
+
     // Create indexes
     return ensureRecommendedIndexes(db)
 }
@@ -443,3 +450,55 @@ func migrateRealmsCompositeSlug(db *sql.DB) error {
     fmt.Printf("[OK] Realms table migrated\n")
     return nil
 }
+
+// migrateSeasonsAddRegion adds region column to seasons table if it doesn't exis
t
+func migrateSeasonsAddRegion(db *sql.DB) error {
+    // Check if region column already exists
+    var createSQL string
+    _ = db.QueryRow(`SELECT sql FROM sqlite_master WHERE type='table' AND name='s
easons'`).Scan(&createSQL)
+
+    // If table already has region column, nothing to do
+    if strings.Contains(strings.ToLower(createSQL), "region text") {
+        return nil
+    }
+
+    fmt.Printf("[MIGRATE] Adding region column to seasons table...\n")
+    tx, err := db.Begin()
+    if err != nil { return err }
+    defer tx.Rollback()
+
+    // Create new table with region column
+    if _, err := tx.Exec(`
+        CREATE TABLE IF NOT EXISTS seasons_new (
+            id INTEGER PRIMARY KEY AUTOINCREMENT,
+            season_number INTEGER NOT NULL,
+            region TEXT NOT NULL,
+            start_timestamp INTEGER,
+            end_timestamp INTEGER,
+            season_name TEXT,
+            first_period_id INTEGER,
+            last_period_id INTEGER,
+            UNIQUE(season_number, region)
+        )
+    `); err != nil { return fmt.Errorf("create seasons_new: %w", err) }
+
+    // Copy existing data, defaulting region to 'us' for backward compatibility
+    if _, err := tx.Exec(`
+        INSERT INTO seasons_new (id, season_number, region, start_timestamp, end_
timestamp, season_name, first_period_id, last_period_id)
+        SELECT id, season_number, 'us', start_timestamp, end_timestamp, season_na
me, first_period_id, last_period_id
+        FROM seasons
+    `); err != nil {
+        return fmt.Errorf("copy seasons: %w", err)
+    }
+
+    // Rename old and new
+    if _, err := tx.Exec(`ALTER TABLE seasons RENAME TO seasons_old`); err != nil
 { return fmt.Errorf("rename old: %w", err) }
+    if _, err := tx.Exec(`ALTER TABLE seasons_new RENAME TO seasons`); err != nil
 { return fmt.Errorf("rename new: %w", err) }
+
+    // Drop old
+    if _, err := tx.Exec(`DROP TABLE seasons_old`); err != nil { return fmt.Error
f("drop old: %w", err) }
+
+    if err := tx.Commit(); err != nil { return err }
+    fmt.Printf("[OK] Seasons table migrated - added region column\n")
+    return nil
+}

diff --git a/nix/pkgs/ookstats/src/internal/
database/client.go b/nix/pkgs/ookstats/src/i
nternal/database/client.go
index 469e4f1..2a94fa6 100644
--- a/nix/pkgs/ookstats/src/internal/databas
e/client.go
+++ b/nix/pkgs/ookstats/src/internal/databas
e/client.go
@@ -324,13 +324,15 @@ func EnsureCompleteSch
ema(db *sql.DB) error {
 
 		// Season tables
 		`CREATE TABLE IF NOT EXISTS seasons (
-			id INTEGER PRIMARY KEY,
-			season_number INTEGER UNIQUE,
+			id INTEGER PRIMARY KEY AUTOINCREMENT,
+			season_number INTEGER NOT NULL,
+			region TEXT NOT NULL,
 			start_timestamp INTEGER,
 			end_timestamp INTEGER,
 			season_name TEXT,
 			first_period_id INTEGER,
-			last_period_id INTEGER
+			last_period_id INTEGER,
+			UNIQUE(season_number, region)
 		)`,
 
 		`CREATE TABLE IF NOT EXISTS period_season
s (
@@ -353,6 +355,11 @@ fmt.Printf("[OK] All ta
bles created\n")
         return err
     }
 
+    // Migrate seasons schema if needed (ad
d region column)
+    if err := migrateSeasonsAddRegion(db); 
err != nil {
+        return err
+    }
+
     // Create indexes
     return ensureRecommendedIndexes(db)
 }
@@ -443,3 +450,55 @@ func migrateRealmsCompo
siteSlug(db *sql.DB) error {
     fmt.Printf("[OK] Realms table migrated\
n")
     return nil
 }
+
+// migrateSeasonsAddRegion adds region colu
mn to seasons table if it doesn't exist
+func migrateSeasonsAddRegion(db *sql.DB) er
ror {
+    // Check if region column already exist
s
+    var createSQL string
+    _ = db.QueryRow(`SELECT sql FROM sqlite
_master WHERE type='table' AND name='seasons
'`).Scan(&createSQL)
+
+    // If table already has region column, 
nothing to do
+    if strings.Contains(strings.ToLower(cre
ateSQL), "region text") {
+        return nil
+    }
+
+    fmt.Printf("[MIGRATE] Adding region col
umn to seasons table...\n")
+    tx, err := db.Begin()
+    if err != nil { return err }
+    defer tx.Rollback()
+
+    // Create new table with region column
+    if _, err := tx.Exec(`
+        CREATE TABLE IF NOT EXISTS seasons_
new (
+            id INTEGER PRIMARY KEY AUTOINCR
EMENT,
+            season_number INTEGER NOT NULL,
+            region TEXT NOT NULL,
+            start_timestamp INTEGER,
+            end_timestamp INTEGER,
+            season_name TEXT,
+            first_period_id INTEGER,
+            last_period_id INTEGER,
+            UNIQUE(season_number, region)
+        )
+    `); err != nil { return fmt.Errorf("cre
ate seasons_new: %w", err) }
+
+    // Copy existing data, defaulting regio
n to 'us' for backward compatibility
+    if _, err := tx.Exec(`
+        INSERT INTO seasons_new (id, season
_number, region, start_timestamp, end_timest
amp, season_name, first_period_id, last_peri
od_id)
+        SELECT id, season_number, 'us', sta
rt_timestamp, end_timestamp, season_name, fi
rst_period_id, last_period_id
+        FROM seasons
+    `); err != nil {
+        return fmt.Errorf("copy seasons: %w
", err)
+    }
+
+    // Rename old and new
+    if _, err := tx.Exec(`ALTER TABLE seaso
ns RENAME TO seasons_old`); err != nil { ret
urn fmt.Errorf("rename old: %w", err) }
+    if _, err := tx.Exec(`ALTER TABLE seaso
ns_new RENAME TO seasons`); err != nil { ret
urn fmt.Errorf("rename new: %w", err) }
+
+    // Drop old
+    if _, err := tx.Exec(`DROP TABLE season
s_old`); err != nil { return fmt.Errorf("dro
p old: %w", err) }
+
+    if err := tx.Commit(); err != nil { ret
urn err }
+    fmt.Printf("[OK] Seasons table migrated
 - added region column\n")
+    return nil
+}
 

diff --git a/nix/pkgs/ookstats/src/internal/database/operations.go b/nix/pkgs/ooks
tats/src/internal/database/operations.go
index 1518169..18675c8 100644
--- a/nix/pkgs/ookstats/src/internal/database/operations.go
+++ b/nix/pkgs/ookstats/src/internal/database/operations.go
@@ -1181,17 +1181,19 @@ func (ds *DatabaseService) insertPlayerEquipmentTx(tx *sql
.Tx, playerID int, equ
 
 // Season management operations
 
-// UpsertSeason inserts or updates a season record
-func (ds *DatabaseService) UpsertSeason(seasonID int, seasonName string, startTim
estamp int64) error {
+// UpsertSeason inserts or updates a season record and returns the auto-increment
 ID
+func (ds *DatabaseService) UpsertSeason(seasonID int, region string, seasonName s
tring, startTimestamp int64) (int, error) {
 	query := `
-		INSERT INTO seasons (id, season_number, season_name, start_timestamp)
+		INSERT INTO seasons (season_number, region, season_name, start_timestamp)
 		VALUES (?, ?, ?, ?)
-		ON CONFLICT(id) DO UPDATE SET
+		ON CONFLICT(season_number, region) DO UPDATE SET
 			season_name = excluded.season_name,
 			start_timestamp = excluded.start_timestamp
+		RETURNING id
 	`
-	_, err := ds.db.Exec(query, seasonID, seasonID, seasonName, startTimestamp)
-	return err
+	var id int
+	err := ds.db.QueryRow(query, seasonID, region, seasonName, startTimestamp).Scan(
&id)
+	return id, err
 }
 
 // UpdateSeasonPeriodRange updates the first_period_id and last_period_id for a s
eason
@@ -1376,6 +1378,32 @@ func (ds *DatabaseService) GetPeriodsForSeason(seasonID int
) ([]int, error) {
 	return periods, rows.Err()
 }
 
+// GetPeriodsForRegion retrieves all period IDs for all seasons in a given region
+func (ds *DatabaseService) GetPeriodsForRegion(region string) ([]int, error) {
+	query := `
+		SELECT DISTINCT ps.period_id
+		FROM period_seasons ps
+		JOIN seasons s ON ps.season_id = s.id
+		WHERE s.region = ?
+		ORDER BY ps.period_id DESC
+	`
+	rows, err := ds.db.Query(query, region)
+	if err != nil {
+		return nil, err
+	}
+	defer rows.Close()
+
+	var periods []int
+	for rows.Next() {
+		var periodID int
+		if err := rows.Scan(&periodID); err != nil {
+			return nil, err
+		}
+		periods = append(periods, periodID)
+	}
+	return periods, rows.Err()
+}
+
 // GetRealmPoolIDs returns all realm IDs in a realm pool (parent + all children)
 // For a child realm, it returns the parent and all siblings
 // For a parent realm, it returns itself and all children

diff --git a/nix/pkgs/ookstats/src/internal/
database/operations.go b/nix/pkgs/ookstats/s
rc/internal/database/operations.go
index 1518169..18675c8 100644
--- a/nix/pkgs/ookstats/src/internal/databas
e/operations.go
+++ b/nix/pkgs/ookstats/src/internal/databas
e/operations.go
@@ -1181,17 +1181,19 @@ func (ds *DatabaseSe
rvice) insertPlayerEquipmentTx(tx *sql.Tx, p
layerID int, equ
 
 // Season management operations
 
-// UpsertSeason inserts or updates a season
 record
-func (ds *DatabaseService) UpsertSeason(sea
sonID int, seasonName string, startTimestamp
 int64) error {
+// UpsertSeason inserts or updates a season
 record and returns the auto-increment ID
+func (ds *DatabaseService) UpsertSeason(sea
sonID int, region string, seasonName string,
 startTimestamp int64) (int, error) {
 	query := `
-		INSERT INTO seasons (id, season_number, s
eason_name, start_timestamp)
+		INSERT INTO seasons (season_number, regio
n, season_name, start_timestamp)
 		VALUES (?, ?, ?, ?)
-		ON CONFLICT(id) DO UPDATE SET
+		ON CONFLICT(season_number, region) DO UPD
ATE SET
 			season_name = excluded.season_name,
 			start_timestamp = excluded.start_timesta
mp
+		RETURNING id
 	`
-	_, err := ds.db.Exec(query, seasonID, seas
onID, seasonName, startTimestamp)
-	return err
+	var id int
+	err := ds.db.QueryRow(query, seasonID, reg
ion, seasonName, startTimestamp).Scan(&id)
+	return id, err
 }
 
 // UpdateSeasonPeriodRange updates the firs
t_period_id and last_period_id for a season
@@ -1376,6 +1378,32 @@ func (ds *DatabaseSer
vice) GetPeriodsForSeason(seasonID int) ([]i
nt, error) {
 	return periods, rows.Err()
 }
 
+// GetPeriodsForRegion retrieves all period
 IDs for all seasons in a given region
+func (ds *DatabaseService) GetPeriodsForReg
ion(region string) ([]int, error) {
+	query := `
+		SELECT DISTINCT ps.period_id
+		FROM period_seasons ps
+		JOIN seasons s ON ps.season_id = s.id
+		WHERE s.region = ?
+		ORDER BY ps.period_id DESC
+	`
+	rows, err := ds.db.Query(query, region)
+	if err != nil {
+		return nil, err
+	}
+	defer rows.Close()
+
+	var periods []int
+	for rows.Next() {
+		var periodID int
+		if err := rows.Scan(&periodID); err != ni
l {
+			return nil, err
+		}
+		periods = append(periods, periodID)
+	}
+	return periods, rows.Err()
+}
+
 // GetRealmPoolIDs returns all realm IDs in
 a realm pool (parent + all children)
 // For a child realm, it returns the parent
 and all siblings
 // For a parent realm, it returns itself an
d all children
 

diff --git a/nix/pkgs/ookstats/src/internal/generator/leaderboards.go b/nix/pkgs/o
okstats/src/internal/generator/leaderboards.go
index 23770be..d616815 100644
--- a/nix/pkgs/ookstats/src/internal/generator/leaderboards.go
+++ b/nix/pkgs/ookstats/src/internal/generator/leaderboards.go
@@ -156,9 +156,13 @@ type seasonInfo struct {
 	Name string
 }
 
-// loadSeasons loads all seasons from the database
+// loadSeasons loads all distinct season numbers from the database
 func loadSeasons(db *sql.DB) ([]seasonInfo, error) {
-	rows, err := db.Query(`SELECT id, season_name FROM seasons ORDER BY start_timest
amp ASC`)
+	rows, err := db.Query(`
+		SELECT DISTINCT season_number, season_name
+		FROM seasons
+		ORDER BY season_number ASC
+	`)
 	if err != nil {
 		return nil, fmt.Errorf("seasons query: %w", err)
 	}

diff --git a/nix/pkgs/ookstats/src/internal/
generator/leaderboards.go b/nix/pkgs/ookstat
s/src/internal/generator/leaderboards.go
index 23770be..d616815 100644
--- a/nix/pkgs/ookstats/src/internal/generat
or/leaderboards.go
+++ b/nix/pkgs/ookstats/src/internal/generat
or/leaderboards.go
@@ -156,9 +156,13 @@ type seasonInfo struct 
{
 	Name string
 }
 
-// loadSeasons loads all seasons from the d
atabase
+// loadSeasons loads all distinct season nu
mbers from the database
 func loadSeasons(db *sql.DB) ([]seasonInfo,
 error) {
-	rows, err := db.Query(`SELECT id, season_n
ame FROM seasons ORDER BY start_timestamp AS
C`)
+	rows, err := db.Query(`
+		SELECT DISTINCT season_number, season_nam
e
+		FROM seasons
+		ORDER BY season_number ASC
+	`)
 	if err != nil {
 		return nil, fmt.Errorf("seasons query: %w
", err)
 	}
 

diff --git a/nix/pkgs/ookstats/src/internal/pipeline/fetch.go b/nix/pkgs/ookstats/
src/internal/pipeline/fetch.go
index f6aa51c..40f743b 100644
--- a/nix/pkgs/ookstats/src/internal/pipeline/fetch.go
+++ b/nix/pkgs/ookstats/src/internal/pipeline/fetch.go
@@ -136,20 +136,33 @@ func FetchChallengeMode(db *database.DatabaseService, client
 *blizzard.Client, o
 
 		// Determine periods for this region
 		var periods []string
-		var err error
 
 		if len(opts.Periods) > 0 {
 			// User-specified periods
 			periods = opts.Periods
 			fmt.Printf("Using user-specified periods: %v (%d periods)\n", periods, len(per
iods))
 		} else {
-			// Fetch periods dynamically from Blizzard API for this region
-			fmt.Printf("Fetching period list dynamically from Blizzard API for %s...\n", s
trings.ToUpper(region))
-			periods, err = client.GetDynamicPeriodList(region)
+			// Fetch periods from database (populated by season sync)
+			fmt.Printf("Fetching period list from database for %s...\n", strings.ToUpper(r
egion))
+			periodInts, err := db.GetPeriodsForRegion(region)
 			if err != nil {
-				fmt.Printf("Failed to fetch period list for %s: %v - skipping region\n", stri
ngs.ToUpper(region), err)
+				fmt.Printf("Failed to fetch periods from database for %s: %v - skipping regio
n\n", strings.ToUpper(region), err)
 				continue
 			}
+
+			// Convert []int to []string for compatibility
+			periods = make([]string, len(periodInts))
+			for i, p := range periodInts {
+				periods[i] = fmt.Sprintf("%d", p)
+			}
+
+			if len(periods) == 0 {
+				fmt.Printf("No periods found in database for %s (run season sync first) - ski
pping region\n", strings.ToUpper(region))
+				continue
+			}
+
+			fmt.Printf("[OK] Fetched %d periods from database for %s (newest: %s, oldest: 
%s)\n",
+				len(periods), strings.ToUpper(region), periods[0], periods[len(periods)-1])
 		}
 
 		if len(periods) == 0 {

diff --git a/nix/pkgs/ookstats/src/internal/
pipeline/fetch.go b/nix/pkgs/ookstats/src/in
ternal/pipeline/fetch.go
index f6aa51c..40f743b 100644
--- a/nix/pkgs/ookstats/src/internal/pipelin
e/fetch.go
+++ b/nix/pkgs/ookstats/src/internal/pipelin
e/fetch.go
@@ -136,20 +136,33 @@ func FetchChallengeMod
e(db *database.DatabaseService, client *bliz
zard.Client, o
 
 		// Determine periods for this region
 		var periods []string
-		var err error
 
 		if len(opts.Periods) > 0 {
 			// User-specified periods
 			periods = opts.Periods
 			fmt.Printf("Using user-specified periods
: %v (%d periods)\n", periods, len(periods))
 		} else {
-			// Fetch periods dynamically from Blizza
rd API for this region
-			fmt.Printf("Fetching period list dynamic
ally from Blizzard API for %s...\n", strings
.ToUpper(region))
-			periods, err = client.GetDynamicPeriodLi
st(region)
+			// Fetch periods from database (populate
d by season sync)
+			fmt.Printf("Fetching period list from da
tabase for %s...\n", strings.ToUpper(region)
)
+			periodInts, err := db.GetPeriodsForRegio
n(region)
 			if err != nil {
-				fmt.Printf("Failed to fetch period list
 for %s: %v - skipping region\n", strings.To
Upper(region), err)
+				fmt.Printf("Failed to fetch periods fro
m database for %s: %v - skipping region\n", 
strings.ToUpper(region), err)
 				continue
 			}
+
+			// Convert []int to []string for compati
bility
+			periods = make([]string, len(periodInts)
)
+			for i, p := range periodInts {
+				periods[i] = fmt.Sprintf("%d", p)
+			}
+
+			if len(periods) == 0 {
+				fmt.Printf("No periods found in databas
e for %s (run season sync first) - skipping 
region\n", strings.ToUpper(region))
+				continue
+			}
+
+			fmt.Printf("[OK] Fetched %d periods from
 database for %s (newest: %s, oldest: %s)\n"
,
+				len(periods), strings.ToUpper(region), 
periods[0], periods[len(periods)-1])
 		}
 
 		if len(periods) == 0 {
 

diff --git a/nix/pkgs/ookstats/src/internal/pipeline/process.go b/nix/pkgs/ookstat
s/src/internal/pipeline/process.go
index 2e503b6..ca980a3 100644
--- a/nix/pkgs/ookstats/src/internal/pipeline/process.go
+++ b/nix/pkgs/ookstats/src/internal/pipeline/process.go
@@ -113,13 +113,19 @@ func ProcessRunRankings(db *sql.DB, opts ProcessRunRankingsO
ptions) error {
 		return fmt.Errorf("failed to compute regional rankings: %w", err)
 	}
 
+	// step 3: compute realm run rankings (pool-based for connected realms)
+	fmt.Println("\n3. Computing realm run rankings (pool-based)...")
+	if err := computeRealmRankings(tx); err != nil {
+		return fmt.Errorf("failed to compute realm rankings: %w", err)
+	}
+
 	// commit all changes
 	if err := tx.Commit(); err != nil {
 		return fmt.Errorf("failed to commit run rankings: %w", err)
 	}
 
 	// optimize database
-	fmt.Println("\n3. Optimizing database...")
+	fmt.Println("\n4. Optimizing database...")
 	if _, err := db.Exec("VACUUM"); err != nil {
 		fmt.Printf("Warning: database optimization failed: %v\n", err)
 	}
@@ -156,7 +162,7 @@ func createPlayerAggregations(tx *sql.Tx) (int, error) {
 			cr.dungeon_id,
 			cr.id as run_id,
 			cr.duration,
-			COALESCE(ps.season_id, 1) as season_id,
+			COALESCE(s_agg.season_number, 1) as season_id,
 			cr.completed_timestamp,
 			rr_gf.ranking as global_ranking_filtered,
 			rr_rf.ranking as regional_ranking_filtered,
@@ -166,31 +172,41 @@ func createPlayerAggregations(tx *sql.Tx) (int, error) {
 			rr_lf.percentile_bracket as realm_percentile_bracket
 		FROM run_members rm
 		INNER JOIN challenge_runs cr ON rm.run_id = cr.id
-		LEFT JOIN period_seasons ps ON cr.period_id = ps.period_id
+		LEFT JOIN (
+			SELECT ps.period_id, MIN(s.season_number) as season_number
+			FROM period_seasons ps
+			JOIN seasons s ON ps.season_id = s.id
+			GROUP BY ps.period_id
+		) s_agg ON cr.period_id = s_agg.period_id
 		INNER JOIN (
 			SELECT
 				rm2.player_id,
 				cr2.dungeon_id,
-				COALESCE(ps2.season_id, 1) as season_id,
+				COALESCE(s2_agg.season_number, 1) as season_id,
 				MIN(cr2.duration) as best_duration
 			FROM run_members rm2
 			INNER JOIN challenge_runs cr2 ON rm2.run_id = cr2.id
-			LEFT JOIN period_seasons ps2 ON cr2.period_id = ps2.period_id
-			GROUP BY rm2.player_id, cr2.dungeon_id, COALESCE(ps2.season_id, 1)
+			LEFT JOIN (
+				SELECT ps.period_id, MIN(s.season_number) as season_number
+				FROM period_seasons ps
+				JOIN seasons s ON ps.season_id = s.id
+				GROUP BY ps.period_id
+			) s2_agg ON cr2.period_id = s2_agg.period_id
+			GROUP BY rm2.player_id, cr2.dungeon_id, COALESCE(s2_agg.season_number, 1)
 		) best_times ON rm.player_id = best_times.player_id
 					 AND cr.dungeon_id = best_times.dungeon_id
-					 AND COALESCE(ps.season_id, 1) = best_times.season_id
+					 AND COALESCE(s_agg.season_number, 1) = best_times.season_id
 					 AND cr.duration = best_times.best_duration
 		LEFT JOIN run_rankings rr_gf ON cr.id = rr_gf.run_id
 			AND rr_gf.ranking_type = 'global' AND rr_gf.ranking_scope = 'filtered'
-			AND rr_gf.season_id = COALESCE(ps.season_id, 1)
+			AND rr_gf.season_id = COALESCE(s_agg.season_number, 1)
 		LEFT JOIN run_rankings rr_rf ON cr.id = rr_rf.run_id
 			AND rr_rf.ranking_type = 'regional' AND rr_rf.ranking_scope = 'filtered'
-			AND rr_rf.season_id = COALESCE(ps.season_id, 1)
+			AND rr_rf.season_id = COALESCE(s_agg.season_number, 1)
 		LEFT JOIN run_rankings rr_lf ON cr.id = rr_lf.run_id
 			AND rr_lf.ranking_type = 'realm' AND rr_lf.ranking_scope = 'filtered'
-			AND rr_lf.season_id = COALESCE(ps.season_id, 1)
-		GROUP BY rm.player_id, cr.dungeon_id, COALESCE(ps.season_id, 1)
+			AND rr_lf.season_id = COALESCE(s_agg.season_number, 1)
+		GROUP BY rm.player_id, cr.dungeon_id, COALESCE(s_agg.season_number, 1)
 		HAVING cr.id = MIN(cr.id)
 	`)
 	if err != nil {
@@ -225,11 +241,16 @@ func createPlayerAggregations(tx *sql.Tx) (int, error) {
 		FROM players p
 		INNER JOIN player_best_runs pbr ON p.id = pbr.player_id
 		INNER JOIN (
-			SELECT rm.player_id, COALESCE(ps.season_id, 1) as season_id, COUNT(*) as run_c
ount
+			SELECT rm.player_id, COALESCE(s_agg.season_number, 1) as season_id, COUNT(*) a
s run_count
 			FROM run_members rm
 			INNER JOIN challenge_runs cr ON rm.run_id = cr.id
-			LEFT JOIN period_seasons ps ON cr.period_id = ps.period_id
-			GROUP BY rm.player_id, COALESCE(ps.season_id, 1)
+			LEFT JOIN (
+				SELECT ps.period_id, MIN(s.season_number) as season_number
+				FROM period_seasons ps
+				JOIN seasons s ON ps.season_id = s.id
+				GROUP BY ps.period_id
+			) s_agg ON cr.period_id = s_agg.period_id
+			GROUP BY rm.player_id, COALESCE(s_agg.season_number, 1)
 		) season_runs ON p.id = season_runs.player_id AND pbr.season_id = season_runs.s
eason_id
 		GROUP BY p.id, pbr.season_id, p.name, p.realm_id, season_runs.run_count
 	`, currentTime)
@@ -278,8 +299,8 @@ func computePlayerRankings(tx *sql.Tx) (int, error) {
 
 	currentTime := time.Now().UnixMilli()
 
-	// Get all seasons
-	seasonRows, err := tx.Query("SELECT DISTINCT season_id FROM player_profiles ORDE
R BY season_id")
+	// Get all distinct season numbers (global seasons across all regions)
+	seasonRows, err := tx.Query("SELECT DISTINCT season_number FROM seasons ORDER BY
 season_number")
 	if err != nil {
 		return 0, fmt.Errorf("failed to query seasons: %w", err)
 	}
@@ -287,11 +308,11 @@ func computePlayerRankings(tx *sql.Tx) (int, error) {
 
 	var seasons []int
 	for seasonRows.Next() {
-		var seasonID int
-		if err := seasonRows.Scan(&seasonID); err != nil {
+		var seasonNumber int
+		if err := seasonRows.Scan(&seasonNumber); err != nil {
 			return 0, err
 		}
-		seasons = append(seasons, seasonID)
+		seasons = append(seasons, seasonNumber)
 	}
 
 	if len(seasons) == 0 {
@@ -547,11 +568,16 @@ func computeGlobalRankings(tx *sql.Tx) error {
 			cr.dungeon_id,
 			'global' as ranking_type,
 			'all' as ranking_scope,
-			ROW_NUMBER() OVER (PARTITION BY cr.dungeon_id, COALESCE(ps.season_id, 1) ORDER
 BY cr.duration ASC, cr.completed_timestamp ASC) as ranking,
-			COALESCE(ps.season_id, 1) as season_id,
+			ROW_NUMBER() OVER (PARTITION BY cr.dungeon_id, COALESCE(s_agg.season_number, 1
) ORDER BY cr.duration ASC, cr.completed_timestamp ASC) as ranking,
+			COALESCE(s_agg.season_number, 1) as season_id,
 			? as computed_at
 		FROM challenge_runs cr
-		LEFT JOIN period_seasons ps ON cr.period_id = ps.period_id
+		LEFT JOIN (
+			SELECT ps.period_id, MIN(s.season_number) as season_number
+			FROM period_seasons ps
+			JOIN seasons s ON ps.season_id = s.id
+			GROUP BY ps.period_id
+		) s_agg ON cr.period_id = s_agg.period_id
 	`, currentTime)
 	if err != nil {
 		return err
@@ -616,7 +642,16 @@ func computeGlobalRankings(tx *sql.Tx) error {
 	}
 
 	// Get all seasons (including fallback season 1 for unmapped periods)
-	seasonRows, err := tx.Query("SELECT DISTINCT COALESCE(ps.season_id, 1) as season
_id FROM challenge_runs cr LEFT JOIN period_seasons ps ON cr.period_id = ps.period
_id")
+	seasonRows, err := tx.Query(`
+		SELECT DISTINCT COALESCE(s_agg.season_number, 1) as season_id
+		FROM challenge_runs cr
+		LEFT JOIN (
+			SELECT ps.period_id, MIN(s.season_number) as season_number
+			FROM period_seasons ps
+			JOIN seasons s ON ps.season_id = s.id
+			GROUP BY ps.period_id
+		) s_agg ON cr.period_id = s_agg.period_id
+	`)
 	if err != nil {
 		return err
 	}
@@ -640,8 +675,13 @@ func computeGlobalRankings(tx *sql.Tx) error {
 						cr.team_signature,
 						MIN(cr.duration) as best_duration
 					FROM challenge_runs cr
-					LEFT JOIN period_seasons ps ON cr.period_id = ps.period_id
-					WHERE cr.dungeon_id = ? AND COALESCE(ps.season_id, 1) = ?
+					LEFT JOIN (
+						SELECT ps.period_id, MIN(s.season_number) as season_number
+						FROM period_seasons ps
+						JOIN seasons s ON ps.season_id = s.id
+						GROUP BY ps.period_id
+					) s_agg ON cr.period_id = s_agg.period_id
+					WHERE cr.dungeon_id = ? AND COALESCE(s_agg.season_number, 1) = ?
 					GROUP BY cr.team_signature
 				),
 				filtered_runs AS (
@@ -651,10 +691,15 @@ func computeGlobalRankings(tx *sql.Tx) error {
 						cr.completed_timestamp,
 						ROW_NUMBER() OVER (ORDER BY cr.duration ASC, cr.completed_timestamp ASC) as
 filtered_rank
 					FROM challenge_runs cr
-					LEFT JOIN period_seasons ps ON cr.period_id = ps.period_id
+					LEFT JOIN (
+						SELECT ps.period_id, MIN(s.season_number) as season_number
+						FROM period_seasons ps
+						JOIN seasons s ON ps.season_id = s.id
+						GROUP BY ps.period_id
+					) s_agg ON cr.period_id = s_agg.period_id
 					INNER JOIN best_team_runs btr ON cr.team_signature = btr.team_signature
 												 AND cr.duration = btr.best_duration
-					WHERE cr.dungeon_id = ? AND COALESCE(ps.season_id, 1) = ?
+					WHERE cr.dungeon_id = ? AND COALESCE(s_agg.season_number, 1) = ?
 					GROUP BY cr.team_signature
 					HAVING cr.id = MIN(cr.id)
 				)
@@ -757,12 +802,17 @@ func computeRegionalRankings(tx *sql.Tx) error {
 				cr.dungeon_id,
 				'regional' as ranking_type,
 				? as ranking_scope,
-				ROW_NUMBER() OVER (PARTITION BY cr.dungeon_id, COALESCE(ps.season_id, 1) ORDE
R BY cr.duration ASC, cr.completed_timestamp ASC) as ranking,
-				COALESCE(ps.season_id, 1) as season_id,
+				ROW_NUMBER() OVER (PARTITION BY cr.dungeon_id, COALESCE(s_agg.season_number, 
1) ORDER BY cr.duration ASC, cr.completed_timestamp ASC) as ranking,
+				COALESCE(s_agg.season_number, 1) as season_id,
 				? as computed_at
 			FROM challenge_runs cr
 			INNER JOIN realms r ON cr.realm_id = r.id
-			LEFT JOIN period_seasons ps ON cr.period_id = ps.period_id
+			LEFT JOIN (
+				SELECT ps.period_id, MIN(s.season_number) as season_number
+				FROM period_seasons ps
+				JOIN seasons s ON ps.season_id = s.id
+				GROUP BY ps.period_id
+			) s_agg ON cr.period_id = s_agg.period_id
 			WHERE r.region = ?
 		`, region, currentTime, region)
 
@@ -830,10 +880,15 @@ func computeRegionalRankings(tx *sql.Tx) error {
 
 		// Get all seasons for this region
 		seasonRows, err := tx.Query(`
-			SELECT DISTINCT COALESCE(ps.season_id, 1) as season_id
+			SELECT DISTINCT COALESCE(s_agg.season_number, 1) as season_id
 			FROM challenge_runs cr
 			INNER JOIN realms r ON cr.realm_id = r.id
-			LEFT JOIN period_seasons ps ON cr.period_id = ps.period_id
+			LEFT JOIN (
+				SELECT ps.period_id, MIN(s.season_number) as season_number
+				FROM period_seasons ps
+				JOIN seasons s ON ps.season_id = s.id
+				GROUP BY ps.period_id
+			) s_agg ON cr.period_id = s_agg.period_id
 			WHERE r.region = ?
 		`, region)
 		if err != nil {
@@ -861,8 +916,13 @@ func computeRegionalRankings(tx *sql.Tx) error {
 							MIN(cr.duration) as best_duration
 						FROM challenge_runs cr
 						INNER JOIN realms r ON cr.realm_id = r.id
-						LEFT JOIN period_seasons ps ON cr.period_id = ps.period_id
-						WHERE cr.dungeon_id = ? AND r.region = ? AND COALESCE(ps.season_id, 1) = ?
+						LEFT JOIN (
+							SELECT ps.period_id, MIN(s.season_number) as season_number
+							FROM period_seasons ps
+							JOIN seasons s ON ps.season_id = s.id
+							GROUP BY ps.period_id
+						) s_agg ON cr.period_id = s_agg.period_id
+						WHERE cr.dungeon_id = ? AND r.region = ? AND COALESCE(s_agg.season_number, 
1) = ?
 						GROUP BY cr.team_signature
 					),
 					filtered_runs AS (
@@ -873,10 +933,15 @@ func computeRegionalRankings(tx *sql.Tx) error {
 							ROW_NUMBER() OVER (ORDER BY cr.duration ASC, cr.completed_timestamp ASC) a
s filtered_rank
 						FROM challenge_runs cr
 						INNER JOIN realms r ON cr.realm_id = r.id
-						LEFT JOIN period_seasons ps ON cr.period_id = ps.period_id
+						LEFT JOIN (
+							SELECT ps.period_id, MIN(s.season_number) as season_number
+							FROM period_seasons ps
+							JOIN seasons s ON ps.season_id = s.id
+							GROUP BY ps.period_id
+						) s_agg ON cr.period_id = s_agg.period_id
 						INNER JOIN best_team_runs btr ON cr.team_signature = btr.team_signature
 														AND cr.duration = btr.best_duration
-						WHERE cr.dungeon_id = ? AND r.region = ? AND COALESCE(ps.season_id, 1) = ?
+						WHERE cr.dungeon_id = ? AND r.region = ? AND COALESCE(s_agg.season_number, 
1) = ?
 						GROUP BY cr.team_signature
 						HAVING cr.id = MIN(cr.id)
 					)
@@ -944,3 +1009,276 @@ func computeRegionalRankings(tx *sql.Tx) error {
 	fmt.Printf("[OK] Computed regional rankings with percentile brackets for %d regi
ons\n", len(regions))
 	return nil
 }
+
+// computeRealmRankings computes realm rankings per realm pool (connected realms 
grouped together)
+func computeRealmRankings(tx *sql.Tx) error {
+	fmt.Printf("Computing realm rankings (pool-based for connected realms)...\n")
+
+	currentTime := time.Now().UnixMilli()
+
+	// clear existing realm rankings
+	if _, err := tx.Exec("DELETE FROM run_rankings WHERE ranking_type = 'realm'"); e
rr != nil {
+		return err
+	}
+
+	// get all realm pools (parent realms or independent realms that will be used as
 pool identifiers)
+	type RealmPool struct {
+		PoolSlug string
+		Region   string
+	}
+
+	poolRows, err := tx.Query(`
+		SELECT DISTINCT
+			COALESCE(parent_r.slug, r.slug) as pool_slug,
+			r.region
+		FROM realms r
+		LEFT JOIN realms parent_r ON r.parent_realm_slug = parent_r.slug AND r.region =
 parent_r.region
+		ORDER BY r.region, pool_slug
+	`)
+	if err != nil {
+		return err
+	}
+	defer poolRows.Close()
+
+	var pools []RealmPool
+	for poolRows.Next() {
+		var pool RealmPool
+		if err := poolRows.Scan(&pool.PoolSlug, &pool.Region); err != nil {
+			return err
+		}
+		pools = append(pools, pool)
+	}
+
+	fmt.Printf("Found %d realm pools to process\n", len(pools))
+
+	for _, pool := range pools {
+		// unfiltered realm rankings (per season) using pool-based partitioning
+		_, err := tx.Exec(`
+			INSERT INTO run_rankings (run_id, dungeon_id, ranking_type, ranking_scope, ran
king, season_id, computed_at)
+			SELECT
+				cr.id as run_id,
+				cr.dungeon_id,
+				'realm' as ranking_type,
+				? as ranking_scope,
+				ROW_NUMBER() OVER (
+					PARTITION BY cr.dungeon_id, COALESCE(s_agg.season_number, 1)
+					ORDER BY cr.duration ASC, cr.completed_timestamp ASC
+				) as ranking,
+				COALESCE(s_agg.season_number, 1) as season_id,
+				? as computed_at
+			FROM challenge_runs cr
+			INNER JOIN realms r ON cr.realm_id = r.id
+			LEFT JOIN realms parent_r ON r.parent_realm_slug = parent_r.slug AND r.region 
= parent_r.region
+			LEFT JOIN (
+				SELECT ps.period_id, MIN(s.season_number) as season_number
+				FROM period_seasons ps
+				JOIN seasons s ON ps.season_id = s.id
+				GROUP BY ps.period_id
+			) s_agg ON cr.period_id = s_agg.period_id
+			WHERE r.region = ? AND COALESCE(parent_r.slug, r.slug) = ?
+		`, pool.PoolSlug, currentTime, pool.Region, pool.PoolSlug)
+
+		if err != nil {
+			return err
+		}
+
+		// update percentile brackets for unfiltered realm rankings
+		_, err = tx.Exec(`
+			UPDATE run_rankings
+			SET percentile_bracket = (
+				CASE
+					WHEN counts.duration = counts.min_duration THEN 'artifact'
+					ELSE
+						CASE
+							WHEN (CAST(counts.ranking AS REAL) / CAST(counts.total_in_pool_season_dung
eon AS REAL) * 100) <= 1.0 THEN 'excellent'
+							WHEN (CAST(counts.ranking AS REAL) / CAST(counts.total_in_pool_season_dung
eon AS REAL) * 100) <= 5.0 THEN 'legendary'
+							WHEN (CAST(counts.ranking AS REAL) / CAST(counts.total_in_pool_season_dung
eon AS REAL) * 100) <= 20.0 THEN 'epic'
+							WHEN (CAST(counts.ranking AS REAL) / CAST(counts.total_in_pool_season_dung
eon AS REAL) * 100) <= 40.0 THEN 'rare'
+							WHEN (CAST(counts.ranking AS REAL) / CAST(counts.total_in_pool_season_dung
eon AS REAL) * 100) <= 60.0 THEN 'uncommon'
+							ELSE 'common'
+						END
+				END
+			)
+			FROM (
+				SELECT
+					rr.run_id,
+					rr.dungeon_id,
+					rr.season_id,
+					rr.ranking,
+					cr.duration,
+					MIN(cr.duration) OVER (PARTITION BY rr.dungeon_id, rr.season_id, rr.ranking_
scope) as min_duration,
+					COUNT(*) OVER (PARTITION BY rr.dungeon_id, rr.season_id, rr.ranking_scope) a
s total_in_pool_season_dungeon
+				FROM run_rankings rr
+				INNER JOIN challenge_runs cr ON rr.run_id = cr.id
+				WHERE rr.ranking_type = 'realm' AND rr.ranking_scope = ?
+			) counts
+			WHERE run_rankings.run_id = counts.run_id
+			AND run_rankings.dungeon_id = counts.dungeon_id
+			AND run_rankings.season_id = counts.season_id
+			AND run_rankings.ranking_type = 'realm'
+			AND run_rankings.ranking_scope = ?
+		`, pool.PoolSlug, pool.PoolSlug)
+		if err != nil {
+			return err
+		}
+	}
+
+	// now compute filtered rankings per pool x dungeon x season
+	dungeonRows, err := tx.Query("SELECT id FROM dungeons")
+	if err != nil {
+		return err
+	}
+
+	var dungeonIDs []int
+	for dungeonRows.Next() {
+		var id int
+		if err := dungeonRows.Scan(&id); err != nil {
+			dungeonRows.Close()
+			return err
+		}
+		dungeonIDs = append(dungeonIDs, id)
+	}
+	dungeonRows.Close()
+
+	for _, pool := range pools {
+		// Get seasons for this pool
+		seasonRows, err := tx.Query(`
+			SELECT DISTINCT COALESCE(s_agg.season_number, 1) as season_id
+			FROM challenge_runs cr
+			INNER JOIN realms r ON cr.realm_id = r.id
+			LEFT JOIN realms parent_r ON r.parent_realm_slug = parent_r.slug AND r.region 
= parent_r.region
+			LEFT JOIN (
+				SELECT ps.period_id, MIN(s.season_number) as season_number
+				FROM period_seasons ps
+				JOIN seasons s ON ps.season_id = s.id
+				GROUP BY ps.period_id
+			) s_agg ON cr.period_id = s_agg.period_id
+			WHERE r.region = ? AND COALESCE(parent_r.slug, r.slug) = ?
+		`, pool.Region, pool.PoolSlug)
+		if err != nil {
+			return err
+		}
+
+		var seasonIDs []int
+		for seasonRows.Next() {
+			var id int
+			if err := seasonRows.Scan(&id); err != nil {
+				seasonRows.Close()
+				return err
+			}
+			seasonIDs = append(seasonIDs, id)
+		}
+		seasonRows.Close()
+
+		// filtered realm rankings - per dungeon x season using pool-based partitioning
+		for _, dungeonID := range dungeonIDs {
+			for _, seasonID := range seasonIDs {
+				_, err := tx.Exec(`
+					WITH best_team_runs AS (
+						SELECT
+							cr.team_signature,
+							MIN(cr.duration) as best_duration
+						FROM challenge_runs cr
+						INNER JOIN realms r ON cr.realm_id = r.id
+						LEFT JOIN realms parent_r ON r.parent_realm_slug = parent_r.slug AND r.regi
on = parent_r.region
+						LEFT JOIN (
+							SELECT ps.period_id, MIN(s.season_number) as season_number
+							FROM period_seasons ps
+							JOIN seasons s ON ps.season_id = s.id
+							GROUP BY ps.period_id
+						) s_agg ON cr.period_id = s_agg.period_id
+						WHERE cr.dungeon_id = ?
+							AND r.region = ?
+							AND COALESCE(parent_r.slug, r.slug) = ?
+							AND COALESCE(s_agg.season_number, 1) = ?
+						GROUP BY cr.team_signature
+					),
+					filtered_runs AS (
+						SELECT
+							cr.id as run_id,
+							cr.duration,
+							cr.completed_timestamp,
+							ROW_NUMBER() OVER (ORDER BY cr.duration ASC, cr.completed_timestamp ASC) a
s filtered_rank
+						FROM challenge_runs cr
+						INNER JOIN realms r ON cr.realm_id = r.id
+						LEFT JOIN realms parent_r ON r.parent_realm_slug = parent_r.slug AND r.regi
on = parent_r.region
+						LEFT JOIN (
+							SELECT ps.period_id, MIN(s.season_number) as season_number
+							FROM period_seasons ps
+							JOIN seasons s ON ps.season_id = s.id
+							GROUP BY ps.period_id
+						) s_agg ON cr.period_id = s_agg.period_id
+						INNER JOIN best_team_runs btr ON cr.team_signature = btr.team_signature
+														AND cr.duration = btr.best_duration
+						WHERE cr.dungeon_id = ?
+							AND r.region = ?
+							AND COALESCE(parent_r.slug, r.slug) = ?
+							AND COALESCE(s_agg.season_number, 1) = ?
+						GROUP BY cr.team_signature
+						HAVING cr.id = MIN(cr.id)
+					)
+					INSERT INTO run_rankings (run_id, dungeon_id, ranking_type, ranking_scope, r
anking, season_id, computed_at)
+					SELECT
+						run_id,
+						? as dungeon_id,
+						'realm' as ranking_type,
+						? as ranking_scope,
+						filtered_rank as ranking,
+						? as season_id,
+						? as computed_at
+					FROM filtered_runs
+				`, dungeonID, pool.Region, pool.PoolSlug, seasonID,
+					dungeonID, pool.Region, pool.PoolSlug, seasonID,
+					dungeonID, pool.PoolSlug+"_filtered", seasonID, currentTime)
+
+				if err != nil {
+					return err
+				}
+			}
+		}
+
+		// update percentile brackets for filtered realm rankings
+		filteredScope := pool.PoolSlug + "_filtered"
+		_, err = tx.Exec(`
+			UPDATE run_rankings
+			SET percentile_bracket = (
+				CASE
+					WHEN counts.duration = counts.min_duration THEN 'artifact'
+					ELSE
+						CASE
+							WHEN (CAST(counts.ranking AS REAL) / CAST(counts.total_in_pool_season_dung
eon AS REAL) * 100) <= 1.0 THEN 'excellent'
+							WHEN (CAST(counts.ranking AS REAL) / CAST(counts.total_in_pool_season_dung
eon AS REAL) * 100) <= 5.0 THEN 'legendary'
+							WHEN (CAST(counts.ranking AS REAL) / CAST(counts.total_in_pool_season_dung
eon AS REAL) * 100) <= 20.0 THEN 'epic'
+							WHEN (CAST(counts.ranking AS REAL) / CAST(counts.total_in_pool_season_dung
eon AS REAL) * 100) <= 40.0 THEN 'rare'
+							WHEN (CAST(counts.ranking AS REAL) / CAST(counts.total_in_pool_season_dung
eon AS REAL) * 100) <= 60.0 THEN 'uncommon'
+							ELSE 'common'
+						END
+				END
+			)
+			FROM (
+				SELECT
+					rr.run_id,
+					rr.dungeon_id,
+					rr.season_id,
+					rr.ranking,
+					cr.duration,
+					MIN(cr.duration) OVER (PARTITION BY rr.dungeon_id, rr.season_id, rr.ranking_
scope) as min_duration,
+					COUNT(*) OVER (PARTITION BY rr.dungeon_id, rr.season_id, rr.ranking_scope) a
s total_in_pool_season_dungeon
+				FROM run_rankings rr
+				INNER JOIN challenge_runs cr ON rr.run_id = cr.id
+				WHERE rr.ranking_type = 'realm' AND rr.ranking_scope = ?
+			) counts
+			WHERE run_rankings.run_id = counts.run_id
+			AND run_rankings.dungeon_id = counts.dungeon_id
+			AND run_rankings.season_id = counts.season_id
+			AND run_rankings.ranking_type = 'realm'
+			AND run_rankings.ranking_scope = ?
+		`, filteredScope, filteredScope)
+		if err != nil {
+			return err
+		}
+	}
+
+	fmt.Printf("[OK] Computed realm rankings with percentile brackets for %d realm p
ools\n", len(pools))
+	return nil
+}

diff --git a/nix/pkgs/ookstats/src/internal/
pipeline/process.go b/nix/pkgs/ookstats/src/
internal/pipeline/process.go
index 2e503b6..ca980a3 100644
--- a/nix/pkgs/ookstats/src/internal/pipelin
e/process.go
+++ b/nix/pkgs/ookstats/src/internal/pipelin
e/process.go
@@ -113,13 +113,19 @@ func ProcessRunRanking
s(db *sql.DB, opts ProcessRunRankingsOptions
) error {
 		return fmt.Errorf("failed to compute regi
onal rankings: %w", err)
 	}
 
+	// step 3: compute realm run rankings (poo
l-based for connected realms)
+	fmt.Println("\n3. Computing realm run rank
ings (pool-based)...")
+	if err := computeRealmRankings(tx); err !=
 nil {
+		return fmt.Errorf("failed to compute real
m rankings: %w", err)
+	}
+
 	// commit all changes
 	if err := tx.Commit(); err != nil {
 		return fmt.Errorf("failed to commit run r
ankings: %w", err)
 	}
 
 	// optimize database
-	fmt.Println("\n3. Optimizing database...")
+	fmt.Println("\n4. Optimizing database...")
 	if _, err := db.Exec("VACUUM"); err != nil
 {
 		fmt.Printf("Warning: database optimizatio
n failed: %v\n", err)
 	}
@@ -156,7 +162,7 @@ func createPlayerAggrega
tions(tx *sql.Tx) (int, error) {
 			cr.dungeon_id,
 			cr.id as run_id,
 			cr.duration,
-			COALESCE(ps.season_id, 1) as season_id,
+			COALESCE(s_agg.season_number, 1) as seas
on_id,
 			cr.completed_timestamp,
 			rr_gf.ranking as global_ranking_filtered
,
 			rr_rf.ranking as regional_ranking_filter
ed,
@@ -166,31 +172,41 @@ func createPlayerAggre
gations(tx *sql.Tx) (int, error) {
 			rr_lf.percentile_bracket as realm_percen
tile_bracket
 		FROM run_members rm
 		INNER JOIN challenge_runs cr ON rm.run_id
 = cr.id
-		LEFT JOIN period_seasons ps ON cr.period_
id = ps.period_id
+		LEFT JOIN (
+			SELECT ps.period_id, MIN(s.season_number
) as season_number
+			FROM period_seasons ps
+			JOIN seasons s ON ps.season_id = s.id
+			GROUP BY ps.period_id
+		) s_agg ON cr.period_id = s_agg.period_id
 		INNER JOIN (
 			SELECT
 				rm2.player_id,
 				cr2.dungeon_id,
-				COALESCE(ps2.season_id, 1) as season_id
,
+				COALESCE(s2_agg.season_number, 1) as se
ason_id,
 				MIN(cr2.duration) as best_duration
 			FROM run_members rm2
 			INNER JOIN challenge_runs cr2 ON rm2.run
_id = cr2.id
-			LEFT JOIN period_seasons ps2 ON cr2.peri
od_id = ps2.period_id
-			GROUP BY rm2.player_id, cr2.dungeon_id, 
COALESCE(ps2.season_id, 1)
+			LEFT JOIN (
+				SELECT ps.period_id, MIN(s.season_numbe
r) as season_number
+				FROM period_seasons ps
+				JOIN seasons s ON ps.season_id = s.id
+				GROUP BY ps.period_id
+			) s2_agg ON cr2.period_id = s2_agg.perio
d_id
+			GROUP BY rm2.player_id, cr2.dungeon_id, 
COALESCE(s2_agg.season_number, 1)
 		) best_times ON rm.player_id = best_times
.player_id
 					 AND cr.dungeon_id = best_times.dungeo
n_id
-					 AND COALESCE(ps.season_id, 1) = best_
times.season_id
+					 AND COALESCE(s_agg.season_number, 1) 
= best_times.season_id
 					 AND cr.duration = best_times.best_dur
ation
 		LEFT JOIN run_rankings rr_gf ON cr.id = r
r_gf.run_id
 			AND rr_gf.ranking_type = 'global' AND rr
_gf.ranking_scope = 'filtered'
-			AND rr_gf.season_id = COALESCE(ps.season
_id, 1)
+			AND rr_gf.season_id = COALESCE(s_agg.sea
son_number, 1)
 		LEFT JOIN run_rankings rr_rf ON cr.id = r
r_rf.run_id
 			AND rr_rf.ranking_type = 'regional' AND 
rr_rf.ranking_scope = 'filtered'
-			AND rr_rf.season_id = COALESCE(ps.season
_id, 1)
+			AND rr_rf.season_id = COALESCE(s_agg.sea
son_number, 1)
 		LEFT JOIN run_rankings rr_lf ON cr.id = r
r_lf.run_id
 			AND rr_lf.ranking_type = 'realm' AND rr_
lf.ranking_scope = 'filtered'
-			AND rr_lf.season_id = COALESCE(ps.season
_id, 1)
-		GROUP BY rm.player_id, cr.dungeon_id, COA
LESCE(ps.season_id, 1)
+			AND rr_lf.season_id = COALESCE(s_agg.sea
son_number, 1)
+		GROUP BY rm.player_id, cr.dungeon_id, COA
LESCE(s_agg.season_number, 1)
 		HAVING cr.id = MIN(cr.id)
 	`)
 	if err != nil {
@@ -225,11 +241,16 @@ func createPlayerAggre
gations(tx *sql.Tx) (int, error) {
 		FROM players p
 		INNER JOIN player_best_runs pbr ON p.id =
 pbr.player_id
 		INNER JOIN (
-			SELECT rm.player_id, COALESCE(ps.season_
id, 1) as season_id, COUNT(*) as run_count
+			SELECT rm.player_id, COALESCE(s_agg.seas
on_number, 1) as season_id, COUNT(*) as run_
count
 			FROM run_members rm
 			INNER JOIN challenge_runs cr ON rm.run_i
d = cr.id
-			LEFT JOIN period_seasons ps ON cr.period
_id = ps.period_id
-			GROUP BY rm.player_id, COALESCE(ps.seaso
n_id, 1)
+			LEFT JOIN (
+				SELECT ps.period_id, MIN(s.season_numbe
r) as season_number
+				FROM period_seasons ps
+				JOIN seasons s ON ps.season_id = s.id
+				GROUP BY ps.period_id
+			) s_agg ON cr.period_id = s_agg.period_i
d
+			GROUP BY rm.player_id, COALESCE(s_agg.se
ason_number, 1)
 		) season_runs ON p.id = season_runs.playe
r_id AND pbr.season_id = season_runs.season_
id
 		GROUP BY p.id, pbr.season_id, p.name, p.r
ealm_id, season_runs.run_count
 	`, currentTime)
@@ -278,8 +299,8 @@ func computePlayerRankin
gs(tx *sql.Tx) (int, error) {
 
 	currentTime := time.Now().UnixMilli()
 
-	// Get all seasons
-	seasonRows, err := tx.Query("SELECT DISTIN
CT season_id FROM player_profiles ORDER BY s
eason_id")
+	// Get all distinct season numbers (global
 seasons across all regions)
+	seasonRows, err := tx.Query("SELECT DISTIN
CT season_number FROM seasons ORDER BY seaso
n_number")
 	if err != nil {
 		return 0, fmt.Errorf("failed to query sea
sons: %w", err)
 	}
@@ -287,11 +308,11 @@ func computePlayerRank
ings(tx *sql.Tx) (int, error) {
 
 	var seasons []int
 	for seasonRows.Next() {
-		var seasonID int
-		if err := seasonRows.Scan(&seasonID); err
 != nil {
+		var seasonNumber int
+		if err := seasonRows.Scan(&seasonNumber);
 err != nil {
 			return 0, err
 		}
-		seasons = append(seasons, seasonID)
+		seasons = append(seasons, seasonNumber)
 	}
 
 	if len(seasons) == 0 {
@@ -547,11 +568,16 @@ func computeGlobalRank
ings(tx *sql.Tx) error {
 			cr.dungeon_id,
 			'global' as ranking_type,
 			'all' as ranking_scope,
-			ROW_NUMBER() OVER (PARTITION BY cr.dunge
on_id, COALESCE(ps.season_id, 1) ORDER BY cr
.duration ASC, cr.completed_timestamp ASC) a
s ranking,
-			COALESCE(ps.season_id, 1) as season_id,
+			ROW_NUMBER() OVER (PARTITION BY cr.dunge
on_id, COALESCE(s_agg.season_number, 1) ORDE
R BY cr.duration ASC, cr.completed_timestamp
 ASC) as ranking,
+			COALESCE(s_agg.season_number, 1) as seas
on_id,
 			? as computed_at
 		FROM challenge_runs cr
-		LEFT JOIN period_seasons ps ON cr.period_
id = ps.period_id
+		LEFT JOIN (
+			SELECT ps.period_id, MIN(s.season_number
) as season_number
+			FROM period_seasons ps
+			JOIN seasons s ON ps.season_id = s.id
+			GROUP BY ps.period_id
+		) s_agg ON cr.period_id = s_agg.period_id
 	`, currentTime)
 	if err != nil {
 		return err
@@ -616,7 +642,16 @@ func computeGlobalRanki
ngs(tx *sql.Tx) error {
 	}
 
 	// Get all seasons (including fallback sea
son 1 for unmapped periods)
-	seasonRows, err := tx.Query("SELECT DISTIN
CT COALESCE(ps.season_id, 1) as season_id FR
OM challenge_runs cr LEFT JOIN period_season
s ps ON cr.period_id = ps.period_id")
+	seasonRows, err := tx.Query(`
+		SELECT DISTINCT COALESCE(s_agg.season_num
ber, 1) as season_id
+		FROM challenge_runs cr
+		LEFT JOIN (
+			SELECT ps.period_id, MIN(s.season_number
) as season_number
+			FROM period_seasons ps
+			JOIN seasons s ON ps.season_id = s.id
+			GROUP BY ps.period_id
+		) s_agg ON cr.period_id = s_agg.period_id
+	`)
 	if err != nil {
 		return err
 	}
@@ -640,8 +675,13 @@ func computeGlobalRanki
ngs(tx *sql.Tx) error {
 						cr.team_signature,
 						MIN(cr.duration) as best_duration
 					FROM challenge_runs cr
-					LEFT JOIN period_seasons ps ON cr.peri
od_id = ps.period_id
-					WHERE cr.dungeon_id = ? AND COALESCE(p
s.season_id, 1) = ?
+					LEFT JOIN (
+						SELECT ps.period_id, MIN(s.season_num
ber) as season_number
+						FROM period_seasons ps
+						JOIN seasons s ON ps.season_id = s.id
+						GROUP BY ps.period_id
+					) s_agg ON cr.period_id = s_agg.period
_id
+					WHERE cr.dungeon_id = ? AND COALESCE(s
_agg.season_number, 1) = ?
 					GROUP BY cr.team_signature
 				),
 				filtered_runs AS (
@@ -651,10 +691,15 @@ func computeGlobalRank
ings(tx *sql.Tx) error {
 						cr.completed_timestamp,
 						ROW_NUMBER() OVER (ORDER BY cr.durati
on ASC, cr.completed_timestamp ASC) as filte
red_rank
 					FROM challenge_runs cr
-					LEFT JOIN period_seasons ps ON cr.peri
od_id = ps.period_id
+					LEFT JOIN (
+						SELECT ps.period_id, MIN(s.season_num
ber) as season_number
+						FROM period_seasons ps
+						JOIN seasons s ON ps.season_id = s.id
+						GROUP BY ps.period_id
+					) s_agg ON cr.period_id = s_agg.period
_id
 					INNER JOIN best_team_runs btr ON cr.te
am_signature = btr.team_signature
 												 AND cr.duration = btr.best_dur
ation
-					WHERE cr.dungeon_id = ? AND COALESCE(p
s.season_id, 1) = ?
+					WHERE cr.dungeon_id = ? AND COALESCE(s
_agg.season_number, 1) = ?
 					GROUP BY cr.team_signature
 					HAVING cr.id = MIN(cr.id)
 				)
@@ -757,12 +802,17 @@ func computeRegionalRa
nkings(tx *sql.Tx) error {
 				cr.dungeon_id,
 				'regional' as ranking_type,
 				? as ranking_scope,
-				ROW_NUMBER() OVER (PARTITION BY cr.dung
eon_id, COALESCE(ps.season_id, 1) ORDER BY c
r.duration ASC, cr.completed_timestamp ASC) 
as ranking,
-				COALESCE(ps.season_id, 1) as season_id,
+				ROW_NUMBER() OVER (PARTITION BY cr.dung
eon_id, COALESCE(s_agg.season_number, 1) ORD
ER BY cr.duration ASC, cr.completed_timestam
p ASC) as ranking,
+				COALESCE(s_agg.season_number, 1) as sea
son_id,
 				? as computed_at
 			FROM challenge_runs cr
 			INNER JOIN realms r ON cr.realm_id = r.i
d
-			LEFT JOIN period_seasons ps ON cr.period
_id = ps.period_id
+			LEFT JOIN (
+				SELECT ps.period_id, MIN(s.season_numbe
r) as season_number
+				FROM period_seasons ps
+				JOIN seasons s ON ps.season_id = s.id
+				GROUP BY ps.period_id
+			) s_agg ON cr.period_id = s_agg.period_i
d
 			WHERE r.region = ?
 		`, region, currentTime, region)
 
@@ -830,10 +880,15 @@ func computeRegionalRa
nkings(tx *sql.Tx) error {
 
 		// Get all seasons for this region
 		seasonRows, err := tx.Query(`
-			SELECT DISTINCT COALESCE(ps.season_id, 1
) as season_id
+			SELECT DISTINCT COALESCE(s_agg.season_nu
mber, 1) as season_id
 			FROM challenge_runs cr
 			INNER JOIN realms r ON cr.realm_id = r.i
d
-			LEFT JOIN period_seasons ps ON cr.period
_id = ps.period_id
+			LEFT JOIN (
+				SELECT ps.period_id, MIN(s.season_numbe
r) as season_number
+				FROM period_seasons ps
+				JOIN seasons s ON ps.season_id = s.id
+				GROUP BY ps.period_id
+			) s_agg ON cr.period_id = s_agg.period_i
d
 			WHERE r.region = ?
 		`, region)
 		if err != nil {
@@ -861,8 +916,13 @@ func computeRegionalRan
kings(tx *sql.Tx) error {
 							MIN(cr.duration) as best_duration
 						FROM challenge_runs cr
 						INNER JOIN realms r ON cr.realm_id = 
r.id
-						LEFT JOIN period_seasons ps ON cr.per
iod_id = ps.period_id
-						WHERE cr.dungeon_id = ? AND r.region 
= ? AND COALESCE(ps.season_id, 1) = ?
+						LEFT JOIN (
+							SELECT ps.period_id, MIN(s.season_nu
mber) as season_number
+							FROM period_seasons ps
+							JOIN seasons s ON ps.season_id = s.i
d
+							GROUP BY ps.period_id
+						) s_agg ON cr.period_id = s_agg.perio
d_id
+						WHERE cr.dungeon_id = ? AND r.region 
= ? AND COALESCE(s_agg.season_number, 1) = ?
 						GROUP BY cr.team_signature
 					),
 					filtered_runs AS (
@@ -873,10 +933,15 @@ func computeRegionalRa
nkings(tx *sql.Tx) error {
 							ROW_NUMBER() OVER (ORDER BY cr.durat
ion ASC, cr.completed_timestamp ASC) as filt
ered_rank
 						FROM challenge_runs cr
 						INNER JOIN realms r ON cr.realm_id = 
r.id
-						LEFT JOIN period_seasons ps ON cr.per
iod_id = ps.period_id
+						LEFT JOIN (
+							SELECT ps.period_id, MIN(s.season_nu
mber) as season_number
+							FROM period_seasons ps
+							JOIN seasons s ON ps.season_id = s.i
d
+							GROUP BY ps.period_id
+						) s_agg ON cr.period_id = s_agg.perio
d_id
 						INNER JOIN best_team_runs btr ON cr.t
eam_signature = btr.team_signature
 														AND cr.duration = btr.best_du
ration
-						WHERE cr.dungeon_id = ? AND r.region 
= ? AND COALESCE(ps.season_id, 1) = ?
+						WHERE cr.dungeon_id = ? AND r.region 
= ? AND COALESCE(s_agg.season_number, 1) = ?
 						GROUP BY cr.team_signature
 						HAVING cr.id = MIN(cr.id)
 					)
@@ -944,3 +1009,276 @@ func computeRegionalR
ankings(tx *sql.Tx) error {
 	fmt.Printf("[OK] Computed regional ranking
s with percentile brackets for %d regions\n"
, len(regions))
 	return nil
 }
+
+// computeRealmRankings computes realm rank
ings per realm pool (connected realms groupe
d together)
+func computeRealmRankings(tx *sql.Tx) error
 {
+	fmt.Printf("Computing realm rankings (pool
-based for connected realms)...\n")
+
+	currentTime := time.Now().UnixMilli()
+
+	// clear existing realm rankings
+	if _, err := tx.Exec("DELETE FROM run_rank
ings WHERE ranking_type = 'realm'"); err != 
nil {
+		return err
+	}
+
+	// get all realm pools (parent realms or i
ndependent realms that will be used as pool 
identifiers)
+	type RealmPool struct {
+		PoolSlug string
+		Region   string
+	}
+
+	poolRows, err := tx.Query(`
+		SELECT DISTINCT
+			COALESCE(parent_r.slug, r.slug) as pool_
slug,
+			r.region
+		FROM realms r
+		LEFT JOIN realms parent_r ON r.parent_rea
lm_slug = parent_r.slug AND r.region = paren
t_r.region
+		ORDER BY r.region, pool_slug
+	`)
+	if err != nil {
+		return err
+	}
+	defer poolRows.Close()
+
+	var pools []RealmPool
+	for poolRows.Next() {
+		var pool RealmPool
+		if err := poolRows.Scan(&pool.PoolSlug, &
pool.Region); err != nil {
+			return err
+		}
+		pools = append(pools, pool)
+	}
+
+	fmt.Printf("Found %d realm pools to proces
s\n", len(pools))
+
+	for _, pool := range pools {
+		// unfiltered realm rankings (per season)
 using pool-based partitioning
+		_, err := tx.Exec(`
+			INSERT INTO run_rankings (run_id, dungeo
n_id, ranking_type, ranking_scope, ranking, 
season_id, computed_at)
+			SELECT
+				cr.id as run_id,
+				cr.dungeon_id,
+				'realm' as ranking_type,
+				? as ranking_scope,
+				ROW_NUMBER() OVER (
+					PARTITION BY cr.dungeon_id, COALESCE(s
_agg.season_number, 1)
+					ORDER BY cr.duration ASC, cr.completed
_timestamp ASC
+				) as ranking,
+				COALESCE(s_agg.season_number, 1) as sea
son_id,
+				? as computed_at
+			FROM challenge_runs cr
+			INNER JOIN realms r ON cr.realm_id = r.i
d
+			LEFT JOIN realms parent_r ON r.parent_re
alm_slug = parent_r.slug AND r.region = pare
nt_r.region
+			LEFT JOIN (
+				SELECT ps.period_id, MIN(s.season_numbe
r) as season_number
+				FROM period_seasons ps
+				JOIN seasons s ON ps.season_id = s.id
+				GROUP BY ps.period_id
+			) s_agg ON cr.period_id = s_agg.period_i
d
+			WHERE r.region = ? AND COALESCE(parent_r
.slug, r.slug) = ?
+		`, pool.PoolSlug, currentTime, pool.Regio
n, pool.PoolSlug)
+
+		if err != nil {
+			return err
+		}
+
+		// update percentile brackets for unfilte
red realm rankings
+		_, err = tx.Exec(`
+			UPDATE run_rankings
+			SET percentile_bracket = (
+				CASE
+					WHEN counts.duration = counts.min_dura
tion THEN 'artifact'
+					ELSE
+						CASE
+							WHEN (CAST(counts.ranking AS REAL) /
 CAST(counts.total_in_pool_season_dungeon AS
 REAL) * 100) <= 1.0 THEN 'excellent'
+							WHEN (CAST(counts.ranking AS REAL) /
 CAST(counts.total_in_pool_season_dungeon AS
 REAL) * 100) <= 5.0 THEN 'legendary'
+							WHEN (CAST(counts.ranking AS REAL) /
 CAST(counts.total_in_pool_season_dungeon AS
 REAL) * 100) <= 20.0 THEN 'epic'
+							WHEN (CAST(counts.ranking AS REAL) /
 CAST(counts.total_in_pool_season_dungeon AS
 REAL) * 100) <= 40.0 THEN 'rare'
+							WHEN (CAST(counts.ranking AS REAL) /
 CAST(counts.total_in_pool_season_dungeon AS
 REAL) * 100) <= 60.0 THEN 'uncommon'
+							ELSE 'common'
+						END
+				END
+			)
+			FROM (
+				SELECT
+					rr.run_id,
+					rr.dungeon_id,
+					rr.season_id,
+					rr.ranking,
+					cr.duration,
+					MIN(cr.duration) OVER (PARTITION BY rr
.dungeon_id, rr.season_id, rr.ranking_scope)
 as min_duration,
+					COUNT(*) OVER (PARTITION BY rr.dungeon
_id, rr.season_id, rr.ranking_scope) as tota
l_in_pool_season_dungeon
+				FROM run_rankings rr
+				INNER JOIN challenge_runs cr ON rr.run_
id = cr.id
+				WHERE rr.ranking_type = 'realm' AND rr.
ranking_scope = ?
+			) counts
+			WHERE run_rankings.run_id = counts.run_i
d
+			AND run_rankings.dungeon_id = counts.dun
geon_id
+			AND run_rankings.season_id = counts.seas
on_id
+			AND run_rankings.ranking_type = 'realm'
+			AND run_rankings.ranking_scope = ?
+		`, pool.PoolSlug, pool.PoolSlug)
+		if err != nil {
+			return err
+		}
+	}
+
+	// now compute filtered rankings per pool 
x dungeon x season
+	dungeonRows, err := tx.Query("SELECT id FR
OM dungeons")
+	if err != nil {
+		return err
+	}
+
+	var dungeonIDs []int
+	for dungeonRows.Next() {
+		var id int
+		if err := dungeonRows.Scan(&id); err != n
il {
+			dungeonRows.Close()
+			return err
+		}
+		dungeonIDs = append(dungeonIDs, id)
+	}
+	dungeonRows.Close()
+
+	for _, pool := range pools {
+		// Get seasons for this pool
+		seasonRows, err := tx.Query(`
+			SELECT DISTINCT COALESCE(s_agg.season_nu
mber, 1) as season_id
+			FROM challenge_runs cr
+			INNER JOIN realms r ON cr.realm_id = r.i
d
+			LEFT JOIN realms parent_r ON r.parent_re
alm_slug = parent_r.slug AND r.region = pare
nt_r.region
+			LEFT JOIN (
+				SELECT ps.period_id, MIN(s.season_numbe
r) as season_number
+				FROM period_seasons ps
+				JOIN seasons s ON ps.season_id = s.id
+				GROUP BY ps.period_id
+			) s_agg ON cr.period_id = s_agg.period_i
d
+			WHERE r.region = ? AND COALESCE(parent_r
.slug, r.slug) = ?
+		`, pool.Region, pool.PoolSlug)
+		if err != nil {
+			return err
+		}
+
+		var seasonIDs []int
+		for seasonRows.Next() {
+			var id int
+			if err := seasonRows.Scan(&id); err != n
il {
+				seasonRows.Close()
+				return err
+			}
+			seasonIDs = append(seasonIDs, id)
+		}
+		seasonRows.Close()
+
+		// filtered realm rankings - per dungeon 
x season using pool-based partitioning
+		for _, dungeonID := range dungeonIDs {
+			for _, seasonID := range seasonIDs {
+				_, err := tx.Exec(`
+					WITH best_team_runs AS (
+						SELECT
+							cr.team_signature,
+							MIN(cr.duration) as best_duration
+						FROM challenge_runs cr
+						INNER JOIN realms r ON cr.realm_id = 
r.id
+						LEFT JOIN realms parent_r ON r.parent
_realm_slug = parent_r.slug AND r.region = p
arent_r.region
+						LEFT JOIN (
+							SELECT ps.period_id, MIN(s.season_nu
mber) as season_number
+							FROM period_seasons ps
+							JOIN seasons s ON ps.season_id = s.i
d
+							GROUP BY ps.period_id
+						) s_agg ON cr.period_id = s_agg.perio
d_id
+						WHERE cr.dungeon_id = ?
+							AND r.region = ?
+							AND COALESCE(parent_r.slug, r.slug) 
= ?
+							AND COALESCE(s_agg.season_number, 1)
 = ?
+						GROUP BY cr.team_signature
+					),
+					filtered_runs AS (
+						SELECT
+							cr.id as run_id,
+							cr.duration,
+							cr.completed_timestamp,
+							ROW_NUMBER() OVER (ORDER BY cr.durat
ion ASC, cr.completed_timestamp ASC) as filt
ered_rank
+						FROM challenge_runs cr
+						INNER JOIN realms r ON cr.realm_id = 
r.id
+						LEFT JOIN realms parent_r ON r.parent
_realm_slug = parent_r.slug AND r.region = p
arent_r.region
+						LEFT JOIN (
+							SELECT ps.period_id, MIN(s.season_nu
mber) as season_number
+							FROM period_seasons ps
+							JOIN seasons s ON ps.season_id = s.i
d
+							GROUP BY ps.period_id
+						) s_agg ON cr.period_id = s_agg.perio
d_id
+						INNER JOIN best_team_runs btr ON cr.t
eam_signature = btr.team_signature
+														AND cr.duration = btr.best_du
ration
+						WHERE cr.dungeon_id = ?
+							AND r.region = ?
+							AND COALESCE(parent_r.slug, r.slug) 
= ?
+							AND COALESCE(s_agg.season_number, 1)
 = ?
+						GROUP BY cr.team_signature
+						HAVING cr.id = MIN(cr.id)
+					)
+					INSERT INTO run_rankings (run_id, dung
eon_id, ranking_type, ranking_scope, ranking
, season_id, computed_at)
+					SELECT
+						run_id,
+						? as dungeon_id,
+						'realm' as ranking_type,
+						? as ranking_scope,
+						filtered_rank as ranking,
+						? as season_id,
+						? as computed_at
+					FROM filtered_runs
+				`, dungeonID, pool.Region, pool.PoolSlu
g, seasonID,
+					dungeonID, pool.Region, pool.PoolSlug,
 seasonID,
+					dungeonID, pool.PoolSlug+"_filtered", 
seasonID, currentTime)
+
+				if err != nil {
+					return err
+				}
+			}
+		}
+
+		// update percentile brackets for filtere
d realm rankings
+		filteredScope := pool.PoolSlug + "_filter
ed"
+		_, err = tx.Exec(`
+			UPDATE run_rankings
+			SET percentile_bracket = (
+				CASE
+					WHEN counts.duration = counts.min_dura
tion THEN 'artifact'
+					ELSE
+						CASE
+							WHEN (CAST(counts.ranking AS REAL) /
 CAST(counts.total_in_pool_season_dungeon AS
 REAL) * 100) <= 1.0 THEN 'excellent'
+							WHEN (CAST(counts.ranking AS REAL) /
 CAST(counts.total_in_pool_season_dungeon AS
 REAL) * 100) <= 5.0 THEN 'legendary'
+							WHEN (CAST(counts.ranking AS REAL) /
 CAST(counts.total_in_pool_season_dungeon AS
 REAL) * 100) <= 20.0 THEN 'epic'
+							WHEN (CAST(counts.ranking AS REAL) /
 CAST(counts.total_in_pool_season_dungeon AS
 REAL) * 100) <= 40.0 THEN 'rare'
+							WHEN (CAST(counts.ranking AS REAL) /
 CAST(counts.total_in_pool_season_dungeon AS
 REAL) * 100) <= 60.0 THEN 'uncommon'
+							ELSE 'common'
+						END
+				END
+			)
+			FROM (
+				SELECT
+					rr.run_id,
+					rr.dungeon_id,
+					rr.season_id,
+					rr.ranking,
+					cr.duration,
+					MIN(cr.duration) OVER (PARTITION BY rr
.dungeon_id, rr.season_id, rr.ranking_scope)
 as min_duration,
+					COUNT(*) OVER (PARTITION BY rr.dungeon
_id, rr.season_id, rr.ranking_scope) as tota
l_in_pool_season_dungeon
+				FROM run_rankings rr
+				INNER JOIN challenge_runs cr ON rr.run_
id = cr.id
+				WHERE rr.ranking_type = 'realm' AND rr.
ranking_scope = ?
+			) counts
+			WHERE run_rankings.run_id = counts.run_i
d
+			AND run_rankings.dungeon_id = counts.dun
geon_id
+			AND run_rankings.season_id = counts.seas
on_id
+			AND run_rankings.ranking_type = 'realm'
+			AND run_rankings.ranking_scope = ?
+		`, filteredScope, filteredScope)
+		if err != nil {
+			return err
+		}
+	}
+
+	fmt.Printf("[OK] Computed realm rankings w
ith percentile brackets for %d realm pools\n
", len(pools))
+	return nil
+}
 
[ BACK TO LOG ]
──────────────────────────────────────────────────────────────────────────────────────
OOKNET
────────────────────────────────────────────────
OOKNET