|
| 1 | +# Memora Trait Type Casting - Implementation Approaches |
| 2 | + |
| 3 | +**Date:** March 3, 2026 |
| 4 | +**Project:** Memora Destination - Segment Actions |
| 5 | +**Purpose:** Evaluate different approaches for handling trait type conversion when syncing data to Memora |
| 6 | + |
| 7 | +--- |
| 8 | + |
| 9 | +## Problem Statement |
| 10 | + |
| 11 | +Memora traits have specific data types (STRING, NUMBER, BOOLEAN, DATE) that must be respected when sending data. Segment events contain string values that need to be converted to the correct type. We need to determine the best approach to obtain trait type information and perform conversions at runtime. |
| 12 | + |
| 13 | +--- |
| 14 | + |
| 15 | +## Approach 1: User-Selected Types (Current Implementation) |
| 16 | + |
| 17 | +### Description |
| 18 | + |
| 19 | +Users explicitly select the trait type for each field mapping through a dropdown interface with hardcoded type options (STRING, NUMBER, BOOLEAN, DATE). |
| 20 | + |
| 21 | +### How It Works |
| 22 | + |
| 23 | +- Contact traits field is an array of objects |
| 24 | +- Each mapping contains: `trait_name`, `trait_type`, `value` |
| 25 | +- Trait type is selected from a predefined dropdown |
| 26 | +- Type conversion happens at runtime based on user selection |
| 27 | + |
| 28 | +### Advantages |
| 29 | + |
| 30 | +✅ **No Runtime API Calls** - Zero performance overhead |
| 31 | +✅ **No External Dependencies** - No Redis or caching infrastructure needed |
| 32 | +✅ **Immediate Availability** - Works out of the box |
| 33 | +✅ **User Control** - Users explicitly define expected types |
| 34 | +✅ **Simple Architecture** - Straightforward implementation |
| 35 | +✅ **Cost Effective** - No additional infrastructure costs |
| 36 | +✅ **Portable** - Works across all environments without setup |
| 37 | + |
| 38 | +### Disadvantages |
| 39 | + |
| 40 | +❌ **Manual Configuration** - Users must select type for each trait |
| 41 | +❌ **Error Prone** - Users might select wrong type |
| 42 | +❌ **Schema Drift** - User selections can become stale if Memora schema changes |
| 43 | +❌ **Extra UI Steps** - More fields to configure per trait |
| 44 | +❌ **No Validation** - Type selection not validated against actual Memora schema |
| 45 | +❌ **Maintenance Burden** - Users responsible for keeping types in sync |
| 46 | + |
| 47 | +### Implementation Complexity |
| 48 | + |
| 49 | +**Low** - Single code change, no infrastructure |
| 50 | + |
| 51 | +### Maintenance Burden |
| 52 | + |
| 53 | +**Low** - Stable implementation, no external dependencies |
| 54 | + |
| 55 | +--- |
| 56 | + |
| 57 | +## Approach 2: Fetch Trait Info Before Request |
| 58 | + |
| 59 | +### Description |
| 60 | + |
| 61 | +Fetch trait schema from Memora API at runtime before processing each batch of events. Cache the schema in memory with TTL to reduce API calls. |
| 62 | + |
| 63 | +### How It Works |
| 64 | + |
| 65 | +- When `perform()` executes, check in-memory cache for trait schema |
| 66 | +- If cache miss or expired, make API call to fetch trait definitions |
| 67 | +- Cache response for 1 hour (or configurable TTL) |
| 68 | +- Use cached schema to convert trait values to correct types |
| 69 | +- Cache is per-instance, lost on service restart |
| 70 | + |
| 71 | +### Advantages |
| 72 | + |
| 73 | +✅ **Accurate Schema** - Always uses real Memora trait definitions |
| 74 | +✅ **Auto-Discovery** - No user configuration of types needed |
| 75 | +✅ **Schema Validation** - Can validate against actual Memora schema |
| 76 | +✅ **Reduced API Calls** - Caching minimizes performance impact |
| 77 | +✅ **Self-Healing** - Automatically picks up schema changes after TTL |
| 78 | +✅ **No User Error** - Eliminates possibility of user selecting wrong type |
| 79 | + |
| 80 | +### Disadvantages |
| 81 | + |
| 82 | +❌ **Runtime API Calls** - Initial call per store per instance adds latency |
| 83 | +❌ **Cache Limitations** - Cache lost on restarts, not shared across instances |
| 84 | +❌ **Cold Start Penalty** - First batch after restart slower |
| 85 | +❌ **Rate Limits** - Could hit Memora API rate limits with many stores |
| 86 | +❌ **Failure Mode** - If fetch fails, events are blocked |
| 87 | +❌ **Memory Usage** - Cache consumes memory for trait schemas |
| 88 | +❌ **Complexity** - Need cache invalidation, TTL management, error handling |
| 89 | + |
| 90 | +### Implementation Complexity |
| 91 | + |
| 92 | +**Medium** - In-memory cache, TTL management, error handling |
| 93 | + |
| 94 | +### Maintenance Burden |
| 95 | + |
| 96 | +**Medium** - Need to monitor cache effectiveness, tune TTL |
| 97 | + |
| 98 | +--- |
| 99 | + |
| 100 | +## Approach 3: Redis Cache |
| 101 | + |
| 102 | +### Description |
| 103 | + |
| 104 | +Store trait schemas in Redis with TTL. Share cache across all service instances to minimize API calls and improve consistency. |
| 105 | + |
| 106 | +### How It Works |
| 107 | + |
| 108 | +- On first request for a store, fetch trait schema from Memora API |
| 109 | +- Store schema in Redis with configurable TTL (e.g., 1 hour) |
| 110 | +- All instances read from shared Redis cache |
| 111 | +- Background job can warm cache proactively |
| 112 | +- Support manual cache invalidation if needed |
| 113 | + |
| 114 | +### Advantages |
| 115 | + |
| 116 | +✅ **Shared Cache** - All instances benefit from cached data |
| 117 | +✅ **Persistent Cache** - Survives service restarts |
| 118 | +✅ **Minimal API Calls** - Only one fetch per store per TTL across entire cluster |
| 119 | +✅ **Accurate Schema** - Uses real Memora trait definitions |
| 120 | +✅ **Scalable** - Handles high volume efficiently |
| 121 | +✅ **Cache Warming** - Can preload cache for known stores |
| 122 | +✅ **Manual Control** - Support cache invalidation when needed |
| 123 | + |
| 124 | +### Disadvantages |
| 125 | + |
| 126 | +❌ **Infrastructure Required** - Needs Redis deployment and management |
| 127 | +❌ **Operational Overhead** - Monitor Redis health, handle failures |
| 128 | +❌ **Complexity** - Connection management, retry logic, fallback strategy |
| 129 | +❌ **Cost** - Additional infrastructure costs for Redis |
| 130 | +❌ **Network Dependency** - Redis network calls add latency |
| 131 | +❌ **Failure Mode** - Need fallback if Redis unavailable |
| 132 | +❌ **Schema Staleness** - Data could be stale until TTL expires |
| 133 | +❌ **Security** - Need secure Redis access controls |
| 134 | + |
| 135 | +### Implementation Complexity |
| 136 | + |
| 137 | +**High** - Redis setup, connection pooling, error handling, fallback logic |
| 138 | + |
| 139 | +### Maintenance Burden |
| 140 | + |
| 141 | +**High** - Monitor Redis, handle failures, tune cache settings, manage infrastructure |
| 142 | + |
| 143 | +--- |
| 144 | + |
| 145 | +## Approach 4: Memora API Native Support |
| 146 | + |
| 147 | +### Description |
| 148 | + |
| 149 | +Memora team adds native type conversion support to their API. API accepts any value type and converts based on trait schema automatically. |
| 150 | + |
| 151 | +### How It Works |
| 152 | + |
| 153 | +- Send trait values as-is (strings, numbers, booleans) |
| 154 | +- Memora API looks up trait schema internally |
| 155 | +- API performs type conversion/validation server-side |
| 156 | +- Returns clear error messages for type mismatches |
| 157 | +- No client-side type handling needed |
| 158 | + |
| 159 | +### Advantages |
| 160 | + |
| 161 | +✅ **Zero Implementation** - No Segment-side code changes needed |
| 162 | +✅ **Authoritative Source** - Memora is source of truth for schema |
| 163 | +✅ **No Caching Needed** - Memora handles schema internally |
| 164 | +✅ **Best Performance** - No additional API calls or cache lookups |
| 165 | +✅ **No Schema Drift** - Always current schema |
| 166 | +✅ **Simplified Client** - Segment just passes through values |
| 167 | +✅ **Better Error Messages** - API can provide specific type errors |
| 168 | +✅ **Works for All Clients** - Benefits all API consumers, not just Segment |
| 169 | + |
| 170 | +### Disadvantages |
| 171 | + |
| 172 | +❌ **External Dependency** - Relies on Memora team implementation |
| 173 | +❌ **Timeline Uncertainty** - No control over when feature is available |
| 174 | +❌ **Blocked Implementation** - Can't proceed without Memora changes |
| 175 | +❌ **API Version Management** - May require API version upgrades |
| 176 | +❌ **Potential Breaking Changes** - Memora API changes could break integration |
| 177 | +❌ **Limited Control** - Can't customize conversion logic if needed |
| 178 | + |
| 179 | +### Implementation Complexity |
| 180 | + |
| 181 | +**Zero** (Segment side) / **Unknown** (Memora side) |
| 182 | + |
| 183 | +### Maintenance Burden |
| 184 | + |
| 185 | +**Zero** (after Memora implements) |
| 186 | + |
| 187 | +--- |
| 188 | + |
| 189 | +## Comparison Matrix |
| 190 | + |
| 191 | +| Criteria | Approach 1: User-Selected | Approach 2: Runtime Fetch | Approach 3: Redis Cache | Approach 4: API Native | |
| 192 | +| -------------------------- | ------------------------- | ------------------------- | ----------------------- | ---------------------- | |
| 193 | +| **Runtime Performance** | Excellent | Good | Very Good | Excellent | |
| 194 | +| **Accuracy** | User-dependent | High | High | Perfect | |
| 195 | +| **Implementation Time** | 1 day | 3-5 days | 1-2 weeks | Unknown | |
| 196 | +| **Infrastructure Cost** | None | None | Medium | None | |
| 197 | +| **Operational Complexity** | Low | Medium | High | Low | |
| 198 | +| **Schema Freshness** | Manual | 1 hour | 1 hour | Real-time | |
| 199 | +| **User Experience** | More steps | Automatic | Automatic | Automatic | |
| 200 | +| **Failure Risk** | Low | Medium | High | Low | |
| 201 | + |
| 202 | +--- |
| 203 | + |
| 204 | +## Recommended Approach |
| 205 | + |
| 206 | +### Short-term (Immediate Implementation) |
| 207 | + |
| 208 | +**Approach 1: User-Selected Types** |
| 209 | + |
| 210 | +**Rationale:** |
| 211 | + |
| 212 | +- Can be deployed immediately |
| 213 | +- No infrastructure dependencies |
| 214 | +- Low risk, simple to maintain |
| 215 | +- Provides immediate value to customers |
| 216 | +- Can be replaced later if needed |
| 217 | + |
| 218 | +### Long-term (Ideal Solution) |
| 219 | + |
| 220 | +**Approach 4: API Native Support** |
| 221 | + |
| 222 | +**Rationale:** |
| 223 | + |
| 224 | +- Best customer experience |
| 225 | +- Zero maintenance burden |
| 226 | +- Most accurate and reliable |
| 227 | +- Benefits entire Memora ecosystem |
| 228 | + |
| 229 | +### Recommended Path Forward |
| 230 | + |
| 231 | +1. **Phase 1 (Now):** Implement Approach 1 (User-Selected Types) |
| 232 | + |
| 233 | + - Deploy working solution immediately |
| 234 | + - Gather user feedback on UX |
| 235 | + - Monitor for type-related errors |
| 236 | + |
| 237 | +2. **Phase 2 (3-6 months):** Engage Memora Team on Approach 4 |
| 238 | + |
| 239 | + - Present use case for native type support |
| 240 | + - Discuss API enhancement timeline |
| 241 | + - Plan migration strategy |
| 242 | + |
| 243 | +3. **Phase 3 (If Needed):** Consider Approach 2 as interim solution |
| 244 | + |
| 245 | + - If Approach 4 takes >6 months |
| 246 | + - If user feedback shows Approach 1 is too error-prone |
| 247 | + - Implement in-memory caching to reduce friction |
| 248 | + |
| 249 | +4. **Phase 4 (When Ready):** Migrate to Approach 4 |
| 250 | + - Remove client-side type handling |
| 251 | + - Simplify configuration UI |
| 252 | + - Document migration for existing customers |
| 253 | + |
| 254 | +--- |
| 255 | + |
| 256 | +## Decision Factors |
| 257 | + |
| 258 | +Choose **Approach 1** if: |
| 259 | + |
| 260 | +- Need solution immediately |
| 261 | +- Want zero operational overhead |
| 262 | +- Acceptable for users to configure types |
| 263 | +- Schema changes are infrequent |
| 264 | + |
| 265 | +Choose **Approach 2** if: |
| 266 | + |
| 267 | +- Schema accuracy is critical |
| 268 | +- Users shouldn't manage types |
| 269 | +- Can accept slight performance impact |
| 270 | +- Don't want infrastructure complexity |
| 271 | + |
| 272 | +Choose **Approach 3** if: |
| 273 | + |
| 274 | +- High volume with many stores |
| 275 | +- Need consistent cache across instances |
| 276 | +- Have Redis infrastructure already |
| 277 | +- Can manage additional complexity |
| 278 | + |
| 279 | +Choose **Approach 4** if: |
| 280 | + |
| 281 | +- Can wait for Memora team implementation |
| 282 | +- Want long-term optimal solution |
| 283 | +- Need perfect schema accuracy |
| 284 | +- Want to minimize Segment-side complexity |
| 285 | + |
| 286 | +--- |
| 287 | + |
| 288 | +## Conclusion |
| 289 | + |
| 290 | +The recommended strategy is to implement **Approach 1** immediately as it provides working functionality with minimal complexity, while pursuing **Approach 4** with the Memora team as the long-term solution. This pragmatic approach delivers immediate value while working toward the ideal architecture. |
0 commit comments