Skip to content
GitLab

Sales Analytics

A complete working example of an Akili data product. Ingests order and customer data from a source database via change data capture, aggregates into daily metrics by region and segment, enforces quality gates, and serves via the analytics engine and a lookup store.

%%{init: {'flowchart': {'curve': 'basis'}}}%%
flowchart LR
    subgraph Source["Source Database"]
        ORDERS[orders]
        CUSTOMERS[customers]
    end

    subgraph Akili["Akili Platform"]
        CDC[Change Data Capture] --> TRANSFORM[SQL Transform]
        TRANSFORM --> QUALITY[Quality Gates]
        QUALITY --> LAKE[Data Lake]
    end

    subgraph Serving["Serving Stores"]
        SR[Analytics Engine]
        PG[Lookup Store]
    end

    ORDERS --> CDC
    CUSTOMERS --> CDC
    LAKE --> SR
    LAKE --> PG

Every Akili data product is defined by 6 YAML manifests in a .akili/ directory. Here is the complete set for the sales analytics product.

Product identity — name, domain, classification, and ownership.

apiVersion: akili/v1
kind: DataProduct
metadata:
name: daily-order-summary
domain: sales
version: 1.0.0
description: >
Daily aggregated order metrics by region and product category.
Consumes orders and customers from the production database via change data capture.
owner: data-engineering@acme-corp.com
classification: internal
tags:
- sales
- analytics
- daily

Two connector inputs from a production relational database. Orders use change data capture; customers use incremental sync.

apiVersion: akili/v1
kind: Inputs
inputs:
- name: orders
type: connector
connection: production_db
resource: public.orders
ingestion:
strategy: cdc
columns:
- order_id
- customer_id
- product_id
- quantity
- unit_price
- total_amount
- region
- order_date
- created_at
- name: customers
type: connector
connection: production_db
resource: public.customers
ingestion:
strategy: incremental
cursor_field: updated_at
columns:
- customer_id
- name
- segment
- country

The output schema contract — columns, types, and roles.

apiVersion: akili/v1
kind: Output
columns:
- name: date
type: TIMESTAMP_TZ
role: event_time
- name: region
type: STRING
role: dimension
- name: customer_segment
type: STRING
role: dimension
- name: order_count
type: BIGINT
role: metric
- name: unique_customers
type: BIGINT
role: metric
- name: total_units
type: BIGINT
role: metric
- name: total_revenue
type: DECIMAL
role: metric
- name: avg_order_value
type: DECIMAL
role: metric

Quality checks enforced after every pipeline run. Critical checks block data promotion; warnings are logged but don’t block.

apiVersion: akili/v1
kind: Quality
checks:
- name: no_null_dates
type: sql
sql: "SELECT COUNT(*) FROM {{ this }} WHERE date IS NULL"
severity: critical
threshold: 0
- name: positive_revenue
type: sql
sql: "SELECT COUNT(*) FROM {{ this }} WHERE total_revenue < 0"
severity: critical
threshold: 0
- name: reasonable_order_count
type: sql
sql: "SELECT COUNT(*) FROM {{ this }} WHERE order_count > 1000000"
severity: warning
threshold: 0
sla:
freshness: 24h
completeness: 0.99

Analytical intent routes queries to the analytics engine (StarRocks). Materialization keeps results fresh.

apiVersion: akili/v1
kind: Serving
intent: analytical
materialization:
enabled: true
refresh_interval: "1h"

SQL transform with schedule and resource allocation. The transform joins orders and customers and aggregates into daily metrics.

apiVersion: akili/v1
kind: Compute
engine: sql
entrypoint: logic/transform.sql
schedule: "0 6 * * *" # Daily at 6 AM UTC
resources:
cpu: "1"
memory: 2Gi
retries: 2

The SQL transform uses {{ ref() }} to reference upstream inputs:

-- logic/transform.sql
SELECT
DATE_TRUNC('day', o.order_date) AS date,
o.region,
c.segment AS customer_segment,
COUNT(DISTINCT o.order_id) AS order_count,
COUNT(DISTINCT o.customer_id) AS unique_customers,
SUM(o.quantity) AS total_units,
SUM(o.total_amount) AS total_revenue,
AVG(o.total_amount) AS avg_order_value
FROM {{ ref('orders') }} o
LEFT JOIN {{ ref('customers') }} c ON o.customer_id = c.customer_id
GROUP BY 1, 2, 3

Classification, team access grants, and ownership are declared in product.yaml.metadata (see above). There is no separate governance file.

  1. Initialize the project

    Terminal window
    mkdir daily-order-summary && cd daily-order-summary
    akili init --name daily-order-summary

    Replace the generated manifest templates with the files above.

  2. Validate manifests

    Terminal window
    akili validate .akili/
  3. Create the product in the platform

    Terminal window
    akili product create \
    --name daily-order-summary \
    --namespace sales
  4. Deploy

    Terminal window
    akili product deploy daily-order-summary
  5. Trigger an execution

    Terminal window
    akili run trigger daily-order-summary
  6. Query results via API

    Terminal window
    curl -H "Authorization: Bearer $TOKEN" \
    "https://api.akili.systems/api/v1/analytics/query" \
    -d '{"sql": "SELECT region, SUM(total_revenue) FROM daily_order_summary GROUP BY region"}'