Adding Required Traits to Ory Kratos Without Breaking Existing Profiles
Add new required traits to Ory Kratos identity schemas without blocking existing users during profile updates.
20 Dec 2025, 00:15 UTC

Required Traits Can Lock Out Existing Users
You add phone_number as a required trait to your Ory Kratos identity schema. New registrations succeed only when the field is present, but existing users who never supplied a phone number now hit a validation error the next time they open the settings flow. The useful takeaway is that schema changes in Ory Kratos are not retroactive migrations; they are new contracts that apply when an identity is created or updated. Roll out required traits in stages instead of flipping a single switch.
Ory Kratos stores user identities as JSON objects. The shape of those objects is governed by an identity schema, a JSON Schema file referenced in your Kratos configuration. Fields inside an identity are called traits. Self-service flows such as registration and profile settings validate traits against that schema before the identity is written or changed.
Why Existing Profiles Break
When you mark a trait as required, Kratos enforces it on the next write. A legacy identity that lacks the trait is still valid under the old schema, but if the user opens the profile settings flow and submits an update, Kratos validates the updated identity against the current schema. The missing required trait causes the flow to return a validation error, so the user cannot save even unrelated changes.
This behavior differs between deployment types. Ory Network manages schema files through the Ory Console. Self-hosted deployments load schemas from filesystem paths or URLs defined in kratos.yml. In both cases, existing identities are not automatically updated when the schema file changes.
A Staged Rollout Pattern
Use this sequence to add a required trait without blocking existing users:
- Add the trait to the schema as optional, with a format constraint such as a regular expression.
- Deploy the schema and let new users supply the value during registration.
- Backfill existing identities through an admin process or invite users to supply the value voluntarily.
- Once most identities have the trait, move it into the
requiredarray and redeploy the schema.
This pattern works because optional traits do not fail validation when absent. Existing users can continue updating their profiles while the new data is collected.
Worked Example: E.164 Phone Number
Suppose you want a phone number stored in E.164 format. First, add it as optional:
{
"$id": "https://example.com/schemas/identity.json",
"type": "object",
"properties": {
"traits": {
"type": "object",
"properties": {
"phone_number": {
"type": "string",
"pattern": "^\\+[1-9]\\d{1,14}$",
"description": "Phone number in E.164 format"
}
}
}
}
}Note: depending on your Kratos version and schema layout, traits may appear directly under the root object rather than nested inside a traits key. Inspect your active schema file before copying this structure.
Where to run: Your self-hosted Kratos host or Ory Network tenant endpoint.
Permissions: Public registration requires no authentication. Updating an existing profile requires an authenticated session. Admin-backed identity updates require an Ory Network API token or access to the self-hosted admin port.
Expected check: Submit a registration request without phone_number. The self-service flow should complete because the trait is optional. Then submit an update that includes phone_number with an invalid value such as 555-0100. The flow should return a schema validation error mentioning the pattern, not a successful update.
Risk: An incorrect schema path in kratos.yml can prevent Kratos from loading the contract, which may disable validation or produce startup errors. Verify the path before restarting.
Limitations and Verification
JSON Schema dialect support depends on the Ory Kratos version. Conditional keywords such as if, then, and else may not be available in older releases. Custom traits describe identity attributes only; they do not replace credentials, sessions, or authentication policies.
To verify the result, inspect your active identity schema reference in kratos.yml or the Ory Console. Then submit a registration request that omits a newly required field. The flow must return a validation error rather than creating the identity. Next, open the settings flow for an existing identity that lacks the field and confirm the update is blocked until the trait is provided. If you moved a trait from optional to required, confirm that identities already containing the value can still update their profiles.
Schema evolution in Ory Kratos is a data-migration problem disguised as a configuration change. Add traits as optional, backfill carefully, and tighten the contract only after existing users have had a chance to comply.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.