1 comments

  • davidvartanian a month ago

    The compound interest framing is the right one. The part people miss is that compound interest works in both directions.

    Good early architectural decisions compound positively. A clean boundary between services means the team that owns service A doesn't need to coordinate with the team that owns service B when either one ships. That coordination cost you avoided on day 30 is the same cost you avoid on day 300, but by day 300 you've avoided it hundreds of times.

    Bad decisions compound negatively, and the mechanism is subtle. A leaky abstraction doesn't break anything immediately. It just means every developer who touches that boundary spends an extra 15 minutes (BS, it can be an hour or two) understanding why the types don't quite match, or why that one field is sometimes null. Multiply 15 minutes by 8 developers by 250 working days and you've lost 500 engineer-hours to a decision someone made in week two.

    The "Mullet Schema" idea (strict columns for business-critical data, JSONB for everything else) is a practical version of this. You're deliberately choosing where to accept compound costs (the JSONB side) and where to prevent them (the strict columns). The key is being explicit about which side a given piece of data belongs on, and reviewing that classification as the product evolves. What starts as "nice to have" metadata has a way of becoming load-bearing business logic over 18 months.

    To answer your question about where to draw the line: I look at how many teams or people need to coordinate when something changes. If a schema change requires three Slack conversations or a "short" call, that's a signal the architecture is creating coordination costs that will definitely compound, what you correctly called "microservice tax" and I call "complexity tax". That's usually where the line should have been drawn earlier.