Skip to main content

Subdomains: Where to Invest Your Effort

Subdomains are natural divisions of your business domain. Understanding them helps you decide where to invest your best engineers, where to buy off-the-shelf, and where "good enough" is actually good enough.

TL;DR

Subdomain TypeDefinitionStrategy
CoreWhat makes you unique, your competitive advantageBuild, invest heavily, best engineers
SupportingNecessary but not differentiatingBuild or buy, adequate investment
GenericSolved problems, commodityBuy, outsource, use existing solutions

The Investment Problem

Not all parts of your system deserve equal attention:

What goes wrong:

  • Senior engineers building login pages (solved problem)
  • Junior engineers on core business logic (competitive advantage)
  • Custom-built email system (SendGrid exists)
  • Everything gets the same architecture (overkill or underbuilt)

The Three Subdomain Types

Core Subdomain

Definition: The part of your business that provides competitive advantage. If you do this poorly, you lose to competitors.

Characteristics:

  • High complexity
  • Frequently changing
  • Unique to your business
  • Hard to copy

Strategy:

  • Build in-house
  • Assign best engineers
  • Apply full DDD tactical patterns
  • Invest in deep domain modeling

Examples by Industry:

CompanyCore Subdomain
NetflixRecommendation algorithm
UberMatching drivers to riders, surge pricing
StripePayment processing, fraud detection
GoogleSearch ranking algorithm
AirbnbTrust & safety, pricing optimization

Supporting Subdomain

Definition: Necessary for the business to function but doesn't provide competitive advantage. Important, but not what makes you special.

Characteristics:

  • Medium complexity
  • Changes less frequently
  • Could be similar across companies
  • Important but not differentiating

Strategy:

  • Build if custom needs exist
  • Buy if good solutions available
  • Adequate (not excessive) investment
  • Simpler patterns acceptable

Examples:

Supporting SubdomainWhy It's Supporting
Order managementNecessary, but not unique
Customer support ticketingImportant, but commodity
Inventory trackingRequired, but standard problem
Reporting/analyticsNeeded, but not competitive advantage

Generic Subdomain

Definition: Solved problems that are the same across all businesses. No competitive advantage possible.

Characteristics:

  • Well-understood problems
  • Stable, rarely changes
  • Same everywhere
  • Many existing solutions

Strategy:

  • Buy off-the-shelf
  • Use SaaS
  • Use open-source
  • Don't reinvent

Examples:

Generic SubdomainSolution
AuthenticationAuth0, Okta, Firebase Auth
Email sendingSendGrid, Mailgun, SES
Payment processingStripe, Braintree (unless you're Stripe!)
File storageS3, Azure Blob
LoggingDatadog, Splunk, ELK

Real-World Example: E-Commerce Platform

Investment Strategy:

SubdomainInvestmentTeamArchitecture
Dynamic PricingHighSenior ML + Domain expertsFull DDD, Event Sourcing
RecommendationsHighML engineersComplex, custom
Search RankingHighSearch specialistsCustom, optimized
Order ManagementMediumMid-level engineersStandard patterns
InventoryMediumMid-level engineersCRUD + events
AuthenticationLowUse Auth0SaaS integration
EmailLowUse SendGridAPI calls

Identifying Subdomain Types

Questions to Ask

Is it Core?

  • Would competitors pay to know how you do this?
  • Does doing this better directly increase revenue?
  • Is this why customers choose you over competitors?
  • Does this require deep domain expertise?

Is it Supporting?

  • Is it necessary for the business to function?
  • Could you describe it to another company in the same industry?
  • Are there multiple reasonable ways to implement it?
  • Does it support core activities without being core itself?

Is it Generic?

  • Is this the same problem every company faces?
  • Are there multiple commercial solutions available?
  • Would building custom provide any advantage?
  • Is the problem well-understood with standard solutions?

Decision Matrix

┌─────────────────────────────────────────────────────────┐
│ SUBDOMAIN CLASSIFICATION MATRIX │
├─────────────────────────────────────────────────────────┤
│ │
│ Competitive Advantage? │
│ YES ──────────────────────────────────► CORE │
│ │ │
│ NO │
│ │ │
│ ▼ │
│ Off-the-shelf solution exists? │
│ YES ──────────────────────────────────► GENERIC │
│ │ │
│ NO │
│ │ │
│ ▼ │
│ ────────────────────────────────────► SUPPORTING │
│ │
└─────────────────────────────────────────────────────────┘

Subdomain Evolution

Subdomains aren't static - they evolve over time:

Examples of Evolution:

ThenNowWhat Happened
Custom web serverUse Nginx/ApacheWeb serving commoditized
Custom databaseUse PostgreSQL/MySQLDatabases became generic
Custom authUse Auth0/OktaAuth became generic
Custom ML infraUse AWS SageMakerML platforms emerged

Implication: Regularly reassess your subdomains. Yesterday's core might be today's generic.

Architecture by Subdomain

Different subdomains deserve different architectural approaches:

Core Subdomain Architecture

// Full DDD with rich domain model
namespace Pricing.Domain
{
public class PricingEngine : AggregateRoot
{
private readonly List<PricingRule> _rules;
private readonly DemandModel _demandModel;

public Price CalculateOptimalPrice(
Product product,
CustomerSegment segment,
MarketConditions conditions)
{
var basePrice = product.BasePrice;
var demandMultiplier = _demandModel.GetMultiplier(conditions);
var segmentAdjustment = GetSegmentAdjustment(segment);

var rules = _rules
.Where(r => r.AppliesTo(product, segment, conditions))
.OrderBy(r => r.Priority);

var price = basePrice;
foreach (var rule in rules)
{
price = rule.Apply(price, demandMultiplier, segmentAdjustment);
}

AddDomainEvent(new PriceCalculated(product.Id, price, conditions));

return price;
}
}
}

Supporting Subdomain Architecture

// Simpler approach - transaction script or basic patterns
namespace Orders.Application
{
public class OrderService
{
public async Task<Order> CreateOrder(CreateOrderRequest request)
{
var order = new Order
{
Id = Guid.NewGuid(),
CustomerId = request.CustomerId,
Items = request.Items.Select(i => new OrderItem
{
ProductId = i.ProductId,
Quantity = i.Quantity,
Price = i.Price
}).ToList(),
Status = OrderStatus.Pending,
CreatedAt = DateTime.UtcNow
};

await _orderRepository.Save(order);
await _eventBus.Publish(new OrderCreated(order.Id));

return order;
}
}
}

Generic Subdomain Architecture

// Just use the library/service
namespace Notifications.Infrastructure
{
public class EmailService
{
private readonly ISendGridClient _sendGrid;

public async Task SendEmail(EmailRequest request)
{
var message = new SendGridMessage
{
From = new EmailAddress(request.From),
Subject = request.Subject,
HtmlContent = request.Body
};
message.AddTo(request.To);

await _sendGrid.SendEmailAsync(message);
}
}
}

Team Allocation by Subdomain

┌─────────────────────────────────────────────────────────┐
│ TEAM ALLOCATION STRATEGY │
├─────────────────────────────────────────────────────────┤
│ │
│ CORE SUBDOMAIN │
│ ├── Staff/Principal engineers │
│ ├── Domain experts embedded │
│ ├── Dedicated team │
│ └── High autonomy │
│ │
│ SUPPORTING SUBDOMAIN │
│ ├── Senior engineers │
│ ├── Domain expert access (not embedded) │
│ ├── Shared team possible │
│ └── Standard processes │
│ │
│ GENERIC SUBDOMAIN │
│ ├── Any engineer level │
│ ├── Integration focus │
│ ├── Minimal custom code │
│ └── Follow vendor docs │
│ │
└─────────────────────────────────────────────────────────┘

Common Mistakes

Mistake 1: Treating Everything as Core

❌ "Authentication is critical, so it's core"
✅ "Authentication is critical but generic - use Auth0"

Critical ≠ Core. Core means competitive advantage.

Mistake 2: Building Generic Subdomains

❌ "Let's build our own email sending system"
✅ "Let's use SendGrid and focus on our pricing algorithm"

Mistake 3: Underinvesting in Core

❌ "Junior devs can handle the recommendation engine"
✅ "Our best engineers should own recommendations - it's our moat"

Mistake 4: Over-engineering Supporting

❌ "Let's apply full DDD with Event Sourcing to order management"
✅ "Simple CRUD with events is sufficient for orders"

Mistake 5: Static Classification

❌ "We classified subdomains 3 years ago, we're done"
✅ "Let's reassess - has anything become commoditized?"

Staff+ Interview Questions

Q: How do you decide what's a core subdomain?

A: I ask:

  1. Does this provide competitive advantage?
  2. Would competitors benefit from knowing how we do this?
  3. Does doing this better directly impact revenue/growth?
  4. Is this why customers choose us?

If yes to most, it's core. If it's necessary but not differentiating, it's supporting. If there are commodity solutions, it's generic.

Q: Should you always buy for generic subdomains?

A: Almost always, but consider:

  • Integration complexity - Sometimes building a thin wrapper is easier
  • Vendor lock-in - Evaluate switching costs
  • Compliance requirements - Some industries restrict SaaS
  • Scale economics - At massive scale, building might be cheaper

But default to buy. The opportunity cost of building generic solutions is high.

Q: How do subdomains relate to bounded contexts?

A: They're orthogonal concepts:

  • Subdomain = Business capability classification (core/supporting/generic)
  • Bounded Context = Model boundary

A core subdomain might have multiple bounded contexts. A bounded context might span supporting and generic subdomains (though this is a smell).

Quick Reference Card

┌─────────────────────────────────────────────────────────┐
│ SUBDOMAIN QUICK REFERENCE │
├─────────────────────────────────────────────────────────┤
│ │
│ CORE │
│ • Competitive advantage │
│ • Build in-house │
│ • Best engineers │
│ • Full DDD patterns │
│ │
│ SUPPORTING │
│ • Necessary, not differentiating │
│ • Build or buy │
│ • Adequate investment │
│ • Simpler patterns OK │
│ │
│ GENERIC │
│ • Solved problems │
│ • Buy/outsource │
│ • Minimal custom code │
│ • Use existing solutions │
│ │
│ Key Question: │
│ "Would doing this better give us competitive │
│ advantage over our rivals?" │
│ │
└─────────────────────────────────────────────────────────┘

Next Steps