Rent control is eating software engineers alive.
Not literally. But if you're building property management tools, compliance with local rent caps is the problem that keeps expanding. California. Oregon. New York. Washington DC. Boston. Each jurisdiction has different rent increase caps, exemption rules, notice periods, and enforcement mechanisms. Add international markets and the complexity becomes a graph database problem—not just a forms problem.
By October 2026, over 200 U.S. municipalities have implemented some form of rent stabilization. That number compounds yearly. A landlord managing 50 units across three states isn't operating in three markets anymore—they're operating in potentially 15+ regulatory jurisdictions. Miss one notice deadline or miscalculate one increase cap, and you're exposed to fines, lease violations, and tenant disputes.
The technical challenge: how do you build a compliance engine that scales across this fragmentation without hardcoding every municipality's ruleset?
The Complexity You're Actually Solving
Let's be concrete. Here's what a landlord in California faces:
- Statewide cap: 5% or CPI + 2%, whichever is lower (as of 2026)
- Local variations: San Francisco (0% increases for some properties), Los Angeles (3% or CPI + 2%), Oakland (3% + inflation)
- Exemptions: New construction built after specific dates, owner-occupied duplexes, single-family homes (varies by city)
- Tenant protections: Just-cause eviction notice requirements, relocation assistance for Ellis Act evictions
- Notice windows: 30, 60, or 90 days depending on increase magnitude and jurisdiction
Now multiply that by 200 municipalities, and consider that rules change annually. New York's rent stabilization board updates guidelines every June. Oregon's cap adjusts each July. California's formula recalculates quarterly based on inflation data.
A self-managing landlord using spreadsheets or basic rental software? They're one compliance miss away from legal liability.
Architectural Patterns for Jurisdiction-Aware Systems
Here's how you model this problem at the code level:
Rule Engine Architecture
The naive approach: a massive if-else tree or lookup table for each jurisdiction.
if (jurisdiction === "SF") {
maxIncrease = 0;
} else if (jurisdiction === "LA") {
maxIncrease = Math.max(0.03, inflation + 0.02);
} else if (jurisdiction === "OAK") {
maxIncrease = 0.03 + inflation;
}
// ... 200+ more conditions
This scales terribly. Rules aren't static. You're shipping updates constantly.
Better: a declarative rules engine where each jurisdiction is a configuration object:
{
"jurisdiction_id": "ca_sf",
"name": "San Francisco",
"rent_increase": {
"type": "fixed",
"annual_cap": 0.0,
"applies_to": {
"property_type": ["residential"],
"built_before": "1979-06-13"
}
},
"exemptions": [
{
"type": "new_construction",
"built_after": "1979-06-13"
}
],
"notice_requirement_days": 60,
"enforcement_agency": "sf_rent_board",
"last_updated": "2026-10-15"
}
This is closer. You can query rules by jurisdiction, check exemptions, calculate increases dynamically. But you still need logic to:
- Detect which jurisdiction(s) apply to a property
- Determine if exemptions override the base rule
- Calculate the next allowable increase
- Generate compliant notices with correct timelines
Detection and Scope
Geolocation matters. A property in a rent-controlled city might fall outside the city limits and be exempt. Some jurisdictions control only certain property types (apartments, not single-family). Some have income thresholds.
This is where your data model gets sophisticated:
CREATE TABLE properties (
id UUID,
address VARCHAR,
latitude DECIMAL,
longitude DECIMAL,
property_type ENUM,
built_date DATE,
units_count INT
);
CREATE TABLE property_jurisdictions (
property_id UUID,
jurisdiction_id VARCHAR,
primary BOOLEAN,
scope TEXT -- what rules apply to this property in this jurisdiction
);
CREATE TABLE compliance_rules (
id VARCHAR PRIMARY KEY,
jurisdiction_id VARCHAR,
rule_type ENUM, -- "rent_increase", "notice_requirement", "exemption"
rule_config JSONB,
effective_date DATE,
version INT
);
You're now tracking: which properties fall under which jurisdictions, versioning rules as they change, and storing configuration as queryable JSON instead of hardcoding logic.
Calculation Pipeline
When a landlord wants to increase rent, your system should:
- Look up all applicable jurisdictions for the property
- Fetch the current rule versions (effective as of today)
- Check exemptions for the property
- Calculate the maximum allowable increase across all applicable rules
- Determine the earliest notice date compliant with all jurisdictions
- Generate a notice document in the correct format
function calculateCompliantRentIncrease(propertyId, requestedIncrease) {
jurisdictions = getApplicableJurisdictions(propertyId)
maxAllowedIncreases = []
earliestNoticeDate = null
for each jurisdiction in jurisdictions:
rules = getRulesForJurisdiction(jurisdiction, today)
if propertyIsExempt(propertyId, rules):
maxAllowedIncreases.push(null) // no cap
else:
maxAllowedIncreases.push(
calculateIncreaseCap(rules, currentRent, inflation)
)
earliestNoticeDate = max(
earliestNoticeDate,
today + rules.notice_requirement_days
)
return {
allowed: min(maxAllowedIncreases),
notice_date: earliestNoticeDate,
jurisdiction_constraints: [...]
}
}
The logic respects the most restrictive rule across jurisdictions. If San Francisco says 0% and a tenant's rent is also subject to state law, the increase is 0%.
Real-World Implementation Lessons
Versioning and Rollout
Rules change mid-year. When California recalculates its inflation cap in Q3, old rent increases calculated in Q1 are suddenly non-compliant if they used outdated inflation data.
Solution: version your rules table and maintain historical snapshots. When a landlord generates a notice in March, tag it with the March 2026 rules version. If rules change in June, notices generated under the old version remain valid—they're timestamped.
Testing at Scale
This is where compliance failures happen. You need test coverage for:
- Every jurisdiction's exemptions
- Rule interactions (multiple jurisdictions applying to one property)
- Edge cases (properties built on exact cutoff dates, tenant occupancy boundaries)
- Annual rule changes
Platforms tracking compliance across jurisdictions (like LeaseBase's compliance engine) version-test rules quarterly as municipalities update. Each rule change triggers regression testing across all property types and exemption scenarios.
Audit Trails
When a landlord gets audited by a city rent board, you need to prove:
- What rules applied on the notice date
- Which version of the rules your system used
- Why the increase was calculated that way
Store everything: rule versions, calculation inputs, notice generation timestamps. Make this queryable and exportable. You're building an audit log, not just a calculation engine.
The Cost of Non-Compliance
Here's the business math: a self-managing landlord might use basic software ($79/month) vs. hiring a property manager ($800-1500/month). The savings are real. But one compliance miss—one notice generated with the wrong increase cap or insufficient notice period—can result in fines of $5,000-$20,000+ depending on the jurisdiction, plus tenant disputes and potential lease invalidation.
A landlord managing 50 units has 50x the exposure. They need either a property manager or compliance software they trust. This is where the moat is: platforms that actually track local jurisdiction rules, version them, and keep them current are doing work that spreadsheets can't.
Resources
If you're building proptech tools and need to integrate compliance, start by mapping your jurisdictions and their rules into configuration. Don't hardcode. Version your rules. Test constantly. When you need a compliance check across multiple properties and states, there are tools that already handle the regulatory database—no need to rebuild that wheel.
For self-managing landlords who want a quick compliance sanity check, LeaseBase's compliance check can verify if a specific rent increase is compliant in a given jurisdiction.
This article is for informational purposes only and does not constitute legal advice.
About the Author
This article was written in collaboration with LeaseBase, a property management platform designed for self-managing landlords. LeaseBase provides compliance tracking, rent increase calculations, and regulatory rule updates across U.S. jurisdictions. The author is part of LeaseBase's content and engineering teams.

