Experience

Software and data engineering.

A closer look at the systems I’ve built, the problems they solve, and the engineering decisions behind them.

Provider integration

Provider migration and ongoing integration.

Current work · C# / .NET · Data mapping · APIs · State management

A healthcare customer needed to migrate provider and credentialing data into a new management platform and keep it updated. The integration maps data for 100,000 practitioners and associated practice and facility locations across roughly 60 destination entity types. It also handles approximately 4.5 million relationships linking practitioners to locations and networks/products.

My contribution

I designed and built the C# integration plugins and shared publishing layer on Gaine’s Integration Hub. A single provider profile can require dozens of related API writes. The integration applies customer-specific selection and mapping rules, then sequences writes when one resource depends on another.

It records destination IDs and publishing outcomes so the team can trace individual records, distinguish failures from intentional exclusions, and investigate the results of each batch.

Delivery and current operation

The migration is complete, and batch publishing is in production. Real-time publishing has been implemented; activation is pending joint validation of data and publishing policies by Gaine and the customer.

Case study / Provider data

Mapping, publishing, and tracking provider data

Keeping complex mappings manageable

A master profile can hold several addresses while the destination accepts one mailing address. I built profile managers that turn Gaine’s generic data entities into typed business objects, selection rules that filter and rank the records, and focused converters that map the chosen data.

This keeps source priority, eligibility checks, and other customer policies separate from field mapping and API execution. Those policies can change without spreading conditional logic through every converter.

Coordinating dependent API writes

One master profile can expand into dozens of API resources. A child resource often needs the ID returned when its parent is created. I built reusable publish plans to describe those dependencies, with a shared executor sequencing dependent writes and running independent work within configured concurrency limits.

Controls for each resource type determine which records can be created or updated, including publishing child records against an existing parent. Follow-up work can run when a resource or batch completes—for example, retrieving updated destination data after publishing a product batch—without changing the shared executor.

Recovering after partial success

I store each resource’s destination ID and a fingerprint of its last successful request. If a practitioner is created but its email fails, the next run can recognize the existing practitioner, skip its unchanged write, and retry the email.

That recognition also works before the new destination ID has returned to Gaine: an alias links the Gaine record to its saved destination state. The protection depends on a confirmed response and a successful state save; lost responses or unsaved state still require investigation.

Accounting for publishing results

I built batch reports that distinguish successful writes, failures, and intentional exclusions. Each result connects to its source record, destination ID, publishing decision, and error details.

Summaries show counts and failure rates by domain and resource type, with historical versions preserving changes to recorded outcomes. The team can move from an overall batch result to the individual records behind it.

Member reconciliation

Member enrollment reconciliation and daily corrections.

2023–present · SQL · 834 ingestion · Reconciliation · Field-level survivorship

A healthcare customer needed to reconcile enrollment data for roughly 80,000 members. The team lacked visibility into differences between source records and HealthRules Payor (HRP), so errors could go unnoticed until members called to report them.

My contribution

I led the implementation on Gaine’s Healthcare Data Management Platform (HDMP). I built the ingestion, mappings, discrepancy audits, and reporting that let the enrollment team compare source, master, and HRP records directly.

Configurable rules select values for automated demographic corrections, including names and addresses. Coverage discrepancies are surfaced for the enrollment team to investigate and resolve manually. Retained profiles and exports preserve what HRP held, what was proposed, and what was sent.

In production

Used by the enrollment team since 2023, the workflow makes discrepancies visible for investigation and produces daily files of eligible demographic corrections for delivery through the customer’s existing vendor integration. Audit checks hold back members whose key information does not align.

Case study / Member data

Deciding what to correct and what to hold back

Preparing source data for reconciliation

I built configurable SQL utilities to cleanse fields and translate source codes. Source-specific views assemble member, address, and coverage data into records ready for mapping. A source date-of-birth key, for example, is resolved to an actual date before the member reaches Gaine.

Staging detects changes against previously loaded data and retains history. The mappings preserve source identifiers and file references, so a discrepancy can be traced from the loaded member back to its original source.

Explaining what went into each extract

Each daily run produces three comparable profiles: the source record, what HRP holds, and the proposed demographic correction. I adapted the profile-versioning approach from master data management so those comparisons remain available for later investigation.

Configurable rules select values from source, master, or HRP data. Related fields can move together, so an address change does not carry forward an old apartment number. I preserve these profiles and the final export in history, linked by extraction identifiers. We can reconstruct what HRP held, what we sent, and why.

Investigating discrepancies and tracking resolution

I built member audits and three reports that connect issue counts to affected members and their source and master records. Configurable rules use the findings to select eligible demographic corrections and hold back members whose key information does not align. Coverage discrepancies remain visible for the enrollment team to investigate and resolve manually.

The reports show the eligibility rules alongside the counts, so the team can move from a summary to the records behind an issue, understand why a member was held back, and track resolution.

Catching a coverage mismatch before sending corrections

When I loaded an updated benefit crosswalk supplied by the customer, audits identified new coverage differences between the incoming enrollment data and HRP. The customer used the findings to trace the mismatch to an older crosswalk still in use in HRP.

Extract gates held the affected members out of the daily correction file while the customer brought the crosswalks into alignment.

Data change requests

Reviewing and applying changes to master data.

Python · Snowflake · C# / .NET · Integration Hub

A customer needed a controlled way to review provider and organization changes submitted through Veeva and apply approved changes to master profiles in Gaine.

My contribution

I designed and built a data change request workflow through Gaine’s platform extension points, using three lifecycle plugin stages to connect Core Services, Orchestrator, and Veeva. Together, they turn incoming provider and organization requests into reviewable records, carry approval decisions between platform components, and apply approved changes with a traceable record of each field’s outcome.

Current status

The workflow has run end to end and produced production extracts. Work continues with the customer as they refine requirements.

Case study / Data change requests

Coordinating review, application, and response across systems

Resolving requests to the right records

A request can target a provider, organization, or one of its addresses, contact records, licenses, or relationships. I built mapping and resolution rules that bind each requested field to its intended record. Supplied keys must agree with the target profile; missing mappings, ambiguous matches, and conflicting lines remain visible as validation findings.

New providers and organizations go through Core Services matching before entering the ordinary creation path. An existing match stops that path and records the matched party for separate review. Provider and organization requests share the validation pipeline through domain-specific adapters.

Rechecking assumptions before applying a decision

A request can wait for review while the underlying data changes. Before applying approved work, I reload the current request and target data. When a request supplies an old value, I compare it with the current value and record a failure if they differ.

Child selection is checked again where it depended on a unique eligible record or an ordered slot. Requests to create a new provider or organization rerun matching before creation. For example, if one request creates an organization while a second awaits approval, the second is stopped from taking the ordinary new-record path when matching finds that organization.

Preserving decisions and applied history

A review decision and a successful application are separate facts. I retain the requested value, review decision, applied value, and outcome for each field. The Core Services feedback plugin updates only changed decision fields in Orchestrator, leaving the rest of the request intact.

When an inbound file is replayed, successfully completed requests keep their existing state. If part of a request has already applied, changed source content cannot replace that recorded request. Older queued events are checked against the current request before any further action.

Returning decisions that Veeva can represent

Gaine records approval decisions per field, but the Veeva response requires one accepted or rejected result for each source section. If one field in a section is approved and another rejected, either single result would misstate the review.

I built Snowflake export checks that reconcile those decisions and hold the whole request when a section is mixed, unresolved, or missing required identity. Responses are packaged with the related provider data. Requests with inconsistent output are held with a recorded reason while unrelated requests can continue.

Payer migration

Migrating legacy data into a payer platform.

SQL / T-SQL · C# / .NET · Transformation framework

A customer needed to bring provider and organization data from multiple legacy systems into HealthRules Payor.

My contribution

I built ingestion and mapping across seven source systems and 50 distinct file feeds. I also built shared SQL utilities and a C# transformation framework, with an HRP-specific plugin for outbound feeds to the new platform.

Outcome

The migration completed, and the integration supported ongoing production feeds for roughly a year. The customer contact later introduced Gaine to another organization because of the integration.

Data ingestion

Configurable source-data preparation.

SQL / T-SQL · Metadata · Source data

Each source has its own field formats, lookup codes, and record relationships. Those differences need to be resolved before the data can be mapped into Gaine.

My contribution

I built shared landing utilities that apply cleansing, lookup translations, field naming, and filtering from configuration tables. Source-specific views handle the joins and business rules, producing records that pass through staging and change tracking before the final mapping.

Developers can reuse the common rules while keeping each source’s logic in a focused, readable view.

In production

Developers use the utilities across customer implementations to prepare new sources and inspect records at each stage of ingestion.

Database deployments

Shared database code, repeatable releases.

SQL Server · DACPAC · C# · Azure DevOps

Customer implementations needed a common database foundation, with their own extensions, configuration, and upgrade requirements.

My contribution

I designed a layered SQL Server deployment framework using DACPAC packages and built its C# tooling. Shared functionality lives in a common repository; customer repositories hold their own extensions and configuration. Deployment combines these layers to bring the database schema and managed data into the state defined by the source repositories.

Azure DevOps tracks the Git commit deployed to each environment, so teams can identify exactly which source version a release came from.

In production

The framework has supported database releases across 10+ customers over six years and remains in use today.

Reporting framework

Separating data views from report logic.

SQL · Reporting · Reusable utilities

New reports repeatedly required the same work: locating fields, joining related records, and deciding how to present the data.

My contribution

I built a shared reporting layer that flattens complex profiles into consistent, readable rows, with the joins, crosswalks, and presentation already defined. Report authors write the selection or calculation for their question, then join the result to that prepared view.

The view contains enough business context to reason about a member or provider. Users can open the full profile in the console when they need the detail.

In production

Used across multiple customers for five years. When the required data is already in the view, new reports can take minutes instead of hours or days, with consistent data and presentation.

Audit framework

Making audit findings visible and searchable.

Auditing · Customer solutions

Customers needed to investigate data quality issues directly in Gaine’s console, alongside the profile data they were reviewing.

My contribution

I extended Gaine’s data model so customers can view audit findings with the relevant profile and search for audit messages in the console.

Gaine platform changes are routed to the integration framework, where custom plugins evaluate each profile and return current findings. The framework compares those findings with stored audits: adding new audit findings, and marking existing findings resolved when they are no longer present.

Severity controls outbound processing: errors block publishing, while warnings remain visible and allow processing to continue.

In production

Used in two production customer implementations.

Career

Roles and responsibilities.

Sep 2019 - PresentGaine Technology

Software Engineer, Solution Consultant

Designs, builds, and supports healthcare and life-sciences integrations, data workflows, and reusable tooling. Works directly with customers from requirements through production, with ingestion spanning 30+ external systems and hundreds of source files and tables.

Jun 2015 - Aug 2016BAE Systems

Software Engineer II / Software Engineer Intern

Promoted from Software Engineer Intern to Software Engineer II in June 2016; developed Java and C++ capabilities for geospatial visualization, data relationships, and streaming.