Skip to main content

Cube.dev Semantic Layer

Cube.dev provides a pure semantic layer on top of the dbt-transformed data, enabling consistent metrics, caching, and multi-protocol access for analytics and AI agents.

Enterprise Feature

Cube.dev semantic layer is available in Enterprise editions.


Overview

Cube sits between the Gold layer and consuming applications, providing:

  • Consistent Metrics: Single source of truth for measures
  • Caching: Pre-aggregations for fast queries
  • Multi-Protocol Access: REST API, GraphQL, SQL API

Cube Semantic Layer


Architecture

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│ PostgreSQL │────▶│ Cube.dev │────▶│ Consumers │
│ (Gold Layer) │ │ Semantic │ │ • REST API │
│ │ │ Layer │ │ • SQL API │
│ dim_*, fact_* │ │ │ │ • MCP Server │
│ sem_* │ │ Cubes/Views │ │ • BI Tools │
└─────────────────┘ └─────────────────┘ └─────────────────┘

Available Cubes

Dimension Cubes

CubeSourceDescription
Studiesdim_studyClinical study master data
Subjectsdim_subjectStudy subject demographics
Sitesdim_siteTrial site information
Patientsdim_patientPatient records
Datesdim_dateDate dimension

Fact Cubes

CubeSourceDescription
Enrollmentsfact_enrollmentEnrollment events
AdverseEventsfact_adverse_eventAdverse event records
Visitsfact_visitStudy visit data
VitalSignsfact_vital_signVital sign measurements
LabTestsfact_lab_resultLaboratory test results
Medicationsfact_medicationConcomitant medications

CDISC Cubes

CubeSourceDescription
CdiscDmcdisc_dmDemographics domain
CdiscAecdisc_aeAdverse Events domain

Measures & Dimensions

Key Measures

CubeMeasureDescription
StudiescountTotal studies
SubjectscountTotal subjects
Enrollmentscount, enrollmentRateEnrollment metrics
AdverseEventscount, seriousCountSafety metrics
Visitscount, completionRateVisit metrics

Key Dimensions

CubeDimensionType
StudiesstudyName, phase, statusString
Subjectssex, ageGroup, enrollmentStatusString
AdverseEventsseverity, causality, isSeriousString/Boolean

Sample Queries

Natural Language → Cube Query

Natural LanguageCube Query
"How many studies do we have?"Studies.count
"Total enrolled subjects"Subjects.count with filter isEnrolled = true
"Adverse events by severity"AdverseEvents.count by AdverseEvents.severity
"Enrollment by study and month"Enrollments.count by Studies.studyName, Dates.month
"Sites with most subjects"Subjects.count by Sites.siteName ordered DESC

REST API Example

curl -X POST http://localhost:4000/cubejs-api/v1/load \
-H "Content-Type: application/json" \
-d '{
"query": {
"measures": ["Enrollments.count"],
"dimensions": ["Studies.studyName"],
"limit": 10
}
}'

SQL API Example

-- Connect via psql to port 15432
SELECT
study_name,
COUNT(*) as enrollments
FROM Enrollments
GROUP BY study_name
ORDER BY enrollments DESC;

Deployment

The Cube.js Docker image is self-contained — it bakes in both the cube.js config and the model/ directory at build time so no cross-repo volume mounts are needed at runtime.

AspectDetail
Source repoctms-data-pipeline-ai-analytics/ctms-cube/
Docker imagezynomi/ctms-cube (Docker Hub)
Base imagecubejs/cube:v0.35.81
CI workflowdocker-build-ctms-cube.yml — builds on push to ctms-cube/**
Profileanalytics
Port4000 (host and container)

The image extends the official Cube image and copies in:

  • cube.js — connection config (reads CUBEJS_* env vars at runtime)
  • model/ — all .yml cube definitions (Studies, Subjects, Enrollments, etc.)
Cross-Repo Dependency

Cube models live in ctms-data-pipeline-ai-analytics, not in ctms.devops. When models change, push to that repo and the CI workflow rebuilds the image automatically.


API Endpoints

EndpointPortDescription
Playground4000Visual query builder
REST API4000/cubejs-api/v1JSON API
SQL API15432PostgreSQL-compatible
Health4000/readyzHealth check