Back to Guides
Pharmacy
Pharmacy Benefits Guide
Complete guide to Pharmacy Benefit Management (PBM) systems. Learn formulary management, drug utilization review, rebate processing, and pharmacy claims adjudication.
Drug Formulary Tiers
1
Tier 1 - Generic Drugs
Lowest cost-sharing for members
Typical copay: $5-$15
2
Tier 2 - Preferred Brand
Preferred brand-name drugs
Typical copay: $25-$50
3
Tier 3 - Non-Preferred Brand
Non-preferred or specialty drugs
Typical copay: $50-$100+
PBM Database Schema
-- Drug Formulary CREATE TABLE formulary ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), plan_id UUID NOT NULL, formulary_name VARCHAR(255), -- Drug ndc VARCHAR(11) NOT NULL, drug_name VARCHAR(500), rxcui VARCHAR(20), -- Tier & Coverage tier INTEGER, -- 1, 2, 3, 4 tier_name VARCHAR(50), covered BOOLEAN DEFAULT TRUE, -- Restrictions prior_auth_required BOOLEAN DEFAULT FALSE, step_therapy_required BOOLEAN DEFAULT FALSE, quantity_limit INTEGER, quantity_limit_days INTEGER, -- Cost Sharing copay_amount DECIMAL(10,2), coinsurance_percent DECIMAL(5,2), -- Status effective_date DATE NOT NULL, termination_date DATE, created_at TIMESTAMP DEFAULT NOW() ); CREATE INDEX idx_formulary_ndc ON formulary(ndc); CREATE INDEX idx_formulary_plan ON formulary(plan_id); CREATE INDEX idx_formulary_tier ON formulary(tier); -- Pharmacy Claims CREATE TABLE pharmacy_claim ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), -- Identifiers claim_number VARCHAR(50) UNIQUE NOT NULL, patient_id UUID NOT NULL, -- Prescription rx_number VARCHAR(50), ndc VARCHAR(11) NOT NULL, drug_name VARCHAR(500), quantity DECIMAL(10,2), days_supply INTEGER, refills_authorized INTEGER, -- Pharmacy pharmacy_ncpdp VARCHAR(7), pharmacy_npi VARCHAR(10), -- Prescriber prescriber_npi VARCHAR(10), prescriber_dea VARCHAR(20), -- Dates fill_date DATE NOT NULL, written_date DATE, -- Pricing ingredient_cost DECIMAL(10,2), dispensing_fee DECIMAL(10,2), total_cost DECIMAL(10,2), -- Adjudication allowed_amount DECIMAL(10,2), paid_amount DECIMAL(10,2), patient_copay DECIMAL(10,2), -- Status status VARCHAR(50), created_at TIMESTAMP DEFAULT NOW() ); CREATE INDEX idx_pharm_claim_patient ON pharmacy_claim(patient_id); CREATE INDEX idx_pharm_claim_ndc ON pharmacy_claim(ndc); CREATE INDEX idx_pharm_claim_fill_date ON pharmacy_claim(fill_date); -- Drug Utilization Review (DUR) CREATE TABLE dur_alert ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), claim_id UUID REFERENCES pharmacy_claim(id), patient_id UUID NOT NULL, -- Alert Details alert_type VARCHAR(100), -- interaction, duplicate, dose severity VARCHAR(20), -- high, medium, low alert_code VARCHAR(20), alert_description TEXT, -- Drug Interaction drug1_ndc VARCHAR(11), drug2_ndc VARCHAR(11), interaction_type VARCHAR(100), -- Resolution override_reason TEXT, overridden_by UUID, override_date TIMESTAMP, created_at TIMESTAMP DEFAULT NOW() ); CREATE INDEX idx_dur_patient ON dur_alert(patient_id); CREATE INDEX idx_dur_severity ON dur_alert(severity); -- Rebates CREATE TABLE manufacturer_rebate ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), manufacturer_id UUID, ndc VARCHAR(11) NOT NULL, -- Rebate Terms rebate_percent DECIMAL(5,2), rebate_amount_per_unit DECIMAL(10,4), -- Period contract_start_date DATE, contract_end_date DATE, -- Volume Requirements minimum_volume INTEGER, created_at TIMESTAMP DEFAULT NOW() );
Point-of-Sale Adjudication
Real-Time Claim Processing (NCPDP D.0)
1.
Patient presents prescription at pharmacy
Pharmacist enters NDC, quantity, days supply
2.
Eligibility verification
Check if patient covered on fill date
3.
Formulary check
Verify drug is covered, check tier and restrictions
4.
DUR screening
Check drug interactions, duplicate therapy, dosing
5.
Pricing & payment
Calculate plan pays, patient copay, return response (~2 seconds)
SQL Query Examples
Check Drug Formulary Status
SELECT f.ndc, f.drug_name, f.tier, f.tier_name, f.copay_amount, f.prior_auth_required, f.step_therapy_required, f.quantity_limit FROM formulary f WHERE f.plan_id = 'plan-uuid' AND f.ndc = '00002-7510-02' AND f.effective_date <= CURRENT_DATE AND (f.termination_date IS NULL OR f.termination_date >= CURRENT_DATE) AND f.covered = TRUE;
Find Drug Interactions for Patient
SELECT
d.alert_type,
d.severity,
d.alert_description,
pc1.drug_name as drug1,
pc2.drug_name as drug2
FROM dur_alert d
JOIN pharmacy_claim pc1 ON d.drug1_ndc = pc1.ndc
JOIN pharmacy_claim pc2 ON d.drug2_ndc = pc2.ndc
WHERE d.patient_id = 'patient-uuid'
AND d.severity IN ('high', 'medium')
AND d.override_date IS NULL
ORDER BY
CASE d.severity WHEN 'high' THEN 1 WHEN 'medium' THEN 2 ELSE 3 END;