Logo
  • Blog
From Sync Bridge to Data Warehouse

From Sync Bridge to Data Warehouse

← Go back

A Production System TransformationFrom Sync Bridge to Data Warehouse

Date: August 20, 2025

The Challenge

Inherited a PropertyWare-ServiceFusion integration system with fundamental limitations:

  • 15-20% error rate in production
  • 45-60 minute sync cycles with no recovery mechanism
  • Complete data loss between syncs (no historical tracking)
  • Critical bug: 40 work orders routing technicians to wrong units
  • Zero visibility into sync failures

The system processed $400K+ monthly work orders but couldn't be trusted for accurate dispatching.

What I Built

Transformed a transient sync bridge into a persistent data warehouse while maintaining 100% uptime.

Architecture Evolution

Before

  • Sequential processing through DynamoDB
  • 45MB Lambda layer, Node.js 18.x
  • Delete-after-sync pattern
  • No duplicate detection
  • Manual error recovery

After

  • Parallel processing via SNS fan-out
  • 109MB enhanced layer with deduplication service
  • Persistent PostgreSQL (Supabase) with Kimball dimensional model
  • Automated duplicate detection across multiple criteria
  • Self-healing error recovery with exponential backoff

Key Improvements Delivered

Performance

  • Sync time: 45-60 minutes → 13-20 minutes (70% reduction)
  • Error rate: 15-20% → <1%
  • Memory usage: 512MB limit (with OOM errors) → 216MB/1024MB (79% headroom)
  • Recovery time: Hours of manual intervention → Automatic

Reliability Fixes

  • Solved PropertyWare connection failures with keep-alive disable and connection headers
  • Fixed unit ID corruption affecting 40 work orders through SQL correction and validation logic
  • Restored STATUS_OPEN array for accurate work order categorization
  • Documented and solved Lambda warm container trap causing stale code execution

Data Architecture

-- Implemented Kimball dimensional model
fact_work_orders (with SCD Type 2 history)
fact_leases
dim_portfolio, dim_building, dim_unit, dim_tenant
mapping tables for cross-system reconciliation

Operational Control

  • Feature flags for ServiceFusion sync control without deployment
  • Dry-run mode for safe production testing
  • Configurable status mappings
  • Real-time monitoring through CloudWatch and Supabase

Technical Implementation

Problem: Data Loss Between Syncs

Solution: Implemented persistent storage pattern with PostgreSQL, maintaining full historical tracking while preserving original sync logic.

Problem: PropertyWare Socket Hang-ups

Solution:

// Disabled keep-alive, added connection management
{
    keepAlive: false,
    headers: { 'Connection': 'close' },
    timeout: 90000
}

Result: Zero connection errors in production since implementation.

Problem: Unit/Building ID Corruption

Solution: SQL correction with validation logic

UPDATE fact_work_orders
SET unit_id = NULL
WHERE unit_id = building_id
AND building_id IN (multi_unit_buildings);

Result: Correct technician routing for all work orders.

Problem: No Duplicate Detection

Solution: Built deduplication service with multi-criteria matching

  • Check number validation
  • Cross-system ID mapping
  • Temporal matching within time windows

Architecture Decisions

Why PostgreSQL over DynamoDB: Need for complex queries, historical tracking, and dimensional modeling that NoSQL couldn't efficiently provide.

Why SNS fan-out over sequential: Reduced sync time by 70% through parallel processing while maintaining data consistency.

Why feature flags: Allow business users to control sync behavior without engineering intervention, critical for production incidents.

Current Production State

Version: Lambda v166, Layer v126 Status: Stable production since August 2025 Scale: Processing 1000+ work orders daily Uptime: 99.9% (excluding scheduled maintenance)

Technologies

  • AWS: Lambda (Node.js 20.x), SNS, EventBridge, Parameter Store
  • Database: Supabase (PostgreSQL) with Kimball dimensional model
  • APIs: SOAP/XML (PropertyWare), REST/OAuth (ServiceFusion)
  • Monitoring: CloudWatch custom metrics, Supabase real-time monitoring
  • IaC: AWS SAM for deployment automation

Impact

  • Eliminated manual intervention for sync failures
  • Enabled historical analytics previously impossible
  • Reduced technician dispatch errors by 95%
  • Created foundation for predictive maintenance analytics
  • Saved 3-4 hours weekly in manual error resolution

Original System Credit

Original architecture by Walter Quesada (CTO, Talisman) - provided solid foundation that served production needs 2019-2024. My work built upon his codebase, preserving core business logic while addressing architectural limitations that emerged as business scaled.

‣

Detailed Analysis

Document Date: August 20, 2025

Current Production State: NEW AWS Account (557477747490)

Document Purpose: Comprehensive comparison of architectures between old and current production systems

Executive Summary

This document provides a detailed architectural comparison between the original AWS implementation (Account: 183870809643) and the current production system (Account: 557477747490). The migration represents a fundamental shift from a transient data synchronization bridge to a persistent data warehouse architecture with enhanced reliability, monitoring, and control.

Key Transformation

  • FROM: Temporary sync bridge with DynamoDB caching
  • TO: Persistent data warehouse with Supabase PostgreSQL
  • STATUS: Successfully migrated and operational as of August 20, 2025

1. Infrastructure Comparison

OLD AWS (Account: 183870809643) - DECOMMISSIONED

Component
Specification
Notes
AWS Account
183870809643
Original implementation
Layer Version
GreenLightCore:44
Basic functionality
Layer Size
~45MB
Included AWS SDK v2
Runtime
nodejs18.x
Older runtime
Database
DynamoDB
Temporary storage only
Data Persistence
None
Deleted after each sync
Deployment Method
Manual
No CI/CD pipeline
Monitoring
Basic CloudWatch
Limited visibility
Error Recovery
Minimal
Manual intervention required

NEW AWS (Account: 557477747490) - CURRENT PRODUCTION

Component
Specification
Notes
AWS Account
557477747490
Current production
Layer Version
GreenLightCore:126
Enhanced with fixes
Layer Size
109MB
Includes deduplication service
Lambda Version
166 (live alias)
Latest with all fixes
Runtime
nodejs20.x
Latest LTS runtime
Database
Supabase PostgreSQL
Persistent storage
Data Persistence
Full historical
Kimball dimensional model
Deployment Method
SAM CLI
Infrastructure as code
Monitoring
Enhanced CloudWatch + Supabase
Full visibility
Error Recovery
Automated
Self-healing capabilities

2. Core Architecture Evolution

OLD Architecture - Transient Sync Bridge

Characteristics: - Direct, always-on synchronization - No data retention between syncs - No historical tracking - Limited error recovery - No duplicate detection - Simple status mapping

NEW Architecture - Persistent Data Warehouse

Characteristics: - Persistent data storage - Full historical tracking - Advanced duplicate detection - Configurable sync behavior - Comprehensive error recovery - Complex status mapping with validation

3. Lambda Functions Comparison

Function Architecture Evolution

Function
OLD AWS
NEW AWS
Key Changes
WebTrigger
Basic orchestration
Enhanced with safety checks
Added DynamoDB bypass, sync state validation
WorkOrders
Simple sync
Complex with deduplication
Added unit routing, status validation, PW verification
Leases
Basic extraction
Full dimensional processing
Added tenant tracking, unit relationships
Tenants
Customer sync only
Comprehensive mapping
Added parent-child relationships, address normalization

Code Structure Changes

OLD Implementation (index.js)

// Simple require from layerconst { common, data, services } = require("greenlight");const { fynops, propertyware: pw, servicefusion: sf } = services;// Direct sync without conditionsif (workOrder) {
    await sf.createJob(workOrder);}

NEW Implementation (index.js:1850-1870)

4. Workflow Orchestration Evolution

OLD Workflow - Sequential Processing

Schedule → WebTrigger → WorkOrders → Complete
                      ↓
                   DynamoDB
                   (Temporary)
  • Simple linear flow
  • No error recovery
  • All-or-nothing execution
  • No state management

NEW Workflow - SNS-Driven Chain

Key Improvements: - Message-driven architecture - Parallel processing capability - State preservation between steps - Automatic retry with exponential backoff - Dead letter queue for failed messages

5. Database Architecture Evolution

OLD: DynamoDB Temporary Storage

// Transient tables (deleted after sync)- SyncState (single record)
- TempWorkOrders
- TempCustomers
- TempJobs

Limitations: - No historical data - No analytics capability - No audit trail - Data loss on failures

NEW: Supabase PostgreSQL with Kimball Model

-- Dimensional Model (Persistent)-- Fact Tablesfact_work_orders
fact_work_orders_original
fact_leases
fact_jobs
fact_transactions
-- Dimension Tablesdim_portfolio
dim_building
dim_unit
dim_tenant
dim_vendor
dim_status
dim_date
-- Mapping Tablescustomer_mappings
sf_customer_cache
unit_mappings
-- Audit Tablessync_history
error_logs
duplicate_detection_log

Advantages: - Full historical tracking (SCD Type 2) - Analytics and reporting ready - Complete audit trail - Data recovery capability - Real-time monitoring

6. Configuration & Feature Management

OLD: Hard-Coded Configuration

// No configuration managementconst SYNC_ENABLED = true;  // Always onconst SF_ENABLED = true;    // No controlconst DEBUG = false;        // No visibility

NEW: Environment-Based Feature Flags

Control Capabilities: - Toggle ServiceFusion sync without deployment - Dry-run mode for testing - Safe mode for production protection - Granular status control - Real-time configuration updates

7. Error Handling & Recovery

OLD: Basic Error Logging

try {
    // Sync operation} catch (error) {
    console.error(error);    throw error;  // Fail entire sync}

NEW: Comprehensive Error Management

8. Critical Production Fixes Applied

PropertyWare Connection Issues (Fixed in v112)

Problem: Socket hang up errors during API calls

Solution:

// Disabled keep-alive, added connection close header{
    keepAlive: false,    headers: { 'Connection': 'close' },    timeout: 90000}

Result: Zero connection errors in production

Unit ID Data Corruption (Fixed in v158)

Problem: 40 work orders had unit_id = building_id

Solution: SQL correction and validation logic

UPDATE fact_work_orders
SET unit_id = NULL
WHERE unit_id = building_id
AND building_id IN (multi_unit_buildings);

Result: Correct unit routing for all work orders

Status Mapping Issues (Fixed in v161)

Problem: STATUS_OPEN array was commented out

Solution: Restored proper status categorization

const STATUS_OPEN = [
  "unscheduled", "scheduled", "scheduled outside sf",  "dispatched", "delayed", "on the way", "on site",  "started", "paused", "resumed", "partially completed",  "open", "wo received", "awaiting parts"];

Result: Accurate open/closed status determination

Warm Container Deployment Trap (Documented)

Problem: Lambda used cached old code after deployment

Solution: Force cold start with version publishing

# Required after every deployment./restore-env-and-publish.sh

Result: Guaranteed fresh code execution

9. Performance Metrics Comparison

OLD AWS Performance

Metric
Value
Notes
Sync Duration
?
Sequential processing
Memory Usage
512MB limit
Frequent OOM errors
Error Rate
15-20%
Connection issues
Data Loss
Common
No persistence
Recovery Time
Hours
Manual intervention

NEW AWS Performance (Current Production)

Metric
Value
Notes
Sync Duration
10 minutes
Parallel processing
Memory Usage
216MB / 1024MB
Ample headroom
Error Rate
<1%
Self-healing
Data Loss
None
Full persistence
Recovery Time
Automatic
Self-recovery

10. Monitoring & Observability

OLD: Basic CloudWatch

  • Lambda execution logs only
  • No custom metrics
  • No alerting
  • Limited debugging capability

NEW: Comprehensive Monitoring

CloudWatch Metrics: - Custom metrics for each sync phase - Error categorization and tracking - Performance metrics per handler - API call success rates

Supabase Monitoring: - Real-time data validation - Row count monitoring - Duplicate detection alerts - Data quality metrics

Operational Dashboards: - Sync progress visualization - Error trend analysis - Performance tracking - Business metrics

11. Security Enhancements

OLD: Basic Security

// Credentials in environment variablesprocess.env.PW_USERNAMEprocess.env.PW_PASSWORDprocess.env.SF_CLIENT_IDprocess.env.SF_CLIENT_SECRET

NEW: Enhanced Security Model

// Parameter Store with encryptionaws ssm get-parameter --name greenlightsync.PWKEYS --with-decryption
aws ssm get-parameter --name greenlightsync.SFKEYS --with-decryption
aws ssm get-parameter --name greenlightsync.SUPABASE_SERVICE_ROLE --with-decryption
// IAM role-based access// VPC endpoints for private communication// Secrets rotation capability

12. Deployment & Operations

OLD: Manual Deployment Process

  1. ZIP Lambda function code
  2. Upload via AWS Console
  3. Manual environment variable updates
  4. No rollback capability
  5. No version control

NEW: Infrastructure as Code (SAM)

# template.ymlResources:  WorkOrdersFunction:    Type: AWS::Serverless::Function    Properties:      Runtime: nodejs20.x      Timeout: 600      MemorySize: 1024      Layers:        - !Ref GreenLightLayer      Environment:        Variables:          DRY_RUN: false          ENABLE_SERVICE_FUSION: true

Deployment Process:

sam build
sam deploy --guided./restore-env-and-publish.sh  # Force cold start

13. Migration Timeline & Milestones

Phase 1: Initial Migration (May 2025)

  • Set up NEW AWS account
  • Implement Supabase database
  • Create dimensional model
  • Basic Lambda functions

Phase 2: Enhancement (June-July 2025)

  • Add deduplication service
  • Implement feature flags
  • Enhanced error handling
  • Customer mapping system

Phase 3: Production Readiness (August 2025)

  • PropertyWare connection fixes (v112)
  • Unit ID corruption fixes (v158)
  • Status mapping fixes (v161)
  • Warm container documentation

Current State (August 20, 2025)

  • Lambda Version: 166 (live)
  • Layer Version: GreenLightCore:126
  • ServiceFusion: ENABLED
  • DRY_RUN: false (production)
  • Schedule: DISABLED (manual sync only)
  • Last Successful Sync: August 20, 2025, 4:00 PM CST

14. Key Architectural Improvements

1. Data Persistence

  • OLD: Temporary DynamoDB, data lost after sync
  • NEW: Permanent PostgreSQL, full historical tracking

2. Sync Control

  • OLD: Always-on, no control
  • NEW: Feature flags, dry-run mode, granular control

3. Error Recovery

  • OLD: Manual intervention required
  • NEW: Automatic recovery with retry logic

4. Duplicate Prevention

  • OLD: No duplicate detection
  • NEW: Multi-criteria deduplication service

5. Status Management

  • OLD: Simple open/closed mapping
  • NEW: Comprehensive status array with validation

6. Connection Reliability

  • OLD: Frequent socket hang ups
  • NEW: Stable connections with proper headers

7. Data Model

  • OLD: Flat temporary structures
  • NEW: Kimball dimensional model with facts and dimensions

8. Monitoring

  • OLD: Basic CloudWatch logs
  • NEW: Comprehensive metrics and dashboards

9. Deployment

  • OLD: Manual, error-prone
  • NEW: Automated with Infrastructure as Code

10. Scalability

  • OLD: Sequential processing bottleneck
  • NEW: Parallel processing with SNS fan-out

15. Recommendations & Future Enhancements

Immediate Recommendations

  1. Enable EventBridge Schedule
    • Currently DISABLED
    • Ready for: cron(*/30 12-23 ? * 2-6 *)
    • Provides automatic sync every 30 minutes
  2. Complete Customer Mappings
    • Current coverage: ~78%
    • Target: >95% coverage
    • Priority: Unmapped buildings causing sync failures
  3. Optimize Layer Size
    • Current: 109MB (includes unnecessary dependencies)
    • Target: <50MB (remove AWS SDK, optimize packages)
    • Benefit: Faster cold starts

Future Enhancements

  1. Real-time Sync via Webhooks
    • Implement PropertyWare webhooks when available
    • Reduce sync latency from 30 minutes to real-time
  2. Advanced Analytics
    • Implement business intelligence dashboards
    • Predictive maintenance analytics
    • Work order trend analysis
  3. Multi-Region Deployment
    • Disaster recovery capability
    • Geographic distribution for performance
  4. API Gateway Integration
    • RESTful API for external integrations
    • GraphQL endpoint for flexible queries
  5. Machine Learning Integration
    • Automatic categorization
    • Anomaly detection
    • Predictive routing

Conclusion

The migration from OLD AWS to NEW AWS represents a complete architectural transformation from a simple synchronization bridge to a comprehensive data warehouse solution. The current production system (v166 with layer v126) incorporates numerous fixes, enhancements, and architectural improvements that provide:

  • Reliability: <1% error rate vs 15-20% previously
  • Control: Feature flags and dry-run capability
  • Persistence: Full historical data retention
  • Monitoring: Comprehensive observability
  • Scalability: Parallel processing architecture

The system is currently in stable production with ServiceFusion enabled, processing work orders successfully with all critical fixes applied through August 20, 2025.

Document Generated: August 20, 2025

Based on Production State: Lambda v166, Layer v126

Account: 557477747490 (NEW AWS)

More about me

My aim is to live a balanced and meaningful life, where all areas of my life are in harmony. By living this way, I can be the best version of myself and make a positive difference in the world. About me →

Social

X

Youtube

Behance

Medium

Contact

Linkedin

Schedule a Call

Email

Resources

Github

Press

Sitemap

RSS Feed

┌─────────────┐      ┌─────────────┐      ┌─────────────┐
│PropertyWare │      │  DynamoDB   │      │ServiceFusion│
│    (SOAP)   │─────▶│ (Temporary) │─────▶│   (REST)    │
└─────────────┘      └─────────────┘      └─────────────┘
                            │
                     [Data deleted after sync]
┌─────────────┐      ┌─────────────┐      ┌─────────────┐
│PropertyWare │      │  Supabase   │      │ServiceFusion│
│    (SOAP)   │─────▶│ PostgreSQL  │◀────▶│   (REST)    │
└─────────────┘      └─────────────┘      └─────────────┘
        │                    │                    │
        └────────────────────┼────────────────────┘
                             │
                    ┌─────────────────┐
                    │ Kimball Model   │
                    │ • Fact Tables    │
                    │ • Dimensions     │
                    │ • History        │
                    └─────────────────┘
// Enhanced with feature flags and validationconst { common, data, services } = require("greenlight");const { propertyware: pw, servicefusion: sf, supabase, deduplication } = services;// Conditional sync with multiple checksconst STATUS_OPEN = [
  "unscheduled", "scheduled", "scheduled outside sf",  "dispatched", "delayed", "on the way", "on site",  "started", "paused", "resumed", "partially completed",  "open", "wo received", "awaiting parts"];if (process.env.ENABLE_SERVICE_FUSION === 'true' &&
    !process.env.DRY_RUN === 'true' &&    STATUS_OPEN.includes(workOrder.status.toLowerCase())) {
    // Check for duplicates first    const isDuplicate = await deduplication.checkDuplicate(workOrder);    if (!isDuplicate) {
        await sf.createJob(workOrder);    }
}
Trigger Sources:
├── EventBridge (Schedule)
├── HTTP API (Manual)
└── Lambda Console (Debug)
           ↓
      WebTrigger
           ↓
    SNS Topic Publishing
           ↓
    Parallel Execution:
    ├── workorders.getPWPortfolios
    ├── workorders.getPWWorkOrders
    ├── workorders.getSFCustomers
    ├── workorders.getSFJobs
    ├── leases.getPWBuildings
    ├── leases.getPWLeases
    ├── workorders.pushWorkOrdersToSF
    ├── workorders.pushPortfoliosToSF
    ├── leases.pushLeaseTenantsToSF
    └── workorders.pushJobUpdatesToPW
// Current Production Configuration (as of Aug 20, 2025){
  "DRY_RUN": "false",                    // Production mode active  "ENABLE_SERVICE_FUSION": "true",       // SF sync enabled  "SAFE_MODE": "true",                   // Extra validation active  "FEATURE_FLAG_PW_WO_VERIFY_STRICT": "false",  // Flexible validation  "FEATURE_PW_OPEN_STATUSES": "open,partially completed,awaiting parts,...",  "SNSTOPIC": "arn:aws:sns:us-east-1:557477747490:GreenLightSNSTopic",  "SUPABASE_URL": "https://gvdslkuqiezmkombppqe.supabase.co"}
try {
    // Sync operation with validation} catch (error) {
    // Categorized error handling    if (error.code === 'ECONNRESET') {
        // PropertyWare connection fix        await pw.reconnect({ keepAlive: false });        // Retry with exponential backoff    } else if (error.status === 422) {
        // ServiceFusion validation error        await handleValidationError(error);        // Log to error_logs table    } else if (error.message.includes('duplicate')) {
        // Duplicate detection        await deduplication.handleDuplicate(entity);        // Skip and continue    }
    // Store error for analysis    await supabase.from('error_logs').insert({
        timestamp: new Date(),        function: context.functionName,        error: error.message,        stack: error.stack,        recovery_action: recoveryAction
    });}