---
title: Managed Resource Definitions
weight: 15
state: alpha
alphaVersion: 2.0
description: Enable selective activation of provider resources
---
{{}}
Crossplane v2.0+ enables managed resource definitions by default. This
automatically converts provider CRDs to MRDs during installation. To disable
this
behavior, set `--enable-custom-to-managed-resource-conversion=false` when
installing Crossplane.
{{}}
A `ManagedResourceDefinition` (MRD) is a lightweight abstraction over
Kubernetes CustomResourceDefinitions (CRDs) that enables selective activation of
managed resources. MRDs solve the problem of providers installing hundreds of
CRDs when you only need one or two, reducing API server overhead and improving
cluster performance.
## The CRD scaling problem
Large Crossplane providers can install 100+ managed resource CRDs. Each CRD
consumes about 3 MiB of API server memory and creates API endpoints that affect
cluster performance:
- **Memory pressure**: Large providers can consume 300+ MiB of API server
memory
- **Slower kubectl operations**: Commands like `kubectl get managed` must query
all custom resource endpoints
- **Increased API server load**: More CRDs mean more API endpoints to serve
- **Unnecessary resource overhead**: Most users only need a subset of provider
resources
MRDs address this by allowing providers to ship resource definitions that only
become active CRDs when explicitly needed.
## How MRDs work
An MRD contains the same schema as a CRD but adds two key fields:
- **`connectionDetails`**: Documents what connection secrets the resource
provides
- **`state`**: Controls whether the underlying CRD exists (`Active` or
`Inactive`)
When an MRD's state is `Inactive`, no CRD exists in the cluster. When
activated, Crossplane creates the corresponding CRD and the provider can start
managing instances of that resource.
```yaml
apiVersion: apiextensions.crossplane.io/v1alpha1
kind: ManagedResourceDefinition
metadata:
name: buckets.s3.aws.m.crossplane.io
spec:
group: s3.aws.m.crossplane.io
names:
kind: Bucket
plural: buckets
scope: Cluster
versions:
- name: v1alpha1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
forProvider:
type: object
properties:
region:
type: string
versioning:
type: boolean
connectionDetails:
- name: bucket-name
description: The name of the created S3 bucket
- name: region
description: The AWS region where the bucket was created
state: Inactive # Default state - no CRD created yet
```
## Key characteristics
- **Selective activation**: Only create CRDs for resources you actually need
- **Performance benefits**: Inactive MRDs consume minimal cluster resources
- **Connection details documentation**: Schema for documenting available
connection secrets
- **One-way state transition**: MRDs can go from `Inactive` to `Active` but not
back
## MRD states
### Inactive state
When `state: Inactive` (the default):
- No CRD exists in the cluster
- No API endpoints exist
- The provider doesn't start a controller for this resource
- Minimal memory and CPU overhead
```yaml
spec:
state: Inactive # Default for all MRDs
```
### Active state
When `state: Active`:
- Crossplane creates the corresponding CRD
- API endpoints become available for the resource
- The provider starts a controller to manage instances
- Full capability like traditional managed resources
```yaml
spec:
state: Active # CRD will be created
```
{{}}
MRD state transitions are one-way only. Once an MRD becomes `Active`, it can't
return to `Inactive`. This prevents accidental deletion of CRDs that may have
existing resources.
{{}}
## Connection details documentation
MRDs can document what connection details a managed resource provides. This
helps users understand what data is available in connection secrets without
having to create test resources.
```yaml
spec:
connectionDetails:
- name: endpoint
description: The RDS instance endpoint for database connections
- name: port
description: The port number for database connections
- name: username
description: The master username for database access
- name: password
description: The auto-generated master password
```
{{}}
Connection details are currently a schema-only feature. Most providers
don't yet populate the `connectionDetails` field in their MRDs, but the structure
is available for future implementation.
{{}}
## Working with MRDs
### Viewing MRDs
List all MRDs in your cluster:
```shell
kubectl get managedresourcedefinitions
```
View MRD details:
```shell
kubectl describe mrd buckets.s3.aws.m.crossplane.io
```
### Checking MRD status
MRDs provide status information about their lifecycle:
```yaml
status:
conditions:
- type: Established
status: "False"
reason: InactiveManagedResource
message: "ManagedResourceDefinition is inactive"
```
**Status conditions:**
- **`Established: False, Reason: InactiveManagedResource`**: MRD is inactive,
no CRD created
- **`Established: Unknown, Reason: PendingManagedResource`**: Crossplane is
creating the CRD
- **`Established: True, Reason: EstablishedManagedResource`**: CRD exists and
is ready
- **`Healthy: True, Reason: Running`**: MRD controller operating
- **`Healthy: Unknown, Reason: EncounteredErrors`**: MRD controller
experiencing issues
### Manually activating MRDs
You can manually activate an MRD by changing its state:
```shell
kubectl patch mrd buckets.s3.aws.m.crossplane.io --type='merge' \
-p='{"spec":{"state":"Active"}}'
```
The recommended approach is to use
[ManagedResourceActivationPolicies]({{[}})
for systematic activation.
## How providers work with MRDs
Crossplane v2.0+ automatically converts all provider CRDs to MRDs during
package installation, regardless of the provider's age or original format. The
provider's `safe-start` capability determines the default MRD state:
### Providers with `safe-start` capability
- MRDs start with `state: Inactive` by default
- Support selective activation via
[ManagedResourceActivationPolicies]({{][}})
- Reduced resource overhead for unused resources
- Provider can start without all CRDs being active
```yaml
# Provider package metadata
apiVersion: meta.pkg.crossplane.io/v1
kind: Provider
spec:
capabilities:
- safe-start
```
{{}}
Crossplane uses fuzzy matching for capabilities, so `safe-start`,
`safe_start`, `safestart`, and `SafeStart` all match the `safe-start`
capability.
{{}}
### Providers without `safe-start` capability
- MRDs start with `state: Active` by default (legacy behavior)
- All CRDs become available for backward compatibility
- Full resource overhead like traditional providers
## Troubleshooting MRDs
### MRD exists but no CRD appears
**Symptoms**: MRD is present but `kubectl get ` shows "no
resources found"
**Cause**: MRD is in `Inactive` state
**Solution**: Activate the MRD using an
[ManagedResourceActivationPolicy]({{][}})
or manually patch the state
```shell
# Check MRD state
kubectl get mrd -o jsonpath='{.spec.state}'
# Activate if needed
kubectl patch mrd --type='merge' -p='{"spec":{"state":"Active"}}'
```
### MRD activation fails
**Symptoms**: MRD state is `Active` but `Established` condition remains `False`
**Cause**: CRD creation failed due to schema issues or conflicts
**Solution**: Check MRD events and status for error details
```shell
kubectl describe mrd
```
**Other status conditions for troubleshooting:**
- **`Established: False, Reason: BlockedManagedResourceActivationPolicy`**:
Blocked by activation policy issues
- **`Established: False, Reason: TerminatingManagedResource`**: Crossplane is
deleting the MRD
**Common events you might see:**
- `Normal CreateCustomResourceDefinition` - CRD successfully created
- `Normal UpdateCustomResourceDefinition` - CRD successfully updated
- `Warning CreateCustomResourceDefinition` - CRD creation failed
- `Warning UpdateCustomResourceDefinition` - CRD update failed
- `Warning Reconcile` - General reconciliation errors
Common issues:
- Malformed OpenAPI schema in the MRD
- CRD name conflicts with existing resources
- Insufficient RBAC permissions for Crossplane
### Provider doesn't support activation
**Symptoms**: Provider starts all controllers regardless of MRD states
**Cause**: Provider doesn't implement late activation support
**Solution**: Check provider capabilities and use a compatible provider version
```shell
# Check if provider supports late activation
kubectl get providerrevision \
-o jsonpath='{.status.capabilities}'
```
Look for the `safe-start` capability.
## Next steps
- Learn about
[ManagedResourceActivationPolicies]({{][}})
for systematic resource activation
- See the
[disabling unused managed resources guide]({{][}})
for practical implementation
- Check the [API reference]({{][}}) for complete MRD schema
documentation]