Skip to content
Trade-offs

Four things I'd fix next

The next architecture step is clearer boundaries inside the Rails monolith, not a microservice rewrite.

  • Centralize the LLM transport boundary. The four core language jobs duplicate OpenRouter transport logic, and the shared client owns no explicit timeout policy. One typed gateway should own timeouts, retry classification, telemetry, response normalization, and test adapters. A worker held open by a provider is a different failure from an invalid response, and the system should name that difference once.
  • Strengthen boundaries inside the Rails monolith. Several high-change reader and processing units carry broad responsibilities. As product work reaches them, I would decompose those paths behind clearer domain interfaces and enforce dependency direction while retaining one Rails application and PostgreSQL transaction boundary. The objective is safer, faster feature delivery, not a microservice rewrite.
  • Finish the cost-table idempotency. Audio cost rows are already protected by a partial unique index scoped to stage = 'audio_generation'. The four language passes write into the same table behind an application-level exists? check, so two workers — or one Sidekiq retry after a timeout — can both read false and both insert. Nothing errors; the ledger is just quietly wrong. The remediation is the index that already exists, extended per stage, with the uniqueness conflict read as success rather than as a failure.
  • Turn founder fit into user evidence. The problem comes from years of language learning, teaching, and translation. The market and the learning outcomes are not proven by that. The next evidence is target-reader research, activation, continued pull, retention, and willingness to pay. A strong thesis should make it easier to ask a precise question, not easier to avoid one.