Skip to main content

Purpose

The Content Service is the authoritative owner of the content record after the media pipeline completes. It manages the content metadata lifecycle from DRAFT through to PUBLISHED and DELETED, enforces content visibility rules, and serves as the data source for discovery flows (search, feed, related content). The Content Service does not handle media bytes — it references object storage locations, not file content.

Responsibilities

ResponsibilityDetail
Content record ownershipMaintains the canonical content record: title, description, tags, category, language, visibility, content_type (VIDEO/AUDIO), publication status, and storage references.
Publication status managementTransitions content through statuses (DRAFTPROCESSINGPUBLISHEDUNLISTEDDELETED) in response to pipeline events and creator or admin actions.
Visibility enforcementEnforces PUBLIC, UNLISTED, and PRIVATE visibility at read time. Unlisted content is accessible only via direct URL. Private content is accessible only to the owning creator.
Search indexingOn PUBLISHED status, triggers a document write to Elasticsearch containing: content_id, title, description, tags, category, content_type, creator_id, language, publish_timestamp.
ML feed integrationReturns ranked content IDs from the ML Inference Service to serve the home feed API via a thin pass-through. The Content Service does not perform ranking — it fetches metadata for pre-ranked IDs provided by the ML layer.
Content deletionCreator-initiated or admin-initiated deletion: marks record as DELETED, triggers CDN cache invalidation, and emits a deletion event for downstream consumers (ML Feature Store, Elasticsearch, Engagement Service) to clean up associated data.

API Surface

MethodEndpointAuthDescription
GET/api/v1/content/{contentId}Bearer or None (public)Fetch content metadata
PATCH/api/v1/content/{contentId}Bearer (Creator, owner only)Update title, description, tags, or thumbnail
DELETE/api/v1/content/{contentId}Bearer (Creator / Platform Admin)Delete content
GET/api/v1/content/feedBearerPersonalised home feed (ML-ranked)
GET/api/v1/content/trendingBearer or NoneTrending content list
GET/api/v1/content/searchBearer or NoneFull-text search with filters
GET/api/v1/content/{contentId}/relatedBearer or NoneML-ranked related content
PATCH/api/v1/content/{contentId}/visibilityBearer (Creator)Change visibility (PUBLIC / UNLISTED / PRIVATE)

Data Owned

StoreSchema
Postgrescontent (content_id, creator_id, title, description, tags[], category, language, content_type, visibility, status, manifest_url, thumbnail_url, residency, published_at, deleted_at)
ElasticsearchContent documents indexed by content_id; full-text search across title, description, tags, category
RedisTrending list cached at 5-minute TTL; static content metadata at 1-hour TTL

Kafka Topics

TopicAction
media.drm.packagedConsumed — triggers status transition to PUBLISHED
media.publishedProduced — fan-out to ML Feature Store, Notification Service, Search Indexer
moderation.flaggedConsumed — triggers status transition based on moderation decision

Failure Behaviour

FailureBehaviour
Elasticsearch unavailableSearch and discovery APIs return 503. Home feed falls back to trending list. Playback is unaffected — playback does not depend on Elasticsearch.
ML Inference Service unavailableHome feed falls back to the trending content list. Graceful degradation per Principle 11.
Content record missing at playbackPlayback Service receives a 404 from Content Service. Client receives a clear not-found error.

Build docs developers (and LLMs) love