---
title: Major Domo Database Release — 2026.3.17
description: Database migration and schema changes for Major Domo v2 on 2026-03-17.
type: reference
domain: server-configs
tags: [major-domo, deployment, release-notes, database]
---

# Major Domo Database Release — 2026.3.17

**Date:** 2026-03-17
**Branch:** next-release → main (PR #64, 11 commits)
**Repo:** cal/major-domo-database
**Server:** akamai (`sba_db_api` container, port 801)

## Release Summary

11 commits from `next-release` rebased onto `main`. Mix of query performance improvements, bug fixes, and code quality cleanup. No schema migrations — safe drop-in deploy.

## Performance

- **Push limit/offset to DB in `PlayerService.get_players`** (#37): Previously fetched all rows then sliced in Python. Now passes `LIMIT`/`OFFSET` directly to the Peewee query, eliminating full-table reads on paginated requests.
- **Eliminate N+1 queries in batch POST endpoints** (#25): Replaced per-row `get_or_none()` loops in `battingstats`, `results`, `schedules`, and `transactions` batch insert endpoints with a single bulk set-lookup before the write loop.

## Bug Fixes

- **Fix `lob_2outs` and `rbipercent` calculation in `SeasonPitchingStats`** (#28): Both fields were returning incorrect values due to wrong formula inputs. Now computed correctly from the underlying stat columns.
- **Invalidate cache after `PlayerService` write operations** (#32): Cache was being populated on reads but never invalidated on writes, causing stale player data to persist until the next restart.
- **Validate `sort_by` parameter with `Literal` type in `views.py`** (#36): Unvalidated `sort_by` could cause silent no-ops or unexpected ordering. Now enforced with a `Literal` type annotation, raising a 422 on invalid values.

## Code Quality

- **Replace bare `except:` with `except Exception:`** (#29): Silencing `KeyboardInterrupt`, `SystemExit`, and `GeneratorExit` is an antipattern. All 6 instances updated.
- **Remove unused imports in `standings.py` and `pitchingstats.py`** (#30): Dead imports removed (`pydantic` in `standings.py`).
- **Replace `print(req.scope)` with `logger.debug` in `/api/docs`** (#21): Debug print statement that logged full request scope on every docs page load replaced with a conditional logger call.
- **Remove empty `WEEK_NUMS` dict from `db_engine.py`** (#34): Unused stub dict removed.
- **Remove unimplementable skipped caching tests** (#33): Tests marked `@pytest.mark.skip` for a caching interface that was never built. Removed rather than leaving permanently skipped.

## Conflict Resolution

Branch was rebased (not squash-merged) onto main. Six files had textual conflicts from two main-branch fixes that landed after `next-release` diverged:

**Trailing slash regression (6 router files)**
- PR #61 on main fixed a production bug: `aiohttp` converts POST→GET on 307 redirects, silently dropping request bodies. The fix changed all `@router.post("")` → `@router.post("/")`.
- next-release's batch N+1 and bare-except PRs all touched the same files with the old `""` signature.
- Resolution: kept `@router.post("/")` from main, applied next-release's functional changes on top.

**Case-insensitive `team_abbrev` filter (`transactions.py`)**
- PR #60 on main fixed affiliate roster transactions being silently dropped due to case mismatch (input uppercased, DB column mixed-case). Fix used `fn.UPPER(Team.abbrev)`.
- next-release's version of `transactions.py` predated this fix.
- Resolution: preserved `fn.UPPER(Team.abbrev)` from main alongside next-release's N+1 fix.

**`requirements.txt`**
- Main has fully pinned deps including `starlette==0.52.1` (from 2026-03-09 outage) and a new `requirements-dev.txt`.
- next-release had loose pins and no `requirements-dev.txt`.
- Resolution: took main's fully-pinned version entirely.
