- PKiduuid
- FKcontact_id→ contact
- purposeenum
- statusenum
- captured_attimestamptz
- sourcetext
Capability 02 of 10 · Technology & Intelligence
Custom software and data platforms modelled on your business.
Custom CRMs, customer data platforms and internal tools built around how your business runs. We model the accounts, orders, cases and consents your teams handle, then build each system on that model in your own cloud.
- PKiduuid
- FKcontact_id→ contact
- typetext
- channelenum
- occurred_attimestamptz
- PKiduuid
- FKaccount_id→ account
- stageenum
- amountnumeric
- PKiduuid
- FKcontact_id→ contact
- FKorder_id→ order
- priorityenum
- sla_due_attimestamptz
- PKiduuid
- FKaccount_id→ account
- emailcitext · PII
- IDXemail_sha256text
- phone_e164text
- PKiduuid
- nametext
- tierenum
- regiontext
- PKskutext
- nametext
- pricenumeric
- activeboolean
- PKiduuid
- FKaccount_id→ account
- totalnumeric
- channelenum
- placed_attimestamptz
An illustrative domain model for “Your company”: eight entities. An Account has one or more Contacts and any number of Opportunities and Orders. A Contact has any number of Events, Consents and Cases, and keeps both a deliverable email and a hashed email used for matching. Each Order has one or more order lines, each naming one Product, and a Case may refer to one Order. Beside the model, the same Account is shown as the record form a person would use, with its tier, region, owner team, health score and latest order.

An illustrative shared spreadsheet with CRM export, Billing and Support tabs. A range copied from the CRM export into Billing fails one VLOOKUP (#N/A) because the account name is spelled differently, and Support can only be matched by email.
Why now
Spreadsheets and email approvals cost your teams hours every week.
Custom software usually replaces a shared sheet, an export or an inbox rule that the business has come to depend on. These are the four signs.
-
01
One customer, four IDs.
Sales uses ACC-10442, billing C-88121 and support an email address, so every report starts by matching records.
9.5h / weekReconciling records
-
02
Approvals by email.
Discounts, refunds and credit limits are agreed in reply-all threads, so nobody can say who approved what without searching an inbox.
7h / weekChasing sign-off
-
03
Reports rebuilt every Monday.
Five exports are pasted together by hand, and the numbers are a week old by the time anyone reads them.
6h / weekRebuilding reports
-
04
No trail of changes.
When a price or status changes, nothing records the old value, who changed it or why, so every audit starts from scratch.
4.5h / weekReconstructing changes
Across all four
27 h / week about 0.7 of a full-time role, before a single error is counted
IllustrativeFigures for a 40-person operations team. We measure your own baseline in the first week, before anything is built.
How it works
Internal tools with access control, approvals and an audit log built in.
Each tool is designed for people who use it all day, with keyboard shortcuts for bulk work, instant updates and single sign-on. The six notes below explain each decision.
An illustrative internal case-management tool for “Your company”. A sidebar with saved views; a case list filtered to open P1 and P2 cases in the West region, which is all the signed-in role can see, with three cases selected for a bulk action; the detail of a refund case whose refund above 50,000 was approved by a second person, with its activity timeline; and an append-only, hash-chained audit log. Six numbered notes below explain the design decisions.
What we offer
Six systems we build on one shared data model.
We design the data model first, so reporting, automation and AI all work from the same governed records. Build, buy or extend is decided per module, with the reasons written down.

Custom CRM
Pipelines, accounts, cases and field work modelled on how your teams sell and serve, with the integrations they depend on.
Build or buy
Extend Salesforce or HubSpot when the standard process fits. Build when the process is your advantage or per-seat licence costs grow with every hire.
- store
- PostgreSQL · RLS
- flow
- Temporal: renewals, onboarding
- sync
- Email, calendar, ERP · two-way
Customer data platform
Identity resolution, consented profiles and real-time segments that marketing, sales and service all read from.
Build or buy
Buy a packaged CDP for standard marketing use. Build one on your own warehouse when you need control of identity, consent and cost.
- match
- Deterministic, then scored
- consent
- Checked per purpose
- activate
- Reverse ETL: CRM, email, ads
Internal tools & back-office
Admin consoles, partner portals and back-office tools that replace spreadsheets and email chains, with every action logged.
Build or buy
Use a low-code builder for simple screens over one table. Build when a tool needs permissions, bulk actions, approvals and an audit trail.
- auth
- SSO · SAML 2.0 or OIDC
- work
- Keyboard-first bulk actions
- audit
- Append-only, hash-chained
Workflow & approval systems
Onboarding, refunds, credit and change approvals run as durable workflows with SLAs, escalations and two-person sign-off.
Build or buy
Use your ERP’s workflow when every step sits in one system. Build when a process crosses systems or waits for days.
- engine
- Temporal · Camunda (BPMN)
- timers
- Retries, timeouts, compensation
- rules
- SLAs, escalations as code
Data platform & semantic layer
Data ingestion, a lakehouse and one semantic layer, so every dashboard, model and AI agent uses the same numbers.
Build or buy
Buy managed connectors and a cloud warehouse. Build the models, data contracts and metric definitions, because they describe how your business works.
- ingest
- CDC · Debezium and Kafka
- model
- dbt, tested in CI
- metrics
- Defined once, used everywhere
Legacy modernisation
Monoliths and ageing business systems replaced module by module, with parallel runs and a way back at every step.
Build or buy
Rehost when the system works but its platform is ageing. Rebuild when the data model or process no longer fits the business.
- route
- Strangler-fig facade
- sync
- CDC sync, daily reconciliation
- undo
- Rollback per module, by flag
Customer data demo
Identity resolution that merges eight events into one profile.
A customer data platform must first know who each customer is. Step through a day of events from five channels as they merge into one profile, then change the match rules or withdraw consent.
Interactive demonstration with fictional data. Use Next event, Play all or Reset to step through eight events. Switch the match rules between deterministic only and deterministic plus probabilistic, and switch marketing consent to withdrawn. The status line below the controls announces each change; the profile, segments, destinations and steward queue update to match.
Event 8 of 8 · Web add_to_cart · ck_e913 scored 0.72, below 0.85 · queued for data steward review
Event stream5 channels
Identity graph7 identifiers · 1 profile · 1 in review
Golden profileKnown
- 9b2e…41 · verified at login
- Phone
- +91 ••••• 4471
- Loyalty
- L-20931 · Silver
- Lifetime value
- 4,850
- Last seen
- 21:03 · Email
- Marketing consent
- Granted · 09:14 · signup form
- Web
- App
- Store
- Support
Segments5 of 5
- Known contactsverified emailIn
- Store buyers · 30 daysPOS purchaseIn
- Open support caseticket status openIn
- High intent · 24 h≥ 2 product viewsIn
- Email engaged · 7 daysclick or replyIn
Activationconsent checked per purpose, every sync
- SalesforceCRM · sales and service Purpose · Service Sendsemail, phone, open case Lawful basis: contract Synced Contact + open case · 16:22
- HubSpotMarketing email Purpose · Marketing Sendsemail, list membership Consent granted · 09:14 Synced List: Email engaged · 21:03
- Google AdsCustomer Match Purpose · Marketing Sendsemail_sha256 only Consent granted · 09:14 Synced Audience: High intent · 19:48
- MetaCustom Audiences Purpose · Marketing Sendsemail_sha256 only Consent granted · 09:14 Synced Exclude: recent store buyers
Data steward queue1 waiting
ck_e913 → P-00010.72 / 0.85
Same /24 network · similar session path · different browser
Nothing waiting. Matches that score below 0.85 land here for a person to decide.
Resolution logappend-only
- merge.queued ck_e913 → P-0001 · 0.72 < 0.85
- event.attached campaign_click → P-0001
- identity.linked ck_d201 → P-0001 · 0.91 · probabilistic
- profile.merged P-0002 → P-0001 · email + phone
- profile.created P-0002 · loyalty + phone
Deterministic first
Records join on exact keys, such as a verified login, hashed email, loyalty ID or phone number, so merges are safe to automate.
Probabilistic, with a threshold
Device, network and behaviour data are scored, and links above the agreed threshold are marked inferred; a data steward decides the rest. When values conflict, verified beats typed and newer beats older.
Consent checked on every send
Consent is stored per purpose and checked each time data is sent. A withdrawal stops marketing syncs within minutes and is logged with the rule applied.
- GDPR — General Data Protection Regulation (EU) 2016/679
- DPDP Act 2023 — Digital Personal Data Protection Act, 2023
Data lakehouse
Data platforms with numbers finance can trace.
Every table has an owner, a schema contract and a freshness target. A batch that breaks its contract is held until its owner fixes it.

- Rows today
- 18,406,212
- Contract checks passed
- 1,284
- Batches quarantined
- 1
- Freshness p95
- 6 min
- Lineage coverage
- 100% of gold
An illustrative data platform for “Your company”. Sources (product apps, SaaS, store POS and files) feed ingest (change data capture, batch connectors, event streams) into a medallion lakehouse: Bronze raw tables; a data contract checked on the way into Silver, with batches that fail it held in a quarantine instead; Silver typed and deduplicated tables; and Gold dimensional tables. A semantic layer defines net revenue, active customers and order cycle time once, and BI dashboards, reverse ETL to the CRM, AI agents and the finance close all read from it.
Freshness SLOs per table, monitored
| Table | SLO | Now | State |
|---|---|---|---|
| silver.orders | ≤ 15 min | 6 min | Met |
| silver.customers | ≤ 60 min | 22 min | Met |
| silver.inventory | ≤ 5 min | 3 min | Met |
| gold.fct_revenue | ≤ 24 h | 4 h 10 min | Met |
| gold.dim_product | ≤ 24 h | 21 h 40 min | At risk |
Breaches page the table owner, not a shared inbox.
Data contract checked on every batch
# contracts/silver/orders.yaml
dataset: silver.orders
owner: order-platform@your-company
schema: # all fields required
order_id: { type: uuid, unique: true }
account_id: { type: uuid, ref: accounts }
total: { type: decimal(12,2), min: 0 }
placed_at: { type: timestamptz }
sla:
freshness: 15m
completeness: 99.9%
on_violation: quarantine + page owner
Technologies we work with on data platforms
- Apache Kafka
- Airbyte
- Snowflake
- Databricks
- Google BigQuery
- Apache Airflow
- Apache Spark
- DuckDB
- Looker
- PostgreSQL
- Debezium
- Apache Iceberg
- dbt
- Power BI
Debezium streams database changes into Kafka, and Apache Iceberg keeps lakehouse tables in an open format any engine can read.
Technology stack
Seven technology layers, each choice recorded with its reason.
Every platform we build has the same seven layers. We choose the technology for each one per project, based on what your team can run.
Layers top to bottom · select one
One platform, seven layers · hover or tab in to explode the stack
Layer 01 · Web, mobile and admin screens
Experience
One design system, server-rendered where speed matters, with admin screens generated from the schema and refined by hand. Tools used all day must feel fast on a five-year-old laptop.
- Our default
- React with Next.js and TypeScript
- Something else when
- Flutter or native when the field app must work offline
Technologies we work with here
- React
- Next.js
- TypeScript
- Storybook
- Tailwind CSS
- Flutter
ADR-004Server-render customer screens; admin screens generated from the schemaAccepted
Layer 02 · Domain services and APIs
Services
Service boundaries follow the domain model, in one language your team can hire for and support out of hours.
- Our default
- Node.js with NestJS, or Python with FastAPI
- Something else when
- Go for high-throughput services; Java with Spring or .NET where your platform team already runs them
Technologies we work with here
- Node.js
- NestJS
- FastAPI
- Python
- Go
- Spring Boot
- .NET
- GraphQL
- OpenAPI Initiative
- Apache Kafka
- RabbitMQ
Kafka and RabbitMQ carry async messages between services
ADR-002One service language per team; a second runtime needs a measured reasonAccepted
Layer 03 · Long-running processes
Workflow
Onboarding, approvals and renewals can run for days across systems, so a workflow engine keeps their place through deploys and outages.
- Our default
- Temporal
- Something else when
- Camunda when the business wants to own the BPMN diagrams; a queue and a state table for simple jobs
Technologies we work with here
- Temporal
- Camunda
ADR-007Any process that outlives a request runs as a durable workflowAccepted
Layer 04 · Systems of record
Data stores
PostgreSQL by default, for its row-level security, JSONB and replication. We add a second store only when an access pattern needs it, and record why.
- Our default
- PostgreSQL
- Something else when
- Redis for caches and rate limits; Elasticsearch or OpenSearch for search; MongoDB for document-shaped data when there is a clear reason
Technologies we work with here
- PostgreSQL
- Redis
- Elasticsearch
- OpenSearch
- MongoDB
- Supabase
ADR-001PostgreSQL is the system of record; a second store needs its own ADRAccepted
Layer 05 · Warehouse, models and metrics
Analytics
Models are tested in CI and documented from their schema. Metrics are defined once in a semantic layer, and warehouses pause when idle.
- Our default
- dbt on your cloud warehouse
- Something else when
- Databricks or Spark when data science shares the platform; DuckDB for local runs and CI
Technologies we work with here
- dbt
- Snowflake
- Databricks
- Google BigQuery
- Apache Airflow
- Airbyte
- Apache Spark
- DuckDB
- Looker
- Power BI
Also Apache Iceberg tables
ADR-009Metrics are defined once in the semantic layer; dashboards may not redefine themAccepted
Layer 06 · Who can do what
Identity
Your identity provider stays the source of truth, with single sign-on over SAML or OIDC, SCIM provisioning, short-lived tokens and secrets kept in a vault.
- Our default
- Your identity provider through OIDC
- Something else when
- Keycloak or Auth0 when there is no enterprise identity provider yet, or for customer-facing portals
Technologies we work with here
- OpenID
- Okta
- Auth0
- JWT
- Vault
Also Keycloak · Microsoft Entra ID
ADR-003Authorisation checked in the service, then enforced again by row-level securityAccepted
Layer 07 · Where it runs
Platform
Everything is code in your cloud account. Deploys are reviewed, reversible and monitored, and the same Terraform builds staging and production.
- Our default
- Kubernetes or a managed container service, Terraform, GitHub Actions
- Something else when
- Serverless for spiky, event-driven pieces; a single VM for a tool with twenty users
Technologies we work with here
- Kubernetes
- Terraform
- Docker
- Helm
- Argo
- GitHub Actions
- AWS
- Microsoft Azure
- Google Cloud
- OpenTelemetry
- Grafana
ADR-005No manual changes to production; every change is planned and applied in CIAccepted
Mature technology first
Mature technology runs the platform, so design effort goes where it pays: the domain model, data contracts and workflows.
One store per access pattern
Each store needs a measured reason, because fewer parts mean less to patch, back up and explain to an auditor.
Everything as code
Infrastructure, pipelines, permissions and documentation live in repositories your team owns, reviewed like any other change.
How we use AI
Data governance with agents doing the routine work.
Agents classify data, map lineage and draft contracts and documentation as models change. Named people approve what they propose before it is applied.
Interactive demonstration with fictional data. The columns list shows agent-proposed classifications with confidence. The steward queue has approve and reject buttons that apply or discard a proposal. Run classifier repeats the scan. The status line announces changes. Column-level lineage traces email from crm.contacts.email through bronze and silver to a hashed column in gold used by the Active customers dashboard, and the catalogue answers lineage questions in plain language. A deletion request, DSR-1042, runs across the CRM, the warehouse, the email platform and the ad audiences in order, with a receipt from each sealed into an evidence bundle.
Columns6 of 8 classified
- customer_id uuid — primary key
- email text PII.contact 0.99 pattern + column name
- phone_e164 text PII.contact 0.98 E.164 pattern
- pan_last4 char(4) Payment.truncated 0.97 name + source: payments
- date_of_birth date PII.sensitive 0.96 name + value distribution
- region text — reference data
- lifetime_value numeric Business.metric 0.91 derived in gold · auto-approved by policy
- consent_marketing boolean Consent.purpose 0.99 source: consents · auto-approved by policy
Approval policy policies/classification.yaml
auto_approve:
when: tag in [Business.*, Consent.*]
and confidence ≥ 0.90
otherwise: queue for data_steward
never_auto: [PII.*, Payment.*, Health.*]
Steward queue4 waiting
- Classification Tag email as PII.contact confidence 0.99 · masks in non-prod · 30-day access log Approved · data_steward · 02:14
- Classification Tag pan_last4 as Payment.truncated confidence 0.97 · last four digits only · finance role Approved · data_steward · 02:14
- Classification Tag phone_e164 as PII.contact confidence 0.98 · masks in non-prod
- Classification Tag date_of_birth as PII.sensitive confidence 0.96 · restricts to support lead role
- Draft Data contract silver.customers v4 drafted from the schema and last 30 days of batches
- Draft Column descriptions · 8 of 8 drafted from names, sources and sample values
- Decided this week
- 38
- Median time to decision
- 4 h 10 min
- Applied without a person
- 0 regulated tags
Column-level lineageemail · source to use
›Where does the email in Active customers come from, and is it masked?
dim_customer.email_hash ← silver.customers.email ← bronze.contacts_raw.email ← crm.contacts.email. SHA-256 hashed in gold, masked in non-prod since 02:14. Owner: growth. 1 consumer, 4 sources cited.
Deletion requestDSR-1042 · subject 9b2e…41 · GDPR Art. 17 / DPDP s.12
- CRMreceipt · a91c…
- Warehousereceipt · 4e07…
- Email platformreceipt · c2f8…
- Ads audiencesreceipt · 77d1…
Evidence bundle e7c1…3a sealed · 4 of 4 systems · 38 s
Steward approved pan_last4 → Payment.truncated · restricted to finance role · logged 02:14:07
Data classification
An agent proposes tags from column names, types and sample values; low-risk tags follow policy, and personal or regulated data waits for a named steward.
Contracts and docs from schemas
Agents draft data contracts, column descriptions and lineage from the models and redraft them when a model changes; people edit and sign off.
Deletion with evidence
Deletion requests run across every system holding the person’s data, with a receipt from each to show a regulator under GDPR or the DPDP Act.
Cost and carbon
Lower warehouse bills and less energy.
The practices that cut warehouse bills also cut the energy behind them, so we report cost and carbon side by side for each workload.
- Scanned per day
- 41.8 TB6.2 TB−85%
- Warehouse credits / day
- 15038−75%
- Storage bill / month
- $841$102−88%
- SCI per 1,000 queries
- 182 g47 gCO₂e
Illustrative figures for “Your company”, before and after the policies; the buttons switch the window between the two states. Storage: 38.2 TB before, of which 34.6 TB sat in the hot tier; after tiering and retention, 0.9 TB hot, 2.4 TB warm, 12 TB cold and 3.6 TB archive, with 19.3 TB deleted. Compute: 150 warehouse credits a day before and 38 after, from incremental models, partition pruning and clustering, change data capture merges, auto-suspend and changed-rows-only syncs. Data scanned falls from 41.8 TB to 6.2 TB a day, the storage bill from about $841 to $102 a month, and software carbon intensity from 182 to 47 grams CO₂e per 1,000 queries. The warehouse now runs about 10 of 24 hours a day instead of all 24.
-
Incremental models
Models process only new and changed rows instead of rebuilding a whole table on every run.
materialized='incremental' -
Partition pruning and clustering
Tables are partitioned by date and clustered on common filters, so a dashboard reads only the days it needs.
PARTITION BY DATE(placed_at) -
Auto-suspend warehouses
Compute pauses after a minute idle and resumes on the next query, removing a common source of waste.
AUTO_SUSPEND = 60 -
Retention by policy
Each dataset’s contract sets a retention period, and tiering and deletion run on schedule while respecting legal holds.
retention: 13 months -
Delete what nobody reads
Access logs find tables nobody has queried in six months, and they are deleted once their owners confirm.
0 reads · 180 days
Legacy modernisation
Replace legacy systems one module at a time.
A routing facade sits in front of the old system. Old and new run side by side while traffic moves across in stages, and each old module is retired only when the numbers agree.
-
Customer accounts retired · data archivedaccounts-service live · legacy switched off archive checksum verifiedCustomer accounts: 100% of live traffic on accounts-service. Legacy retired · data archived.
-
Product catalogue read-only · rollback readycatalogue-service live · 100% reconciled daily · 0 diffsProduct catalogue: 100% of live traffic on catalogue-service. Legacy read-only · rollback ready.
-
Orders serving 50%orders-service 50% · by region 4.8 M compared · 0 diffsOrders: 50% of live traffic on orders-service. Legacy serving 50%.
-
Pricing & quotes serving 90%pricing-service canary · 10% of tenants 96,540 compared · 0 diffsPricing & quotes: 10% of live traffic on pricing-service. Legacy serving 90%.
-
Billing & invoicing serving 100%billing-service shadow · reads mirrored 1.9 M compared · 3 diffs openBilling & invoicing: shadow run, no live traffic moved. Legacy serving 100%.
-
Reporting serving 100%data platform · gold marts not started no parallel run yetReporting: 0% of live traffic on data platform · gold marts. Legacy serving 100%.
- Modules on the platform
- 2 of 6
- Live traffic moved
- 43%
- Open diffs
- 3
- Rollbacks
- 1
- Unplanned downtime
- 0 min
Cutover log append-only
- Accounts legacy module retired · 412,908 records archived · billing shadowed through month-end
- Orders at 10%: diff rate 0.3% over the 0.1% budget · flag back to 0% in 40 s · fixed and resumed
- Accounts to 50% · catalogue 10% · orders in shadow on 4.8 M records
Illustrative programmeSix modules over forty weeks for “Your company”. Your own waves follow your risk, release calendar and month-end close.
How we work with you
Model, build, migrate, run.
We agree the domain model before designing any screen, then put one working flow live early. After that, modules are released every sprint.

Notation in our models
- Domain eventorder.placed
- Commandplace order
- Policywhen paid, ship
- Hotspotwho approves?
-
Model the domain
Wk 01–03
Event-storming workshops with the people who do the work map events, commands and rules, then the entities behind them.
- Agents help
- Transcribe the workshop wall into a draft event catalogue and ERD overnight, and flag words the business uses two ways.
- People decide
- Module boundaries, names and which module goes live first.
In your repoEvent-storming board · ERD · Decision records · Quality targets
-
Launch one working flow
Wk 04–08
One working flow goes live behind a feature flag, with single sign-on, production data, CI/CD and monitoring from the first deploy.
- Agents help
- Scaffold admin screens, API clients and contract tests from the schema and the OpenAPI 3.1 spec.
- People decide
- A named engineer approves every merge; users accept the first flow.
In your repoFirst live flow · CI/CD pipeline · Infrastructure as code · Alerts
deploy #1 → prod · flag onboarding.v1 on for 12 users · p95 180 ms
-
Build module by module
Wk 09+ · every sprint
Two-week sprints in priority order end with a demo on production data and a flagged release, and the data model changes only by migration.
- Agents help
- Draft tests, schema migrations, documentation and release notes; propose refactors when a module departs from the model.
- People decide
- Design, priorities and code review. Nothing merges on an agent’s approval.
In your repoModule releases · OpenAPI 3.1 reference · Test suites in CI · Release notes
sprint 06 · 3 modules live · 1,184 tests · 0 failed
-
Migrate in waves
Per module
Rehearsed dry runs, parallel running with nightly reconciliation, then traffic moved in steps; each team is trained before its cutover.
- Agents help
- Compare sampled records between old and new, cluster the differences and summarise them for the owner.
- People decide
- Sign-off per wave; finance approves modules that move money.
In your repoMigration scripts · Reconciliation reports · Rollback plans · Training
wave 3 · 4.8 M rows compared · 0 diffs · signed 14:20
-
Run and improve
Ongoing
Service-level objectives with error budgets, and weekly reviews of adoption and data quality. Your team owns the backlog.
- Agents help
- Triage alerts, draft incident timelines and answer “where does this number come from” from the lineage.
- People decide
- On-call decisions, the roadmap and what to retire.
In your repoSLOs · Runbooks · Adoption dashboard · Architecture reviews
What you get
Code and documentation in your repositories as we go.
The code, data model, contracts and runbooks live in your repositories and cloud accounts, published as one documentation site your team can search.
Domain model
v12 · migratedThe entities, relations and business terms your platform is built on, versioned with the schema so the diagram can never drift from the database.
- Account
- A legal entity that buys from you. Not a login: people are Contacts.
- Order
- A confirmed purchase. Quotes are not orders until accepted.
Model history
v12orders.channel added as an enum: web, app, storemigration 0042 · 2 reviewsv11consents split by purpose, one row per purposemigration 0039 · 2 reviewsv10cases may refer to one order (0..1)migration 0035 · 1 review
API reference
OpenAPI 3.1 · lintedGenerated from the spec the services are tested against, with typed clients for the web app and your integrations.
- GET
/v1/accounts/{id}Read an account - POST
/v1/ordersPlace an order · idempotency key - PATCH
/v1/cases/{id}Update a case · If-Match - GET
/v1/customers/{id}/profileGolden profile · consent-aware
/v1/orders:
post:
operationId: placeOrder
security: [{ oidc: [orders.write] }]
parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
responses:
'201': { $ref: '#/components/responses/Order' }
'409': { description: Request with this key in progress }
'422': { description: Same key, different body }
Data dictionary silver.orders
5 of 5 describedEvery column with its type, meaning, classification and owner. Descriptions are drafted by agents from the schema and approved by the owner.
| Column | Type | Description | Class | Owner |
|---|---|---|---|---|
| order_id | uuid | Primary key, generated at checkout | — | orders |
| account_id | uuid | Buying account; FK accounts.id | — | orders |
| total | decimal(12,2) | Order value incl. tax, in account currency | Business | finance |
| placed_at | timestamptz | When the customer confirmed, UTC | — | orders |
| ship_email | text | Delivery notification address | PII.contact | orders |
Data models & tests
CI · 412 tests passingEvery transformation is SQL in version control, tested on each pull request and documented from its own schema. Gold models carry an enforced contract, so a breaking change fails the build instead of a dashboard.
| Model | Materialised | Tests | Contract | Owner |
|---|---|---|---|---|
| gold.fct_revenue | incremental | 18 | enforced · v3 | finance |
| gold.dim_customer | incremental | 22 | enforced · v4 | growth |
| silver.orders | incremental | 14 | enforced · v3 | orders |
| silver.refunds | table | 9 | — | finance |
Runbook orders CDC lag
Reviewed 12 days agoOne page per alert: what it means, how bad it is, and the exact steps, written for the person on call at night.
Alertcdc_lag_seconds{table="orders"} > 300 for 10m
ImpactDashboards and the CRM show orders late. Nothing is lost; Kafka retains 7 days.
- Check connector status in the Kafka Connect dashboard.
- If the task failed, restart it through the Kafka Connect REST API:
curl -X POST "$CONNECT_URL/connectors/orders-cdc/restart?includeTasks=true&onlyFailed=true" - If the replication slot is growing, page the database owner.
- Confirm lag falls below 60 s, then resolve with a note.
Access matrix
Mapped to controlsWho can do what, enforced in the application and in the database, and reviewed each quarter against your identity provider’s groups.
| Permission | ops_agent | team_lead | finance | admin |
|---|---|---|---|---|
| View cases | own region | Allowed | Allowed | Allowed |
| Bulk assign | Not allowed | Allowed | Not allowed | Allowed |
| Request refund | own region | Allowed | Not allowed | Not allowed |
| Approve refund > 50k | Not allowed | Not allowed | Allowed | Not allowed |
| Export customer data | Not allowed | Not allowed | Not allowed | Allowed |
| Edit price book | Not allowed | Not allowed | Allowed | Not allowed |
Source code
main · checks passingIn your organisation’s repositories from the first commit, with branch protection, required reviews and a changelog. No code sits in ours.
- apps/web · admin
- services/accounts · orders · cases
- workflows/Temporal definitions
- data/dbt models · contracts
- infra/Terraform · Helm
- docs/this site
a41f2c9orders: idempotent place order2 reviews9f07e11cases: bulk assign preview2 reviews71be3d0data: contract v3 for silver.orders1 review
Infrastructure as code
No driftThe same Terraform builds staging and production in your cloud account. Every change is planned in CI, reviewed and applied by the pipeline, never by hand.
$ terraform plan -out=release-42
~ module.orders.aws_ecs_service.api
desired_count: 3 → 4
~ module.data.snowflake_warehouse.bi
auto_suspend: 3600 → 60
Plan: 0 to add, 2 to change, 0 to destroy.
What changes
Measures we agree before we build.
We track four measures in order: adoption, cycle time, data quality and cost. Baselines are measured before anything goes live; targets are set with you and reported monthly.
-
Adoption
Do people choose to use it?
- Weekly active users ÷ people the tool is for%
- Work done beside the tool: exports and side sheetsper week
-
Cycle time
Does the work move faster?
- Quote to cash, median and 90th percentiledays
- Case resolution, median and 90th percentilehours
-
Data quality
Do the numbers agree?
- Identity match rate%
- Freshness SLO attainment% of hours
- Contract failures caught before loadcount
-
Cost
Is it cheaper to run?
- Licences and tools retiredcount
- Warehouse credits per 1,000 queriescredits
- Hours of manual reconciliationper week
Services & packages
Custom software and data services, from CRM to legacy modernisation.
We build CRMs, operations platforms, internal tools and the data platforms behind your reporting. Each follows your process and data model and runs in your cloud.
- Categories
- 04
- Services
- 16
- Packages
- 05
How to buy
- 01Pick services. Enquire about one, or add several to a brief.
- 02Choose a package. A sprint, a fixed project or an ongoing team.
- 03Send the brief. We reply within one working day.
How we work with you
Ways to engage, from a question to an RFQ.
Ask a quick question, send a project brief or issue a formal RFQ. The lead for the work reads each one in full, and any services already in your brief go with it.
Or book a thirty-minute call-
01
For a first conversation, a press request or anything that does not need a scope yet.
You get A reply from a named lead
-
02Recommended
Goals, audiences, a budget band and timing, so our first reply can outline the work.
You get Options and a first scope after one call
-
03
Your documents, deadlines and the procurement and security rules the work must meet.
You get Receipt confirmed and a named bid lead
How it is priced
Each package shows its pricing model. Work starts once a written scope and quote are agreed.
Opens a project brief with this package chosen.
-
In your brief
- Typical length
- 1–3 weeks
- Pricing
- Fixed fee
-
In your brief
- Typical length
- 3–9 months
- Pricing
- Fixed price per milestone
-
In your brief
- Typical length
- 4–12 weeks
- Pricing
- Fixed price
-
In your brief
- Typical length
- 6–18 months
- Pricing
- Programme fee · by statement of work
-
In your brief
- Typical length
- Ongoing · 3-month minimum
- Pricing
- Time & materials
Compare what each package includes
| Package | Every engagement includes | Best for |
|---|---|---|
| SprintA short, fixed-scope engagement that answers one defined question. |
|
Discovery, a diagnostic, a prototype or a decision you need to make soon |
| MilestoneA larger build in phases you approve and pay for one at a time. |
|
Programmes too large for one contract, where you want control at each step |
| ProjectA defined scope, delivered for a fixed price. |
|
Work you can describe up front: an identity, a platform or a set of tools |
| EnterpriseA multi-workstream programme with a dedicated team, governance and agreed service levels. |
|
Large organisations running change across markets, portfolios or business units |
| SquadA dedicated team that works inside your stack and sprint schedule. |
|
Teams with a clear roadmap that need more senior people quickly |
Questions · 8 answered
Custom software and data, from build-or-buy to handover.
What buyers and their engineering teams ask before they commit. Raise anything else on the first call.
Bring to the first call
- The process that hurts most, as people run it today
- A screenshot of the spreadsheet it lives in today
- The systems it touches, and who owns each one
Usually both, decided module by module. Buy where the process is standard and a product fits. Build where the process is your advantage, or where a product would need fragile integrations. We write down the reasoning for each decision.
Yes, and it is often the right call. We keep your system of record and build around it with custom apps on its APIs, two-way data sync and workflows for the gaps. We replace it only when extending it costs more than the fit is worth.
In your own cloud account and databases, in the region you choose. We work inside your accounts with least-privilege access you can revoke, and copy nothing to ours. Personal data can stay in India or the EU as your obligations require. Any cross-border transfer is documented against the DPDP Act 2023 and GDPR.
Module by module, behind a routing facade. We rehearse each data migration, then run old and new side by side with nightly checks on record counts, checksums and sampled fields. Traffic moves across by percentage, and any module can be rolled back with a flag change until the old one is retired.
Start with the warehouse or lakehouse, which holds your governed data. A customer data platform (CDP) adds identity resolution, consent and audience syncing on top. A packaged CDP suits standard marketing use; a composable one on your own warehouse gives you control of identity, consent and cost. You can add the CDP once warehouse data is trusted.
For routine data housekeeping, approved by a named engineer. Agents classify columns, draft data contracts, documentation and tests, compare migration samples and answer lineage questions. They never approve their own work, merge code or change access, and every action is logged with its inputs.
Your team or ours. Your team takes over with the documentation site, runbooks and a handover period in which they lead and we support. Or our engineers run it under Integration & Support, from the same repositories and on-call runbooks. Explore Integration & Support
Typically within 2 months for a thin slice: one working flow with single sign-on and live data. A first release of the core modules typically lands in 12–24 weeks, depending on how many systems it replaces.
Tell us what you need built.
You will speak to a lead who would run the work, and get a straight answer on fit.
Three ways to start
Every engagement starts with a written scope and a quote agreed before work begins.
Choose one of the three ways above


