Back to all insights
Practice Management 2026-04-29 9 min read

Building CCM/PCM Software: Technical Requirements for Care Coordination Platforms

The engineering requirements for Chronic Care Management (CCM) and Principal Care Management (PCM) software — RBAC, time tracking audit trails, multi-tenant SaaS, and CMS billing documentation.

What Is CCM/PCM Software?

Chronic Care Management (CCM) and Principal Care Management (PCM) are CMS-reimbursed programs that require care coordinators to spend at least 20 minutes per calendar month with eligible Medicare patients — documenting care plan discussions, coordinating across providers, and tracking patient outcomes.

The operational challenge for CCM/PCM companies is not the clinical work. It's the administrative infrastructure: tracking time per patient, managing large staff rosters, allocating patients to coordinators, generating CMS-compliant documentation, and — for scaling companies — doing all of this across a multi-tenant SaaS platform serving multiple health systems.

Generic SaaS tools handle some of this, but companies managing hundreds of coordinators and thousands of patients consistently hit their ceiling. This is the gap that custom CCM/PCM operations software fills — as documented in the CCM/PCM Operations Platform case study.

Requirement 1: Role-Based Access Control (RBAC)

A CCM/PCM platform serves multiple roles with fundamentally different data access needs:

  • Care coordinators: See their assigned patient roster, log time, view and update care plans
  • Managers: See team performance metrics, reassign patients, approve timesheets, flag escalations
  • Billing staff: Access billable minutes per patient, generate CMS documentation, flag billing exceptions
  • Administrators: Full platform access, user management, tenant configuration

RBAC must be enforced at the API layer, not just the UI. A care coordinator whose frontend doesn't show the admin panel should also receive a 403 from the API if they attempt to call admin endpoints directly.

# RBAC middleware in FastAPI
from functools import wraps
from fastapi import HTTPException, Depends

def require_role(*allowed_roles: str):
    def decorator(func):
        @wraps(func)
        async def wrapper(*args, current_user=Depends(get_current_user), **kwargs):
            if current_user.role not in allowed_roles:
                raise HTTPException(
                    status_code=403,
                    detail=f"Role '{current_user.role}' is not authorized for this endpoint"
                )
            return await func(*args, current_user=current_user, **kwargs)
        return wrapper
    return decorator

@app.get("/admin/users")
@require_role("admin")
async def list_all_users():
    ...

@app.get("/manager/team-metrics")
@require_role("admin", "manager")
async def get_team_metrics():
    ...

Requirement 2: Time Tracking With Immutable Audit Trail

CMS reimbursement for CCM (CPT 99490) requires documented time — specifically the date, duration, and activity type for each interaction. The time tracking module must:

  • Record start/stop times with second-level precision
  • Categorize time by activity type (care plan review, provider coordination, patient call, medication management)
  • Prevent retroactive editing without a complete audit trail
  • Generate monthly summaries per patient that meet CMS documentation format requirements

The audit trail requirement is the engineering constraint most teams underestimate. You cannot allow time log records to be deleted — only flagged as erroneous and superseded by corrected entries. Every mutation to the time log table needs an immutable record:

CREATE TABLE time_log_entries (
    id            UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    patient_id    UUID NOT NULL REFERENCES patients(id),
    coordinator_id UUID NOT NULL REFERENCES users(id),
    tenant_id     UUID NOT NULL REFERENCES tenants(id),
    activity_type VARCHAR(50) NOT NULL,
    started_at    TIMESTAMPTZ NOT NULL,
    ended_at      TIMESTAMPTZ NOT NULL,
    duration_secs INTEGER GENERATED ALWAYS AS
                  (EXTRACT(EPOCH FROM (ended_at - started_at))::INTEGER) STORED,
    is_void       BOOLEAN DEFAULT FALSE,
    void_reason   TEXT,
    voided_by     UUID REFERENCES users(id),
    created_at    TIMESTAMPTZ DEFAULT NOW()
    -- No updated_at — records are immutable. Corrections create new rows.
);

Requirement 3: Intelligent Patient Assignment

As a CCM/PCM company scales, patient-to-coordinator assignment becomes a significant operational problem. A coordinator who leaves has their entire roster orphaned. A new coordinator needs a calibrated caseload, not a random batch of the most complex patients.

Intelligent assignment logic accounts for:

  • Current coordinator caseload (patient count + total risk score)
  • Patient complexity (number of chronic conditions, engagement history)
  • Coordinator capacity and specialization
  • Geographic or time zone alignment

At scale, this becomes a scoring and recommendation engine rather than a manual assignment tool. Historical data on coordinator performance and patient engagement can be used to optimize assignments algorithmically — flagging patients who are likely to miss their 20-minute threshold and proactively reassigning them.

Requirement 4: HIPAA-Compliant Multi-Tenant Architecture

If multiple clinic groups or health systems use the same platform instance (the SaaS model), each customer is a separate covered entity and their patient data must be isolated at the database layer, not just the application layer.

The standard PostgreSQL pattern uses row-level security (RLS):

-- Tenant isolation enforced at the DB level
ALTER TABLE patients ENABLE ROW LEVEL SECURITY;

CREATE POLICY tenant_isolation ON patients
    USING (tenant_id = current_setting('app.current_tenant_id')::UUID);

-- Set at connection time from the application session
SET LOCAL app.current_tenant_id = '3f47a9b2-...';

With RLS enabled, even if application code has a bug that forgets to filter by tenant_id, the database will silently return only the current tenant's rows. This satisfies the HIPAA data isolation requirements that hospital security audits verify and also ensures that a multi-tenant breach scenario is structurally prevented at the storage layer.

Each tenant also requires a separate signed HIPAA BAA — the architecture enforces isolation, but the legal agreement still needs to exist per customer relationship.

Requirement 5: CMS Documentation Generation

Monthly billing for CCM and PCM requires generating compliant documentation — a formatted summary of the month's care management activities per patient. The system needs to:

  • Aggregate time logs by patient and calendar month
  • Confirm the 20-minute minimum threshold is met (and flag exceptions)
  • Generate a structured PDF with the required CMS fields
  • Timestamp and digitally identify the generating user
  • Store the document immutably (no post-generation edits)

PDF generation in a Python/FastAPI backend is handled with WeasyPrint or ReportLab, with generated files stored in a KMS-encrypted S3 bucket. The document cannot be deleted — only superseded by a regeneration with an audit record.

The EHR Integration Layer

CCM/PCM platforms that pull care plan data directly from hospital EHR systems (Epic, Cerner) need an EHR integration middleware layer between the platform and the EHR. The CCM/PCM application should not make direct FHIR API calls to Epic — it should call an internal middleware API that handles authentication, FHIR profile mapping, and error handling.

This separation also means the CCM/PCM platform doesn't need to go through Epic App Orchard approval directly — only the middleware service does. See the Epic App Orchard approval guide for what that process involves.

Build vs. Buy

Off-the-shelf CCM platforms work well for companies managing a few hundred patients with a small, stable team. Once you cross ~500 patients or have specific workflows the template doesn't support, per-seat licensing costs and workflow rigidity become real constraints.

Custom-built CCM/PCM software has a fixed build cost and zero ongoing per-seat licensing. For a company at scale, the economics improve dramatically over time — and you own the IP. The Practice Management vs. EHR explainer covers the broader build-vs-buy framing for healthcare operations software.

The Custom Practice Management service includes full CCM/PCM platform architecture — RBAC, time tracking, multi-tenant SaaS conversion, and CMS documentation generation.

Related Service

Custom Practice Management

Deep-dive into our engineering approach, capabilities, and technical specifications.

View Engineering Specs →
SA

Written by Sheharyar Amin

Founder & Lead Engineer, Opexia