Skip to content

Solution 02: BookBridge Education Foundation

AI-Generated Content — Use for Reference Only

This content is AI-generated and has only been validated by AI review processes. It has NOT been reviewed or validated by certified Salesforce CTAs or human subject matter experts. Do not rely on this content as authoritative or completely accurate. Use it solely as a reference point for your own study and preparation. Always verify architectural recommendations against official Salesforce documentation.

Solution Context

Heavy domains: D5 Integration, D6 Dev Lifecycle | Difficulty: Beginner Time budget: 180 minutes | Key frameworks: 9 Essential Artifacts, Five-Finger Method

Attempt the Scenario First

If you have not yet worked through the scenario paper, stop here. Set a 180-minute timer and build your own solution before reading this one.

Assumptions

  1. Salesforce Nonprofit Cloud (NPC) — current-generation platform built on Industries Cloud (not legacy NPSP). Pre-built donation management, constituent modeling, and grant tracking at nonprofit pricing
  2. MuleSoft Composer for integration middleware — visual middleware for an 8-person team with no integration experience. Rejected Anypoint Platform (budget $1.2M/18 months cannot absorb enterprise licensing). Rejected point-to-point (6+ systems = 15 possible connections = unmaintainable)
  3. Single Experience Cloud site for school and volunteer portals with audience-based visibility — reduces licensing cost vs two separate sites
  4. Retain Stripe for payment processing — working system, no benefit to replacing during migration
  5. Keep ShelfTrack Cloud as the warehouse system — working SaaS with documented API; integrate, do not replace

Key Architectural Decisions

Decision 1: Hub-and-Spoke Integration (D5 — HEAVY)

MuleSoft Composer as the central hub because BookBridge has 6 systems with different protocols and anticipates adding 2-3 per year (Req 41). Every system connects to the hub, not to each other. Adding a new system requires one connection.

SystemProtocolPatternDirectionVolume
StripeWebhooks + RESTEvent-DrivenInbound2K-12K/day
ShelfTrackREST v3.1 + WebhooksEvent-Driven + PollingBidirectional~4,700/day
School DistrictsSFTP + CSVBatch ETL (via Anypoint SFTP connector — Composer lacks SFTP support)InboundMonthly (15 districts)
QuickBooksREST + OAuth 2.0Scheduled BatchOutboundWeekly
MailChimpREST v3.0 + WebhooksEvent-Driven + BatchBidirectional~2.5M emails/mo
EventbriteREST + WebhooksEvent-DrivenInbound~120 events/yr

Judge Signal

Judges want each integration classified by protocol, pattern, and direction. Saying “we’ll integrate everything with MuleSoft” without this breakdown will fail. They also want to see the SFTP challenge addressed specifically — it is a different protocol class from REST.

Decision 2: SFTP Staging Pipeline (D5)

SFTP staging pipeline with staging object pattern for the 15 district SFTP feeds, each in a different format (Req 36).

MuleSoft Composer Does Not Support SFTP

MuleSoft Composer does not have a native SFTP connector — it supports REST/webhook-based SaaS systems (Stripe, Salesforce, Slack, etc.) but not SFTP. The SFTP district feeds require either: (a) MuleSoft Anypoint Platform (runtime-level SFTP connector) for this specific integration, retaining Composer for simpler REST integrations; or (b) a lightweight scheduled script or Salesforce-native solution (e.g., Apex + external SFTP library, or a third-party AppExchange SFTP tool) that downloads files and loads into a staging object. Option (a) is recommended if the budget allows a limited Anypoint license; option (b) is the budget-constrained fallback.

  1. SFTP files retrieved on schedule (via Anypoint SFTP connector or scheduled script)
  2. District-specific transformation mapping (15 mappings) transforms files
  3. Records land in District_Data_Staging__c staging object
  4. Validation Flow checks for anomalies (>50% student count drop, missing fields)
  5. Clean records promote to production School__c; flagged records route to manual review

Staging decouples ingestion from consumption — a bad file is contained in staging, not production.

Decision 3: Year-End Campaign Resilience + Environment Strategy (D5 + D6 — HEAVY)

Async event-driven donation processing for the year-end spike (12K/day, ~750/hour): Stripe webhooks received by Composer, pushed as Platform Events into Salesforce with built-in replay (72-hour retention). Migration must NOT happen during November-January — recommend spring cutover with old GiveHub running through one complete year-end cycle.

4-environment strategy with DevOps Center for a team new to Salesforce development (grew from 3 to 8 in 6 months):

EnvironmentTypePurpose
DEV (x3)Developer Pro SandboxesIndividual developer work
QA/TESTPartial CopyIntegration testing, QA validation
UATPartial CopyBusiness stakeholder acceptance
PRODProductionLive system

Chose DevOps Center over custom CI/CD (GitHub Actions + SFDX) because the team has zero prior experience. DevOps Center provides visual work item tracking and deployment pipeline as a stepping stone. 2-week release cadence with QA gate, UAT business approval, and rollback plan per release.

Judge Signal

Dev lifecycle judges want to see you acknowledge the team maturity gap. Prescribing enterprise-grade CI/CD for a team that just learned what a sandbox is will be viewed as tone-deaf.

Critical Diagrams

System Landscape

graph TB
    subgraph SF["Salesforce Nonprofit Cloud (NEW)"]
        NPC["🟢 Nonprofit Cloud (NEW)"]
        EC["🟢 Experience Cloud Portal (NEW)<br/>School Partners + Volunteers"]
        PE["🟢 Platform Events (NEW)"]
    end

    subgraph Hub["Integration Layer"]
        MSC["🟠 MuleSoft Composer<br/>(NEW — Integration Hub)"]
    end

    subgraph External["External Systems"]
        Stripe["⚪ Stripe (KEEPING)"]
        ST["⚪ ShelfTrack Cloud (KEEPING)"]
        SFTP["⚪ 15 School Districts SFTP (KEEPING)"]
        QB["⚪ QuickBooks Online (KEEPING)"]
        MC["⚪ MailChimp (KEEPING)"]
        EB["⚪ Eventbrite (KEEPING)"]
    end

    subgraph Retiring["Retiring Systems"]
        GH["🔴 GiveHub (RETIRING)<br/>Rails 5.2 EOL — Custom Donation App"]
        GS["🔴 City Google Sheets (RETIRING)<br/>Volunteer Hour Tracking"]
        WB["🔴 Whiteboards + Spreadsheets (RETIRING)<br/>Manual Processes"]
    end

    subgraph Legend
        direction LR
        NEW["🟢 NEW - Being Built"]
        KEEP["⚪ KEEPING - No Changes"]
        RETIRE["🔴 RETIRING - Decommissioning"]
        INT["🟠 INTEGRATION LAYER"]
    end

    Stripe -->|"Webhooks, OAuth 2.0<br/>2K-12K donations/day"| MSC
    ST <-->|"REST v3.1 + Webhooks<br/>~4,700 transactions/day"| MSC
    SFTP -->|"SFTP, batch<br/>Monthly from 15 districts<br/>(Anypoint SFTP connector)"| MSC
    QB <-->|"REST, OAuth 2.0<br/>Weekly journal entries"| MSC
    MC <-->|"REST v3.0 + Webhooks<br/>~2.5M emails/month"| MSC
    EB -->|"Webhooks<br/>~120 events/year"| MSC

    MSC -->|"Platform Events"| PE
    PE --> NPC
    NPC --> EC
    GH -.->|"500K donors migrated to SF"| NPC
    GS -.->|"Volunteer data migrated"| NPC
    WB -.->|"Replaced by SF workflows"| NPC

Integration Architecture (Hub-and-Spoke)

graph TB
    subgraph External["External Systems"]
        Stripe["⚪ Stripe (KEEPING)"]
        ST["⚪ ShelfTrack Cloud (KEEPING)"]
        SFTP["⚪ 15 School Districts SFTP (KEEPING)"]
        QB["⚪ QuickBooks Online (KEEPING)"]
        MC["⚪ MailChimp (KEEPING)"]
        EB["⚪ Eventbrite (KEEPING)"]
    end

    subgraph Hub["MuleSoft Composer — Integration Hub"]
        DH["🟠 Donation Handler"]
        WH["🟠 Warehouse Sync"]
        ETL["🟠 District ETL"]
        FIN["🟠 Finance Sync"]
        MKT["🟠 Marketing Sync"]
        VOL["🟠 Volunteer Sync"]
        ERR["🟠 Error Handler + Retry"]
    end

    subgraph SF["Salesforce Nonprofit Cloud"]
        PE["🟢 Platform Events"]
        Core["🟢 Core Objects"]
        Staging["🟢 Staging Objects"]
        EC["🟢 Experience Cloud Portal"]
    end

    Stripe -->|"Webhooks, OAuth 2.0<br/>Real-time, 2K-12K/day<br/>Donor + amount + campaign"| DH
    ST <-->|"REST v3.1 + Webhooks<br/>Bidirectional, ~4,700/day<br/>Inventory + shipments"| WH
    SFTP -->|"SFTP + CSV, batch<br/>Monthly, 15 districts<br/>(via Anypoint SFTP connector)"| ETL
    QB <-->|"REST, OAuth 2.0<br/>Scheduled weekly<br/>Journal entries + fund coding"| FIN
    MC <-->|"REST v3.0 + Webhooks<br/>Bidirectional<br/>Segments out, engagement in"| MKT
    EB -->|"Webhooks<br/>Event-driven<br/>Registrations + check-ins + hours"| VOL

    DH -->|"Platform Events"| PE
    WH -->|"Platform Events"| PE
    ETL -->|"Batch load"| Staging
    FIN <-->|"REST sync"| Core
    MKT <-->|"Sync"| Core
    VOL -->|"Platform Events"| PE
    PE --> Core
    Staging -->|"Validation Flow"| Core
    Core --> EC
    ERR -.->|"Retry queue"| DH

CI/CD Pipeline

graph LR
    DEV[Dev Sandboxes x3] -->|Commit| GH[GitHub Feature Branches]
    GH -->|DevOps Center Promote| QA[QA Sandbox]
    QA --> AT{Tests Pass?}
    AT -->|Yes| UAT[UAT Sandbox]
    AT -->|No| DEV
    UAT --> BIZ{Stakeholder Approval?}
    BIZ -->|Approved| PROD[Production]
    BIZ -->|Rejected| DEV

Data Model

erDiagram
    CONTACT ||--o{ DONATION : "donor (Lookup)"
    CONTACT ||--o{ VOLUNTEER_ACTIVITY : "volunteer (Lookup)"
    CONTACT ||--o{ CAMPAIGN_MEMBER : "member (Lookup)"
    CAMPAIGN ||--|{ CAMPAIGN_MEMBER : "has (M-D)"
    DONATION ||--o{ BOOK_DONATION : "linked to (Lookup)"
    BOOK_DONATION ||--o{ INVENTORY_ITEM : "warehouse intake (Lookup)"
    INVENTORY_ITEM ||--o{ DISTRIBUTION_RECORD : "shipped as (Lookup)"
    SCHOOL ||--|{ DISTRIBUTION_RECORD : "recipient (M-D)"
    SCHOOL ||--o{ BOOK_REQUEST : "submitted by (Lookup)"
    SCHOOL }|--o{ SCHOOL_DISTRICT : "belongs to (Lookup)"
    SCHOOL_DISTRICT ||--o{ DISTRICT_DATA_STAGING : "ingested from (Lookup)"
    CONTACT ||--o{ CORPORATE_SPONSORSHIP : "sponsor contact (Lookup)"
    ACCOUNT ||--|{ CORPORATE_SPONSORSHIP : "sponsor org (M-D)"
    CONTACT ||--o{ GRANT : "grant manager (Lookup)"
    CAMPAIGN ||--o{ DONATION : "campaign source (Lookup)"

    CONTACT {
        string Name "Unified constituent profile"
        string OWD "Private"
        string Volume "500K donors plus 2800 volunteers"
        string Dedup "Fuzzy match across 3 systems"
    }
    ACCOUNT {
        string Name "Corporate sponsors and orgs"
        string OWD "Private"
        string Volume "5K organizations"
    }
    DONATION {
        string Name "One-time and recurring gifts"
        string OWD "Private"
        string Volume "3.2M historical plus 600K per year - LDV"
        string Stripe_ID "Payment processor reference"
    }
    CAMPAIGN {
        string Name "Fundraising campaigns"
        string OWD "Public Read Only"
        string Volume "200 per year"
    }
    BOOK_DONATION {
        string Name "Donated book batches"
        string OWD "Private"
        string Volume "600K per year - LDV"
        string Donor_Attribution "Links donor to books"
    }
    INVENTORY_ITEM {
        string Name "Warehouse book inventory"
        string OWD "Public Read Only"
        string Volume "180K current inventory"
        string Attributes "Condition grade genre level language"
    }
    DISTRIBUTION_RECORD {
        string Name "Books shipped to schools"
        string OWD "Controlled by Parent (School)"
        string Volume "4M historical plus 550K per year - LDV"
        string Tracking "Shipment tracking info"
    }
    SCHOOL {
        string Name "Partner school profiles"
        string OWD "Public Read Only"
        string Volume "2500 current to 5000 in 3 years"
        string Title_I "Title I status and demographics"
    }
    SCHOOL_DISTRICT {
        string Name "District aggregations"
        string OWD "Public Read Only"
        string Volume "15 districts"
    }
    DISTRICT_DATA_STAGING {
        string Name "SFTP ingestion staging"
        string OWD "Private"
        string Volume "Monthly loads from 15 districts"
        string Status "Pending Validated Failed Promoted"
    }
    BOOK_REQUEST {
        string Name "School book requests"
        string OWD "Private"
        string Volume "5K per year"
        string Approval "Inventory plus equity workflow"
    }
    VOLUNTEER_ACTIVITY {
        string Name "Event hours and participation"
        string OWD "Private"
        string Volume "20K records per year"
        string Certification "Hour letters for tax and employer match"
    }
    CORPORATE_SPONSORSHIP {
        string Name "Multi-year pledges and tiers"
        string OWD "Controlled by Parent (Account)"
        string Volume "500 active sponsorships"
        string Installments "Schedule and deliverable tracking"
    }
    GRANT {
        string Name "Grant applications and awards"
        string OWD "Private"
        string Volume "100 active grants"
        string Fund_Restrictions "Program-level expenditure tracking"
    }

LDV Strategy

Three objects exceed the LDV threshold and will grow significantly with the 3-year scaling target (5,000 schools):

ObjectCurrent VolumeAnnual Growth3-Year Projection (5K schools)Strategy
Donation3.2M historical + 600K/yearGrowing with donor base~5M totalCustom indexes on Contact + Date + Campaign. Archive donations >5 years to Big Objects for reporting. Skinny tables on Amount, Date, Campaign
Book Donation~600K/yearScales with school count~2.4M in 3 yearsIndexed on Donor + Date + Warehouse. Linked to Inventory Item for lifecycle chain
Distribution Record4M historical + 550K/yearDoubles with 5K schools (~1.1M/year)~7.3M totalCustom indexes on School + Date + Warehouse. Archive completed distributions >3 years. Critical for impact reporting chain

Impact Reporting Chain and LDV

The full book lifecycle chain (Donation -> Book Donation -> Inventory Item -> Distribution Record -> School) spans multiple LDV objects. Cross-object report types linking these objects will require careful query optimization. Consider CRM Analytics datasets for the impact reporting chain (Req 29) rather than live cross-object SOQL queries across millions of records.

Sharing Model

Role Hierarchy

graph TB
    ED["Executive Director<br/>View All Data"]
    CTO["CTO<br/>Full system access"]
    DFD["Dir of Fundraising<br/>All donor + campaign data"]
    DPR["Dir of Programs<br/>All school + distribution data"]
    DFI["Dir of Finance<br/>All financial data"]

    subgraph Fundraising["Fundraising Team (20)"]
        FM["Fundraising Managers<br/>Donor records + campaigns"]
        FA["Fundraising Associates<br/>Own donor assignments"]
    end

    subgraph Programs["Programs Team (35)"]
        CM["City Managers (15)<br/>Own city: schools + volunteers + events"]
        PA["Programs Associates<br/>Assigned school partnerships"]
    end

    subgraph Warehouse["Warehouse Team (25)"]
        WM["Warehouse Managers (4)<br/>Own warehouse inventory"]
        WS["Warehouse Staff<br/>Inbound + outbound only"]
    end

    subgraph Finance["Finance Team"]
        FC["Finance Controller<br/>Donations + grants + QBO"]
        FK["Finance Clerk<br/>Transaction processing"]
    end

    subgraph Tech["Tech Team (8)"]
        TL["Tech Lead<br/>Full donor + config access"]
        DEV["Developers (7)<br/>No HR or accounting data"]
    end

    subgraph PortalUsers["Portal Users (External — Outside Hierarchy)"]
        SP["School Partners (2,500)<br/>Own school: requests + shipments + impact"]
        VL["Volunteers (800+)<br/>Own participation + events + certifications"]
    end

    ED --> CTO
    ED --> DFD
    ED --> DPR
    ED --> DFI
    DFD --> FM --> FA
    DPR --> CM --> PA
    DFI --> FC --> FK
    CTO --> TL --> DEV
    DPR --> WM --> WS

OWD Summary

ObjectOWDSharing Mechanism
Contact (Constituent)PrivateRole hierarchy; fundraising sees donors, programs sees volunteers, dedup links both
Account (Organization)PrivateRole hierarchy; corporate sponsors visible to fundraising + finance
DonationPrivateRole hierarchy; finance and fundraising access via role; tech team via permission set (read-only)
CampaignPublic Read OnlyAll internal staff can view; edit restricted to fundraising team via profile
SchoolPublic Read OnlyAll internal staff can view school profiles; school partners see only own school via portal sharing
Distribution RecordControlled by Parent (School)Inherits School sharing (Public Read Only); programs team and warehouse team access via parent; edit restricted to programs team via profile
Inventory ItemPublic Read OnlyAll internal staff can view inventory; warehouse team edits via profile
Book RequestPrivateOwned by requesting school portal user; programs team access via sharing rules
Volunteer ActivityPrivateCity managers see own city via criteria-based sharing on City field; volunteers see own records via portal
GrantPrivateFinance team access via role hierarchy; programs team read-only via sharing rules
Corporate SponsorshipControlled by Parent (Account)Inherits Account sharing; fundraising and finance access via parent Account role hierarchy

City Manager Isolation

City managers (Req 23) see volunteer and event data for their city only. This is implemented via criteria-based sharing rules on the City__c field across Volunteer Activity, Event, and School objects. City managers also see regional school partnerships through territory-based sharing. This prevents a NYC city manager from seeing Chicago volunteer data.

Migration Strategy

flowchart LR
    subgraph P1["Phase 1: Foundation<br/>Months 1-4"]
        P1A["Deploy Salesforce NPC<br/>+ MuleSoft Composer"]
        P1B["Environment strategy<br/>DEV x3, QA, UAT"]
        P1C["Configure core objects<br/>+ Experience Cloud site"]
        P1A --> P1B --> P1C
    end

    subgraph P2["Phase 2: GiveHub Migration<br/>Months 5-8"]
        P2A["Export 500K donors<br/>+ 3.2M transactions<br/>from PostgreSQL"]
        P2B["Fuzzy dedup across<br/>GiveHub + MailChimp +<br/>Eventbrite (email + name)"]
        P2C["Load unified constituents<br/>+ giving history<br/>into NPC"]
        P2D["Stripe webhooks<br/>cutover to Composer<br/>(spring — NOT December)"]
        P2A --> P2B --> P2C --> P2D
    end

    subgraph P3["Phase 3: Integrations<br/>Months 9-14"]
        P3A["ShelfTrack bidirectional<br/>sync + book lifecycle"]
        P3B["SFTP district ETL<br/>15 district mappings<br/>(Anypoint SFTP connector)"]
        P3C["MailChimp + Eventbrite<br/>bidirectional sync"]
        P3D["QuickBooks weekly<br/>journal entries"]
        P3A --> P3B --> P3C --> P3D
    end

    subgraph P4["Phase 4: Go-Live<br/>Months 15-18"]
        P4A["GiveHub decommissioned<br/>(Rails 5.2 EOL)"]
        P4B["Google Sheets retired<br/>volunteer data in SF"]
        P4C["Full impact reporting<br/>chain validated"]
        P4A --> P4B --> P4C
    end

    P1 --> P2 --> P3 --> P4
PhaseKey ActivitiesValidation Criteria
Phase 1 (Mo 1-4)NPC deployment, environment setup, DevOps Center, core object configEnvironments operational; CI/CD pipeline tested; Experience Cloud site live
Phase 2 (Mo 5-8)GiveHub donor migration, 3-system dedup, Stripe cutover (spring only)500K donors loaded; <1% unresolved duplicates; giving history intact; Stripe live via Composer
Phase 3 (Mo 9-14)All 6 integrations live one-at-a-time; load testing at 2x peakEach integration passing end-to-end; 12K/day donation simulation passes; SFTP all 15 districts validated
Phase 4 (Mo 15-18)GiveHub decommission, Google Sheets retired, full impact chainImpact report generates end-to-end; GiveHub read-only then off; board report automated

Year-End Campaign Blackout

GiveHub-to-Salesforce donation cutover MUST happen in spring (April-May recommended). GiveHub remains the donation system of record through at least one complete December year-end campaign cycle. No production deployments November 1 through January 15. The $15K lost-donation incident from a fundraising-event outage underscores why this blackout window is non-negotiable.

Identity & SSO Flow

sequenceDiagram
    participant Staff as BookBridge Staff
    participant Browser as Browser
    participant Google as Google Workspace<br/>(IdP)
    participant SF as Salesforce NPC

    Staff->>Browser: Navigate to Salesforce
    Browser->>Google: Redirect (SP-initiated SAML 2.0)
    Google->>Google: Authenticate (Google MFA)
    Google->>Browser: SAML Assertion (Federation ID = Google email)
    Browser->>SF: POST SAML to ACS URL
    SF->>SF: Match Federation ID → User record
    SF->>Browser: Session Cookie + Redirect
sequenceDiagram
    participant ExtUser as School Partner /<br/>Volunteer
    participant Browser as Browser
    participant SF as Experience Cloud Portal

    ExtUser->>Browser: Navigate to Portal
    Browser->>SF: Login page (email + password)
    SF->>SF: Authenticate (optional MFA)
    SF->>SF: Assign portal profile<br/>(School Partner or Volunteer)
    SF->>SF: Apply sharing: audience-based visibility
    SF->>Browser: Session Cookie + Portal Home

SSO Design Rationale

Internal staff (120 employees): SAML 2.0 SP-initiated SSO via Google Workspace (standard for nonprofits using Google for Nonprofits). Google handles MFA. Federation ID is the Google email address. If BookBridge later moves to Microsoft 365 or Okta, only the IdP metadata needs updating.

School partners and volunteers: Username/password through Experience Cloud (single site with audience-based visibility). School contacts submit book requests and track shipments; volunteers view participation history and download hour certifications. No SSO for external users — the diverse partner base (2,500 schools, 800 volunteers) makes a shared IdP impractical. Self-registration with email verification is enabled for new school contacts.

Integration Error Handling

Each integration has specific error handling tailored to its pattern, volume, and business criticality.

IntegrationPatternRetryDLQMonitorFallback
Stripe → DonationsWebhook → Composer → Platform Event3x exponential (2s, 15s, 120s)Integration_Error__c with full Stripe payload + event IDEmail alert to tech team on 3rd failure; Slack notification for >10 failures/hourStripe retries webhooks for up to 72 hours; Platform Event replay (72-hour window); manual reprocess UI
ShelfTrack (bidirectional)REST + Webhooks via Composer3x exponential (5s, 30s, 300s)Integration_Error__c with payload + ShelfTrack transaction IDDaily digest of failed syncs to warehouse manager + tech teamQueue failed records; ShelfTrack webhook retry (configurable); manual reconciliation report
School Districts SFTPBatch ETL via Anypoint SFTP connector → Staging object (Composer lacks SFTP support)1 automatic re-fetch per district after 24 hoursDistrict_Data_Staging__c with Status__c = Validation_FailedMonthly summary of failed/flagged records to programs teamBad files quarantined in staging; clean records still promote; manual review queue for anomalies
QuickBooks (outbound)Scheduled batch REST via Composer2x retry (immediate + 1 hour)Integration_Error__c with journal entry payloadEmail to finance director on any failure (weekly financial data is sensitive)Finance team manually enters weekly summary CSV (current process) as interim fallback
MailChimp (bidirectional)REST + Webhooks via Composer3x exponential (5s, 30s, 120s)Integration_Error__c with contact/campaign IDsWeekly digest of sync failures to marketing teamSegments can be manually exported as CSV (current process) while integration is restored
Eventbrite (inbound)Webhooks via Composer3x exponential (2s, 15s, 120s)Integration_Error__c with event/attendee payloadAlert on registration sync failures during active event windowsEventbrite retains all data; manual CSV export available; volunteer hours tracked in backup Google Sheet per city

Year-End Campaign — Elevated Monitoring

During December 15-31 (year-end campaign, up to 12K donations/day), the Stripe integration monitoring threshold drops from 10 failures/hour to 3 failures/hour for immediate alerting. A dedicated on-call rotation covers the integration layer. Platform Event replay (72-hour window) provides the safety net — no donation data is lost even if processing is delayed.

Governance & DevOps

Environment Strategy

flowchart LR
    DEV1[Dev Sandbox 1<br/>Developer Pro] --> QA[QA / Integration<br/>Partial Copy]
    DEV2[Dev Sandbox 2<br/>Developer Pro] --> QA
    DEV3[Dev Sandbox 3<br/>Developer Pro] --> QA
    QA --> AT{Automated Tests<br/>+ QA Analyst}
    AT -->|Pass| UAT[UAT<br/>Partial Copy]
    AT -->|Fail| DEV1
    UAT --> BIZ{Business Stakeholder<br/>Approval}
    BIZ -->|Approved| PROD[Production]
    BIZ -->|Rejected| DEV1

Sandbox Strategy

SandboxTypePurposeNotes
DEV-1, DEV-2, DEV-3Developer ProIndividual developer work (team of 8, 3 active sandboxes)Seed data with synthetic donors, schools, inventory
QA/TESTPartial CopyIntegration testing with Composer sandbox connections, QA validationConnected to ShelfTrack staging, Stripe test mode, MailChimp test list
UATPartial CopyBusiness stakeholder acceptancePrograms, fundraising, and warehouse staff validate workflows

Partial Copy (not Full Copy) for both QA and UAT is appropriate for BookBridge — the nonprofit budget ($1.2M) does not justify Full Copy licensing, and Partial Copy with sampled data provides sufficient test coverage for the data volumes involved.

Branching Strategy

  • main — production-ready; deploys to Production via DevOps Center
  • develop — integration branch; auto-deploys to QA sandbox
  • feature/[work-item]-description — individual feature branches in Dev sandboxes
  • Pull requests require 1 peer review (team is learning; reviews double as knowledge transfer)
  • Merges to main require QA analyst sign-off + business stakeholder UAT approval

Testing Strategy

Test TypeEnvironmentScopeCriteria
Apex Unit TestsDeveloper sandboxesCustom Apex, triggers, batch jobs>75% coverage; mock callouts for all Composer-invoked APIs
Integration TestsQAAll 6 system connections via Composer sandboxEnd-to-end data flow validated; error handling exercised
Load TestingQAStripe webhook processing at peak volumeSimulate 12K donations/day (year-end); validate Platform Event processing
UATUATDonor management, book requests, volunteer workflowsBusiness users validate real-world scenarios; 3-day UAT per release

CoE / Post-Go-Live Governance

Team Growth Path: The 8-person tech team (from 3 six months ago) needs structure, not overhead. DevOps Center provides visual deployment tracking as a stepping stone. Plan to evaluate migration to GitHub Actions + SFDX at the 12-month mark once the team has foundational skills.

Release Cadence:

  • Standard releases: Bi-weekly (2-week sprints) aligned with DevOps Center work items
  • Hotfixes: Same-day path for critical defects (e.g., donation processing failures)
  • Blackout window: No production deployments November 1 through January 15 (year-end campaign + reconciliation period)

Onboarding: Development process documented in a runbook (Req 48) covering sandbox setup, branching conventions, deployment steps, and integration testing procedures. Target: new team member onboards within 5 business days.

Ongoing Governance: CTO reviews all integration changes; QA analyst gates all deployments; monthly tech debt review to prevent the “GiveHub problem” (undocumented, untested custom code) from recurring.

Requirements Addressed

  1. ✅ Unified constituent profiles — Single Contact record linking donor, volunteer, and event data (Reqs 1-2, 13)
  2. ✅ Zero-downtime donation processing — Stripe webhooks → Platform Events with 72-hour replay; spring cutover avoids December (Req 3)
  3. ✅ Hub-and-spoke integration — MuleSoft Composer central hub for 6 systems, extensible for 2-3 new/year (Reqs 33-40)
  4. ✅ SFTP district data ingestion — District-specific ETL mappings with staging object and validation (Reqs 20, 35)
  5. ✅ Book lifecycle tracking — Donation → warehouse → distribution chain linked via Composer sync with ShelfTrack (Reqs 8-12)
  6. ✅ School/volunteer portal — Single Experience Cloud site with audience-based visibility (Reqs 24, 26)
  7. ✅ Structured dev process — DevOps Center with 4-environment strategy; QA + stakeholder gates (Reqs 41-48)
  8. ✅ Donor deduplication — Fuzzy matching across GiveHub, MailChimp, and Eventbrite with survivorship rules (Reqs 16, 19)

Risk Assessment

RiskImpactProbMitigation
Year-end donation processing failureCRITICALMEDAsync Platform Events with replay; no cutover Nov-Jan; load test at 2x peak (24K/day)
Team overwhelm (simultaneous process + platform change)HIGHHIGHPhased rollout: environments first (Mo 1-2), core platform (Mo 3-8), integrations one-at-a-time (Mo 9-14)
SFTP format changes break ingestionMEDHIGHDistrict-specific mappings isolated; staging object catches bad data; monitoring alerts on validation failures
GiveHub security vulnerability before decommissionHIGHMEDRails 5.2 EOL; implement WAF rules; accelerate Stripe-direct to reduce GiveHub to read-only

Domain Scoring Notes

  • D5 Integration (HEAVY): Classify EACH integration by protocol/pattern/direction/volume. Address SFTP separately from REST. Explain error handling per integration individually — “MuleSoft handles errors” is not sufficient.
  • D6 Dev Lifecycle (HEAVY): Design CI/CD for the team’s current maturity. Acknowledge the maturity gap. Include onboarding documentation, release process, and automated testing strategy (mock callouts in sandboxes).
  • D3 Data (MED): Unified constituent model — single Contact for a person who is both donor and volunteer (Req 13). Donor deduplication across 3 systems.
  • D1 System Arch (LIGHT): Mention Power of Us program (10 free licenses) to show budget awareness.

Reporting Approach

Standard Salesforce reports and dashboards cover the Executive Director dashboard (Req 27), campaign performance (Req 28), and grant funder reports (Req 32). The impact reporting chain (donation → books → schools → students, Req 29) requires cross-object report types linking Donation, Inventory, Distribution, and School records. The automated monthly reconciliation (Req 30) is a scheduled Apex batch comparing platform totals against Stripe settlements and QBO journal entries. If the board quarterly report (Req 31) or cross-system impact analytics demand more sophisticated visualization, consider CRM Analytics (included in some nonprofit bundles) for cross-source dashboards.

What Would Fail

  1. Point-to-point integrations for everything — 6 systems growing to 9 means up to 36 connections. Req 41 explicitly requires accommodating new connections without re-architecture. Hub-and-spoke is the only defensible answer.
  2. Treating SFTP the same as REST APIs — The 15 district feeds are batch, schema-less, and arrive on different schedules. Lumping them with REST integrations shows you did not read the scenario. Note: MuleSoft Composer does not support SFTP natively — this integration requires Anypoint Platform’s SFTP connector or an alternative approach. Judges expect a specific staging and transformation strategy.
  3. Prescribing enterprise CI/CD for a beginner team — Jenkins, GitHub Actions + SFDX, and feature-flag management for a team that was deploying to production manually 3 months ago is tone-deaf. Start with DevOps Center, then evolve.

Self-Scoring Checklist

  • Did I classify every integration by protocol, pattern, direction, and volume?
  • Did I justify middleware vs point-to-point with a specific rationale?
  • Did I handle the SFTP feeds differently from the REST APIs?
  • Did I design the CI/CD for the team’s current maturity level?
  • Did I avoid the December cutover window?
  • Did I present a unified constituent model (not separate donor/volunteer)?
  • Did I include error handling for each integration?

Scoring Rubric

CriterionWeightWhat Judges Look For
Integration Architecture30%Every integration classified by protocol, pattern, direction, and volume. Hub-and-spoke justification over point-to-point. SFTP feeds treated differently from REST APIs. Error handling per integration with retry, DLQ, and monitoring strategies
Dev Lifecycle & Governance25%CI/CD maturity matched to team capability (not enterprise overkill for a beginner team). Environment strategy with appropriate sandbox types. Release planning that avoids the December donation spike. Change management process
Solution Design20%Unified constituent model (not separate donor/volunteer objects). Nonprofit Cloud justification. Build-vs-buy decisions for each capability area
Data Architecture15%Constituent deduplication strategy across 6 systems. Data quality handling for inconsistent SFTP formats. Scaling plan for 5,000-school growth target
Communication & Trade-offs10%Clear explanation of middleware choice, why DevOps Center before full CI/CD, how the architecture accommodates future integrations (Req 41) without re-architecture

This is a personal study site for Salesforce CTA exam preparation. Built with AI assistance. Not affiliated with Salesforce.