Skip to main content
The Integration Quality Scale is Home Assistant’s framework for measuring and ensuring the quality of integrations. It provides clear standards and guidelines that help maintainers build reliable, user-friendly integrations.

Overview

The quality scale consists of four tiers, each building upon the previous one:
  • Bronze: Essential functionality and basic best practices
  • Silver: Enhanced reliability and maintainability
  • Gold: Production-ready with excellent user experience
  • Platinum: Exceptional quality with advanced features
Integrations declare their quality scale level in manifest.json:
{
  "domain": "example",
  "name": "Example Integration",
  "quality_scale": "gold"
}

Quality Scale Tiers

Bronze Tier

The bronze tier establishes fundamental requirements for all integrations:

Key Requirements

  • Config Flow: User-friendly configuration through the UI
  • Unique Config Entry: Prevent duplicate configurations
  • Entity Unique ID: All entities must have stable unique IDs
  • Runtime Data: Use modern entry.runtime_data pattern
  • Test Before Setup: Validate connectivity before completing setup
  • Has Entity Name: Entities must have proper names
  • Documentation: High-level description, installation, and removal instructions

Example: Runtime Data Pattern

from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant

from .coordinator import MyCoordinator

type MyConfigEntry = ConfigEntry[MyCoordinator]

async def async_setup_entry(hass: HomeAssistant, entry: MyConfigEntry) -> bool:
    """Set up from a config entry."""
    coordinator = MyCoordinator(hass, entry)
    await coordinator.async_config_entry_first_refresh()
    
    # Store coordinator in runtime_data
    entry.runtime_data = coordinator
    
    await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
    return True

Silver Tier

Silver tier adds reliability and proper error handling:

Key Requirements

  • Config Entry Unloading: Clean shutdown and resource cleanup
  • Reauthentication Flow: Handle expired credentials gracefully
  • Entity Unavailable: Mark entities unavailable when device is offline
  • Parallel Updates: Protect against concurrent state updates
  • Test Coverage: Minimum 90% code coverage
  • Integration Owner: Designated code owner for maintenance

Example: Config Entry Unloading

async def async_unload_entry(hass: HomeAssistant, entry: MyConfigEntry) -> bool:
    """Unload a config entry."""
    return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)

Example: Parallel Updates Protection

from homeassistant.helpers.entity import Entity

class MyEntity(Entity):
    """Example entity with parallel updates protection."""
    
    # Limit concurrent updates to prevent race conditions
    _attr_parallel_updates = 1

Gold Tier

Gold tier represents production-ready integrations with excellent UX:

Key Requirements

  • Devices: Proper device registry integration
  • Diagnostics: Debug information download
  • Discovery: Automatic device discovery support
  • Entity Translations: Translated entity states
  • Exception Translations: User-friendly error messages
  • Reconfiguration Flow: Allow changing settings without removing integration
  • Repair Issues: Proactive issue detection and resolution
  • Comprehensive Documentation: Examples, use cases, troubleshooting

Example: Diagnostics

from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant

from .const import DOMAIN

async def async_get_config_entry_diagnostics(
    hass: HomeAssistant, entry: ConfigEntry
) -> dict:
    """Return diagnostics for a config entry."""
    coordinator = hass.data[DOMAIN][entry.entry_id]
    
    return {
        "entry": {
            "title": entry.title,
            "version": entry.version,
        },
        "data": coordinator.data,
        "device_info": coordinator.device.info,
    }

Platinum Tier

Platinum tier represents the highest quality standards:

Key Requirements

  • Async Dependency: Library must be fully asynchronous
  • Inject Websession: Reuse Home Assistant’s aiohttp session
  • Strict Typing: Complete type hints with mypy validation

Example: Injecting Web Session

from homeassistant.helpers.aiohttp_client import async_get_clientsession

async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
    """Set up from a config entry."""
    # Reuse Home Assistant's aiohttp session
    session = async_get_clientsession(hass)
    client = MyAPIClient(session)
    
    coordinator = MyCoordinator(hass, client)
    await coordinator.async_config_entry_first_refresh()
    
    entry.runtime_data = coordinator
    return True

Quality Scale Files

Integrations track their progress using quality_scale.yaml files:
rules:
  # Bronze
  config-flow: done
  unique-config-entry: done
  runtime-data: done
  test-before-setup: done
  
  # Silver
  config-entry-unloading: done
  reauthentication-flow: done
  test-coverage: done
  
  # Gold
  diagnostics: done
  discovery:
    status: exempt
    comment: |
      This integration does not support automatic discovery
      as devices must be manually configured with API keys.

Special Scales

Internal Scale

Integrations marked as internal are core Home Assistant components:
{
  "domain": "zone",
  "quality_scale": "internal"
}
Internal integrations don’t require quality scale validation.

Legacy Scale

Integrations marked as legacy are maintained but don’t meet modern standards:
{
  "domain": "example_legacy",
  "quality_scale": "legacy"
}
Legacy integrations are discouraged for new development.

Validation

The quality scale is enforced by the hassfest tool:
python3 -m script.hassfest --action validate
This validates:
  • Declared quality scale matches implemented rules
  • All required rules for the tier are completed
  • Documentation matches requirements
  • Test coverage meets minimums

Best Practices

Start with Bronze

New integrations should target bronze tier first:
  1. Implement config flow
  2. Add unique IDs to entities
  3. Use runtime_data pattern
  4. Write basic documentation
  5. Add test-before-setup validation

Progress Gradually

Move up tiers systematically:
  1. Complete all rules in current tier
  2. Update quality_scale.yaml
  3. Run validation: python3 -m script.hassfest
  4. Update manifest.json when tier is complete

Exemptions

Some rules can be exempted with justification:
rules:
  discovery:
    status: exempt
    comment: |
      Clear explanation of why this rule doesn't apply
      to this specific integration.

Resources

Common Pitfalls

Not Using Runtime Data

Wrong: Storing data in hass.data
hass.data.setdefault(DOMAIN, {})
hass.data[DOMAIN][entry.entry_id] = coordinator
Correct: Using entry.runtime_data
entry.runtime_data = coordinator

Missing Parallel Updates

Wrong: No protection against concurrent updates
class MyEntity(Entity):
    async def async_turn_on(self):
        await self.device.turn_on()
Correct: Limited parallel updates
class MyEntity(Entity):
    _attr_parallel_updates = 1
    
    async def async_turn_on(self):
        await self.device.turn_on()

Incomplete Unloading

Wrong: Not unloading platforms
async def async_unload_entry(hass, entry):
    return True
Correct: Proper cleanup
async def async_unload_entry(hass, entry):
    return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
By following the quality scale framework, you ensure your integration meets Home Assistant’s standards for reliability, maintainability, and user experience.

Build docs developers (and LLMs) love