Data Modeling Guide
Data Modeling Guide¶
This guide is provided to help navigate introducing new fields, and Entities into the FireFly schema. It’s important when considering expanding on the existing schema the entire schema across AmazonMusic (Including Podcasts, and various other integrations) are considered wholistically.
FireFly is NOT a passthrough service, and so modeling data in FireFly in a manner that copies an upstream service’s will almost always be rejected.
Third Part Lens - No Internal naming conventions¶
The FireFly schema is designed to be contextual and intuitive, this is done by removing all internal/proprietary terminology and aligning the Metadata API with what an end-user that uses the Music App would expect.
As such concepts like customerId, marketplace, and codenames like PCA, SONIC_RUSH, NIGHT_WING, are not exposed through this API. Instead you will find User.ID, markets, and subscription tiers the product offers such as PRIME, and FREE. This is an important distinction compared to modeling an internal API built against a project name.
Identifiers¶
When modeling Entities in FireFly, we should not be exposing named internal identifier names such as globalAsin or seriesAsin. The schema allows for an ID property that can be added on all entities. It is required that this ID be the main interface between a user and an entities metadata.
❌ Don’t:
@ObjectType
Foo {
@Field()
globalAsin: string
@Field()
customerId: string
@Field()
seriesAsin: string
}
✅ Do:
@ObjectType
Foo {
@Field()
Id: string
}
Linking vs Identifiers¶
FireFly is a Graphql aggregation API. We should not be exposing identifiers of children items, for a user to later re-query. Instead provide the connection directly against the type to allow users to expand in the same query. Take advantage of the ‘relational’ aspect of a Graph when modeling your datasets.
❌ Don’t:
@ObjectType
Foo {
@Field()
id: string
@Field()
barId: string
}
✅ Do:
@ObjectType
Foo {
@Field()
Id: string
@Field(Bar)
bar: Bar
}
Reuse existing ObjectTypes¶
Whenever a new entity is added to FireFly that’s an additional layer of complexity that has been introduced, both as a platform as well as an end-user. To reduce the amount of mental fatigue associated with a multitude of models, it’s required the the existing ObjectTypes are evaluated prior to introducing a new type.
❌ Don’t:
@ObjectType
Foo {
@Field()
id: string
@Field()
artist: Artist
}
@ObjectType
Bar {
@Field()
id: string
@Field()
artist: ArtistV2
}
✅ Do:
@ObjectType
Foo {
@Field()
id: string
@Field()
artist: Artist
}
@ObjectType
Bar {
@Field()
id: string
@Field()
artist: Artist
}
Prefer flattening over ObjectTypes¶
There is an implicit bias towards wanting to create a container for metadata that may need to be grouped in the future. Do NOT design for a future use-case, design for your existing use-cases. The Graphql schema is versionless, and so fields can and will be deprecated as the schema evolves.
❌ Don’t:
@ObjectType
Foo {
@Field()
id: string
@Field()
metadata: {
@Field()
isValid: boolean;
}
}
✅ Do:
@ObjectType
Foo {
@Field()
id: string
@Field()
isValid: boolean;
}
