Categories and custom attributes
Every project has metadata that doesn't fit into predefined fields. Cost centres, risk ratings, compliance classifications, custom priority schemes — these vary by organisation and even by project. Raytio PPM handles this through categories and custom attributes, a structured extension mechanism that lets you add typed fields to work items without changing the schema.
The problem: extensible metadata
Standard fields (title, status, dates, work) cover the universal aspects of project management. But organisations need custom fields too:
- A construction company tracks contract type (lump sum, time and materials, cost plus)
- A software team tracks story points and sprint on each work item
- A compliance team tracks regulatory framework (SOX, GDPR, HIPAA) and audit status
These fields are:
- Organisation-specific — different tenants need different fields
- Project-specific — different projects within the same tenant may need different fields
- Type-specific — an epic might need "budget code" while a task needs "skill level"
- Evolving — new fields are added as processes mature
Categories and custom attributes let teams capture this variation at runtime without database migrations, while keeping the stored data typed, validated, and discoverable.
How categories work
Categories are the organising layer that groups related custom attributes together. A category represents a "set of custom fields" that can be applied to work items.
Category structure
| Entity | Purpose |
|---|---|
| Category | A named group of attributes, scoped to a project |
| Category attribute | A single custom field definition within a category (name, type, validation) |
| Category value | The actual value of a category attribute for a specific work item |
Example
A construction project might define two categories:
Category: Contract Management
| Attribute | Type | Values |
|---|---|---|
| Contract type | Select | Lump sum, T&M, Cost plus |
| Contract value | Number | — |
| Contractor | Text | — |
Category: Risk Assessment
| Attribute | Type | Values |
|---|---|---|
| Risk rating | Select | Low, Medium, High, Critical |
| Mitigation status | Select | Open, In progress, Mitigated |
| Review date | Date | — |
A work item can be assigned to both categories simultaneously, giving it all six custom attributes.
Multi-category keying: avoiding collisions
Because a work item can belong to multiple categories, two categories could each define an attribute with the same name (for example, both "Contract Management" and "Risk Assessment" might have a "Status" attribute). Raytio PPM keeps these values distinct through composite keying:
Primary key: (entity_id, category_attr_id)
Where:
entity_idis the work item (or project, or other entity)category_attr_idis the specific attribute definition within a specific category
Because category_attr_id is unique per category, two categories can both have a "Status" attribute with different IDs. The composite key ensures that values from different categories never collide, even when they share the same human-readable attribute name.
Worked example
| entity_id | category_attr_id | value |
|---|---|---|
| WI-42 | contract_mgmt.status (id: 101) | "Active" |
| WI-42 | risk_assessment.status (id: 205) | "Under review" |
Both attributes are named "Status" in their respective categories, but they are stored as separate records because their category_attr_id values differ. There is no ambiguity.
Supported attribute types
Each category attribute has a declared type that controls validation and storage:
| Type | Storage | Validation |
|---|---|---|
| Text | String | Optional max length |
| Number | Decimal | Optional min/max range |
| Date | Date | Optional min/max date |
| Select | String | Must match one of the predefined options |
| Multi-select | Array | Each value must match a predefined option |
| Boolean | Boolean | True or false |
The type system ensures that attribute values are consistent and queryable. A "Contract value" number attribute will always contain a numeric value, enabling aggregation queries like "total contract value across all work items."
Categories vs labels
PPM provides both categories (structured custom attributes) and labels (free-form tags). They serve different purposes:
| Aspect | Categories | Labels |
|---|---|---|
| Structure | Typed attributes with validation | Free-form text tags |
| Scope | Project-scoped | Tenant-scoped |
| Purpose | Structured metadata for reporting and workflows | Lightweight classification and filtering |
| Example | Risk rating = "High" | urgent, blocked, frontend |
Use categories when you need structured, validated, reportable metadata. Use labels when you need quick, informal classification.
Further reading
- Labels vs Categories — the difference between free-form tags and structured classification attributes
- Baselines and variance — baselines capture category values as part of the work item snapshot