Skip to content
February 28, 202613 min readbusiness

The Hidden Tax of "We Support Both"

Every SaaS team eventually says "we'll support both" ... both databases, both auth providers, both deployment targets. The hidden cost isn't the initial implementation. It's the 2x testing matrix, 2x documentation, and the subtle bugs that only appear in one configuration.

architecturesaastechnical-debtdecision-makingstrategy
The Hidden Tax of "We Support Both"

TL;DR

"We support both" is the most expensive sentence in SaaS architecture. Every "both" doubles your surface area: testing, documentation, operational runbooks, security audits, and the mental model your team carries. I've audited 8 SaaS codebases where "we support both MySQL and PostgreSQL" or "we support both AWS and GCP" accounted for 25-40% of total engineering overhead. The cost isn't visible in sprint planning because it's distributed: an extra 30 minutes on every PR review checking both paths, an extra 2 hours on every deployment verifying both configurations, an extra week on every security audit. The fix isn't always eliminating one option... sometimes you genuinely need both. The fix is making the decision consciously, quantifying the tax, and choosing "both" only when the business value exceeds the ongoing engineering cost.

Part of the SaaS Architecture Decision Framework ... a comprehensive guide to architecture decisions from MVP to scale.


Where "Both" Comes From

The decision to support both is never made at an architecture meeting. It accumulates.

The customer-driven "both": Your biggest prospect uses MongoDB. Your application runs on PostgreSQL. Sales says "can we support both?" Engineering says "it's just a database adapter." Six months later, the adapter has 47 special cases for MongoDB's different join behavior, transaction semantics, and query syntax.

The acquisition "both": Two companies merge. One runs on AWS, the other on GCP. "We'll support both while we migrate." Three years later, both are still supported. The migration never happened because there was always a more urgent feature.

The team preference "both": Half the team prefers REST, half prefers GraphQL. "Let's support both." Now every API endpoint has two implementations, two sets of documentation, and two integration test suites.

The backward compatibility "both": You shipped API v1. Now v2 is better. "We'll support both until customers migrate." V1 is still running five years later with 12% of traffic and 40% of the API-related bugs.


The Hidden Costs (Quantified)

I've tracked the actual engineering cost of "both" across 8 advisory clients. The results are consistent.

Testing Overhead

ConfigurationTest MatrixMaintenance
One database1x tests1x maintenance
Two databases2.3x tests2.5x maintenance
Two databases + two cloud providers4.6x tests5x maintenance

The multiplier isn't exactly 2x because some tests are configuration-independent. But the configuration-specific tests... the ones that verify behavior unique to each option... are where the bugs hide. And those bugs are the hardest to reproduce because your development environment runs one configuration while production might run the other.

Operational Overhead

Every runbook, every monitoring dashboard, every alert configuration needs to work for both. The on-call engineer at 3 AM needs to know not just "the database is slow" but "the MySQL database is slow and the fix is different than the PostgreSQL fix."

Real example from a client: Their PostgreSQL deployment used pg_stat_statements for query analysis. Their MySQL deployment used performance_schema. The monitoring dashboards were different. The optimization runbooks were different. The on-call engineer needed to know both.

Measured impact: On-call MTTR was 35% longer for issues in the less-used configuration because engineers had less operational muscle memory for it.

Cognitive Load

Every engineer who touches the codebase needs to understand both configurations. Not just "they exist" but "how they differ and when the difference matters."

// The abstraction that doesn't fully abstract async function getUser(id: string): Promise<User> { if (config.database === "postgresql") { // PostgreSQL: JSONB query for preferences return db.query(`SELECT *, preferences->>'theme' as theme FROM users WHERE id = $1`, [id]); } else { // MongoDB: dot notation for nested fields return db .collection("users") .findOne({ _id: new ObjectId(id) }, { projection: { "preferences.theme": 1 } }); } }

This pattern... a function that branches on configuration... appears innocuous. But multiply it by 200 database operations and you have a codebase where every function has two code paths that diverge in subtle ways.

Security Surface Area

Every "both" doubles your security audit scope. Two databases means two sets of access controls, two sets of encryption configurations, two sets of vulnerability scanning pipelines.

A client discovered this the hard way: their PostgreSQL deployment had Row-Level Security enforcing tenant isolation. Their MongoDB deployment relied on application-level filtering. A bug in the application filter exposed cross-tenant data... but only in the MongoDB configuration. The vulnerability existed for 8 months before discovery because security testing focused on the PostgreSQL path.


The Decision Framework

Before accepting "we support both," quantify the cost:

Step 1: Calculate the Ongoing Tax

Cost CategoryEstimation Method
TestingCount configuration-specific tests. Multiply by average test maintenance time.
CI/CDNumber of additional build/deploy pipelines. Multiply by compute cost and maintenance time.
DocumentationPages of configuration-specific documentation. Multiply by update frequency.
On-callAdditional runbooks and dashboards. Multiply by incident frequency in each configuration.
SecurityAdditional attack surface. Multiply by audit frequency and remediation time.
Cognitive loadNumber of engineers who need to understand both. Multiply by ramp-up time.

Step 2: Calculate the Business Value

Value SourceEstimation Method
Revenue at riskARR from customers who require the second option
Market expansionTAM unlocked by supporting the second option
Competitive advantageDoes "both" differentiate from competitors?
Acquisition requirementIs "both" a requirement for an M&A deal?

Step 3: Compare Honestly

If the annual engineering tax of "both" exceeds the annual revenue benefit, cut one. This sounds obvious, but I've seen teams support MySQL for a single $50K/year customer while spending $200K/year in engineering overhead to maintain it.


When "Both" Is Justified

I'm not arguing that you should never support multiple configurations. Some cases genuinely warrant it:

Multi-cloud for enterprise customers. If your enterprise tier sells to companies with cloud mandates (government, regulated industries), supporting AWS and GCP is a revenue driver. Budget the tax explicitly.

Database-per-tenant for isolation. If your security model requires per-tenant database instances and customers bring their own database, supporting PostgreSQL and MySQL is a product feature.

API versioning during migration. Supporting v1 and v2 during a 6-month migration window is pragmatic. Supporting v1 and v2 indefinitely is a tax.

The key: in each justified case, the "both" has a clear business reason, a defined scope, and ideally an expiration date.


The Exit Strategy

When you decide to eliminate one option, the migration path determines whether it takes 3 months or 3 years.

The Strangler Fig for "Both"

  1. Stop new development on the deprecated option. All new features only need to work with the chosen option.
  2. Migrate existing customers. Provide migration tooling and a timeline. Offer migration support as a service.
  3. Set a sunset date. Announce it 6-12 months in advance. Stick to it.
  4. Remove the code. After the sunset date, delete the abstraction layer and all configuration-specific code. The code reduction alone improves velocity.

The Conversation with Customers

"We're consolidating from two database backends to one. This lets us ship features 30% faster and reduce our security surface area. We'll provide full migration support and a 9-month transition period."

In my experience, 90% of customers accept this without pushback when you frame it as a quality and velocity improvement. The 10% who push back are either bluffing (they'll migrate when the deadline arrives) or genuinely locked in (negotiate a custom support contract).


Common "Both" Scenarios and Recommendations

"Both" ScenarioRecommendationReasoning
MySQL and PostgreSQLPick PostgreSQLJSONB, RLS, better extension ecosystem for SaaS
PostgreSQL and MongoDBPick one based on workloadMongoDB excels at document-heavy workloads; PostgreSQL covers relational + JSONB. Supporting both is rarely worth the adapter complexity.
REST and GraphQLPick one based on clientsMobile-heavy = GraphQL; B2B integrations = REST
AWS and GCPPick one unless enterprise requires itMulti-cloud tax is 30-50% of infrastructure engineering time
Docker and bare metalDockerThe abstraction cost is negligible; operational benefits are real
API v1 and v2Sunset v1 within 12 monthsEvery additional API version is permanent maintenance
Webpack and ViteViteThe migration is a one-time cost; the build speed improvement is permanent
Jest and VitestPick oneThey're similar enough that maintaining both is pure overhead

When to Apply This

  • Your team mentions "we support both" for any infrastructure component
  • CI/CD pipelines run multiple configurations and you're not sure why
  • Bug reports include "only happens when configured with X"
  • New engineers take extra time ramping up because of configuration complexity

When NOT to Apply This

  • You genuinely serve customers on different platforms and the revenue justifies the tax
  • The "both" is temporary with a defined sunset date
  • The abstraction layer is clean and the configurations are truly interchangeable

Paying the hidden tax of "we support both"? I help teams quantify the cost, make the decision, and execute the migration.


Continue Reading

This post is part of the SaaS Architecture Decision Framework ... covering database design, deployment strategy, API patterns, and infrastructure decisions.

More in This Series

Get insights like this weekly

Join The Architect's Brief — one actionable insight every Tuesday.

Need help with SaaS architecture?

Let's talk strategy