Feed Services Documentation
Overview
Microservice Name: eq-foundation-service
Version: 9.0
API Reference: Swagger UI
Description
The Equinox Foundation Feed Services is the data orchestration and batch processing backbone of the Equinox 9.x commerce platform — enabling businesses to automate data imports, exports, synchronizations, and transformations across all platform services. This service provides centralized control over data processing pipelines, from catalog imports to GDPR exports, with flexible execution engines and comprehensive monitoring.
Business Value
| Capability | Business Outcome |
|---|---|
| Unified Feed Orchestration | One centralized platform for all data import/export operations — no scattered batch scripts across services |
| Multi-Engine Support | Choose the right execution engine (Lambda, Step Functions, Spring Batch, AWS Glue) for each job type |
| Automated Scheduling | Configure recurring feeds with EventBridge integration — schedule once, run forever |
| Real-Time Monitoring | Track every feed execution with detailed history, progress reporting, and error diagnostics |
| Multi-Tenant Isolation | Complete data segregation per tenant with business and instance-level filtering |
| Event-Driven Architecture | Fire-and-forget execution via EventBridge — services remain decoupled and independently scalable |
Who Uses It
| Persona | How They Interact |
|---|---|
| Data Operations Teams | Configure and schedule feeds, monitor execution history, troubleshoot failures |
| Commerce Managers | Trigger on-demand catalog imports/exports, sync inventory data, generate GDPR reports |
| Platform Administrators | Define feed templates, configure retry policies, manage execution clusters |
| Business Analysts | Access feed execution metrics, success rates, and performance statistics |
| Service Developers | Integrate new feed types, implement custom processors, extend Step Functions |
Related Resources
- Glossary: Section 13
- Batch API Reference: Section 5
- Feed Architectures:
docs/feed-architectures.md - BRD Document:
BRD-FEED-20260224-V1.0.md
Orchestrate Your Data. Automate Your Operations.
One platform. Every feed. Complete control.
The Equinox Foundation Feed Services gives commerce platforms a unified, scalable infrastructure for all data processing operations. Whether importing product catalogs, exporting inventory snapshots, or fulfilling GDPR data requests, Feed Services handles scheduling, execution, monitoring, and error recovery — so your teams can focus on business outcomes rather than managing batch infrastructure.
Why Equinox Feed Services?
Modern commerce platforms require reliable, automated data pipelines. Catalog updates, inventory synchronizations, price imports, and compliance exports must run on schedule, at scale, without manual intervention. Feed Services provides the orchestration layer that makes it possible.
Key Capabilities
Multi-Engine Execution
Support for Lambda functions, AWS Step Functions with Distributed Map, Spring Batch, and AWS Glue. Choose the right engine based on data volume, complexity, and processing requirements.
Event-Driven Architecture
Publish-subscribe pattern via EventBridge. Foundation Service publishes batch.job.initiated events; Job Initiator Lambda subscribes and starts Step Functions. Services remain decoupled and independently scalable.
Intelligent Scheduling
EventBridge-native scheduling with cron expressions and rate limits. Supports recurring schedules, one-time schedules, and on-demand execution. Pause, resume, or stop schedules without code changes.
Comprehensive Monitoring
Track every execution with detailed history records. Monitor status (INITIATED → RUNNING → COMPLETED/FAILED), progress percentage, chunk-level success rates, and error diagnostics. 90-day history retention with TTL.
Parallel Execution Control
Configure whether feeds can run concurrently. When allowParallelExecution=false, Foundation Service prevents resource contention by blocking new executions until the current one completes.
Automatic Retry & Error Recovery
Configurable retry policies (exponential backoff, fixed interval, circuit breaker). Error threshold enforcement with toleration policies. Failed chunks retry independently without reprocessing successful data.
Multi-Tenant by Design
Business-level and instance-level data isolation. Every batch, job, schedule, and execution is scoped to a specific tenant. Filters enforce access control at query time.
S3-Based Data Handoff
Stateless Lambda functions coordinate via S3. Upload raw files to imports/, process in chunks, write results to results/, generate error files in source format. No shared memory or database transactions across execution boundaries.
Who Benefits
| Persona | Business Benefit |
|---|---|
| Data Operations | Automated feed execution with scheduling, monitoring, and error recovery — reduce manual processing by 80% |
| Commerce Managers | On-demand data imports/exports via UI; track progress in real time; download error files for corrections |
| Platform Teams | Event-driven architecture with decoupled services; horizontally scalable execution; standard API contracts |
| Business Analysts | Access execution metrics, success rates, and performance statistics for reporting and optimization |
| Compliance Officers | Automated GDPR export and deletion workflows with complete audit trails |
At a Glance
| Metric | Detail |
|---|---|
| Execution Engines | Lambda, Step Functions (Distributed Map), Spring Batch, AWS Glue |
| Scheduling | EventBridge rules with cron/rate expressions |
| Data Storage | S3 (raw files, chunk files, result files, error files) |
| Feed Types | Import (Catalog, Inventory, Price, Category) / Export (Catalog, Inventory, GDPR) |
| Max Concurrent Chunks | 20 per Step Function Map (configurable per job) |
| History Retention | 90 days with TTL |
| Error Recovery | Exponential backoff, circuit breaker, error threshold enforcement |
| Deployment | Cloud-native — serverless (AWS Lambda + Step Functions) |
| Version | 9.0 |
| API Reference | Swagger UI |
Core Features
| # | Domain | Feature |
|---|---|---|
| 1 | Batch | Create, read, update, delete batch definitions (execution configuration, parallel control, max runtime) |
| 2 | Batch Job | Create, read, update, delete job definitions within a batch (job parameters, retry policy, error threshold) |
| 3 | Batch Schedule | Create, read, update, delete schedules for jobs (cron/rate expressions, EventBridge integration) |
| 4 | Batch Execution | Trigger job execution (on-demand or scheduled), track status, view progress, stop running jobs |
| 5 | Execution History | Complete audit trail of all executions with start/end times, status, result, error diagnostics |
| 6 | File Upload | Presigned S3 URLs for batch file uploads with validation and metadata tracking |
| 7 | Schedule State Management | Activate, pause, resume, stop schedules without deleting EventBridge rules |
| 8 | Progress Reporting | Real-time chunk-level progress updates with success/failure counts |
| 9 | Metrics & Analytics | Execution statistics, success rates, performance metrics per batch/job |
| 10 | PIM Catalog Import | Multi-sheet Excel/CSV import for products, SKUs, categories, attributes, prices |
| 11 | PIM Catalog Export | Multi-sheet Excel/CSV export with entity extraction order and locale support |
| 12 | PIM Category Import | Hierarchical category import with parent-child validation (sequential processing) |
| 13 | PIM Price Import | Price list import with date range validation and currency checks |
| 14 | Inventory Import | Multi-sheet import for locations, SKUs, lots, policies, positions, transactions |
| 15 | Inventory Export | Multi-sheet export with 9-entity hierarchy (3 levels: master, policy, transactional) |
| 16 | GDPR Export | User PII export as Excel (user, addresses, payments, lists, consents, orders) |
| 17 | GDPR Delete | Anonymize user PII after retention period (Step Functions + Lambda) |
| 18 | Error File Generation | Produces error files in source format with _importErrors column for failed rows |
| 19 | Distributed Map Processing | AWS Step Functions Distributed Map for parallel chunk processing (max 20 concurrent) |
| 20 | Retry Orchestration | Automatic retry with configurable policies (exponential backoff, max retries, circuit breaker) |
Batch & Job Concepts
Hierarchy
Batch (Execution Group)
├── Metadata: batchId, name, serviceType, executionType
├── Configuration: allowParallelExecution, maxRuntime, jobEndpoint
└── BatchJob (Executable Unit)
├── Metadata: jobId, name, status (ACTIVE/INACTIVE)
├── Configuration: jobParams (jobType, instanceId, catalogId, fileUrl, etc.)
├── Retry Policy: maxRetries, retryDelay, backoffMultiplier
├── Error Handling: errorThreshold, tolerationPolicy
└── BatchSchedule (Trigger Mechanism)
├── Metadata: scheduleId, name, status, state
├── Schedule: repeatInterval (cron/rate), startDate, endDate
├── State: ACTIVE, PAUSED, STOPPED
└── EventBridge: ruleName, targetArn, lastRunTime, nextRunTime
Core Entities
Batch
Purpose: Logical grouping of related jobs (e.g., “PIM Import Batch”, “Inventory Export Batch”).
Key Properties:
batchId— Unique identifier (kebab-case, e.g.,pim-catalog-import)serviceType— Service domain (e.g.,pim-import,inventory-export)executionType— Execution engine (LAMBDA,STEP_FUNCTION,SPRING_BATCH,GLUE)allowParallelExecution— Boolean flag controlling concurrent job instancesmaxRuntime— Maximum execution time in seconds (enforced by Step Functions timeout)jobEndpoint— Lambda ARN or API endpoint for execution
BatchJob
Purpose: Specific executable unit within a batch (e.g., “Product Full Refresh”, “Inventory Stock Sync”).
Key Properties:
-
jobId— Unique identifier within the batch -
status—ACTIVE(can execute) orINACTIVE(disabled) -
jobParams— Flat key-value object with execution parametersjobType— Feed type (e.g.,CATALOG_IMPORT,INVENTORY_EXPORT,GDPR_EXPORT)instanceId— Tenant identifier (multi-tenant isolation)catalogId— PIM catalog identifier (for catalog-scoped jobs)fileUrl— S3 path for import files (for import jobs)chunkSize— Number of rows per chunk (default: 100)- Custom parameters per job type
-
Retry Policy:
maxRetries— Maximum retry attempts (default: 3)retryDelay— Initial delay in seconds (default: 60)backoffMultiplier— Exponential backoff factor (default: 2)retryStrategy—exponential,fixed,circuitBreaker
-
Error Handling:
errorThreshold— Percentage of failures allowed before job fails (default: 10)tolerationPolicy—STRICT(fail fast) orLENIENT(continue with errors)
BatchSchedule
Purpose: Trigger mechanism for recurring or on-demand job execution.
Key Properties:
scheduleId— Unique identifier within the jobstatus—SCHEDULED(cron/rate) orONDEMAND(manual trigger)state—ACTIVE,PAUSED,STOPPED(lifecycle state)repeatInterval— EventBridge expression- Cron:
cron(0 10 * * ? *)— Daily at 10:00 AM UTC - Rate:
rate(1 day)— Every 24 hours
- Cron:
startDate/endDate— Schedule validity windoweventBridgeRuleName— Generated rule name (format:{stage}-fnd-{batchId}-{jobId}-{scheduleId})lastRunTime/nextRunTime— Execution tracking
Special Status: ONDEMAND
- Creates schedule record but skips EventBridge rule creation
- Immediately triggers
executeBatchJob()and returnsrunRequestId - Used for UI-triggered imports/exports and GDPR requests
Execution Lifecycle
1. INITIATED — Job record created in MongoDB, EventBridge event published
└─► Job Initiator Lambda subscribes to event
2. PENDING — Job Initiator Lambda invokes Step Function
└─► Step Function starts execution
3. RUNNING — Step Function processes chunks via Distributed Map
└─► Lambda functions validate, parse, process data
4. COMPLETED — All chunks processed successfully
└─► Result file(s) written to S3
└─► History record updated with end time, duration, result
└─► EventBridge event: batch.execution.completed
5. FAILED — Execution failed (validation error, threshold exceeded, timeout)
└─► Error message recorded in history
└─► EventBridge event: batch.execution.failed
└─► Retry policy determines if retry is triggered
Parallel Execution Control
When allowParallelExecution = false:
- Foundation Service checks for existing
RUNNINGexecutions for same(batchId, jobId) - If found: Throws
BATCH_JOB_ALREADY_RUNNINGerror (HTTP 409 Conflict) - Purpose: Prevent resource contention and ensure sequential execution
When allowParallelExecution = true:
- Multiple concurrent executions allowed for same job
- Each execution tracked independently by
runRequestId - Use case: Tenant-specific imports running in parallel
API Endpoints
Swagger UI: https://eq9-pdn1.equinox.shop/foundation-service-prod/documentation
API prefix: /v1
Security: Bearer JWT token in
Authorizationheader. Privileges are enforced per endpoint viapreHandlerhooks.
Batch Management (/src/routes/batch.routes.ts)
| Method | Path | Privilege | Description |
|---|---|---|---|
| POST | /v1/batches |
foundation:createBatch |
Create a new batch entity |
| GET | /v1/batches |
foundation:viewBatch |
List batches (paginated, filterable by instanceId) |
| GET | /v1/batches/:batchId |
foundation:viewBatch |
Get specific batch by batchId |
| PATCH | /v1/batches/:batchId |
foundation:updateBatch |
Partial update of batch properties |
| DELETE | /v1/batches/:batchId |
foundation:deleteBatch |
Soft-delete batch (cascades to jobs and schedules) |
Batch Job Management (/src/routes/batchJob.routes.ts)
| Method | Path | Privilege | Description |
|---|---|---|---|
| POST | /v1/batches/:batchId/jobs |
foundation:createBatch |
Create a new job within a batch |
| GET | /v1/batches/:batchId/jobs |
foundation:viewBatch |
List jobs for a batch (paginated) |
| GET | /v1/batches/:batchId/jobs/:jobId |
foundation:viewBatch |
Get specific job by jobId |
| PATCH | /v1/batches/:batchId/jobs/:jobId |
foundation:updateBatch |
Partial update of job properties |
| DELETE | /v1/batches/:batchId/jobs/:jobId |
foundation:deleteBatch |
Soft-delete job (cascades to schedules) |
Batch Schedule Management (/src/routes/batchSchedule.routes.ts)
| Method | Path | Privilege | Description |
|---|---|---|---|
| POST | /v1/batches/:batchId/jobs/:jobId/schedules |
foundation:createBatch |
Create schedule (EventBridge rule or ONDEMAND trigger) |
| GET | /v1/batches/:batchId/jobs/:jobId/schedules |
foundation:viewBatch |
List schedules for a job (paginated) |
| GET | /v1/batches/:batchId/jobs/:jobId/schedules/:scheduleId |
foundation:viewBatch |
Get specific schedule by scheduleId |
| PATCH | /v1/batches/:batchId/jobs/:jobId/schedules/:scheduleId |
foundation:updateBatch |
Update schedule properties (resyncs EventBridge rule) |
| DELETE | /v1/batches/:batchId/jobs/:jobId/schedules/:scheduleId |
foundation:deleteBatch |
Delete schedule (removes EventBridge rule) |
| POST | /v1/schedules/:scheduleId/state |
foundation:updateBatch |
Change schedule state (ACTIVE → PAUSED → STOPPED) |
Batch Execution (/src/routes/batchExecution.routes.ts)
| Method | Path | Privilege | Description |
|---|---|---|---|
| POST | /v1/batches/:batchId/jobs/:jobId/execute |
foundation:executeBatch |
Trigger job execution (on-demand) |
| POST | /v1/batches/:batchId/jobs/:jobId/history/:runRequestId/status |
Internal (Lambda callback) | Update execution status from Lambda |
| POST | /v1/batches/:batchId/jobs/:jobId/history/:runRequestId/progress |
Internal (Lambda callback) | Update execution progress (chunk-level) |
| POST | /v1/batches/:batchId/jobs/:jobId/history/:runRequestId/stop |
foundation:executeBatch |
Stop running execution (Step Functions StopExecution API) |
| GET | /v1/batches/:batchId/jobs/:jobId/history |
foundation:viewBatchHistory |
Get execution history (filterable by status, date range) |
| GET | /v1/batches/:batchId/jobs/:jobId/history/:runRequestId |
foundation:viewBatchHistory |
Get specific execution by runRequestId |
| GET | /v1/batches/:batchId/jobs/:jobId/metrics |
foundation:viewBatchHistory |
Get execution metrics (success rate, avg duration, failure count) |
File Upload (/src/routes/fileUpload.routes.ts)
| Method | Path | Privilege | Description |
|---|---|---|---|
| POST | /v1/batch-uploads |
foundation:uploadBatchFile |
Generate presigned S3 URL for file upload |
| GET | /v1/batch-uploads |
foundation:viewBatchUpload |
List uploaded files (paginated) |
| GET | /v1/batch-uploads/:uploadId |
foundation:viewBatchUpload |
Get specific upload metadata |
Available Feeds Summary
PIM Feeds (Product Information Management)
| Feed Type | Job Type | Direction | Input Format | Output Format | Max Concurrency | Processing Order |
|---|---|---|---|---|---|---|
| Catalog Import | CATALOG_IMPORT |
Import | CSV, XLSX | Error CSV/XLSX | 20 | Unordered |
| Category Import | CATEGORY_IMPORT |
Import | CSV, XLSX | Error CSV/XLSX | 1 (Sequential) | Hierarchical (depth-first) |
| Price Import | PRICE_IMPORT |
Import | CSV, XLSX | Error CSV/XLSX | 20 | Unordered |
| Catalog Export | PIM_CATALOG_EXPORT |
Export | — | Excel (multi-sheet) | 20 | Entity extraction order |
Key Characteristics:
- Chunk Size: 100 rows per chunk (configurable)
- Entity Extraction Order (Export):
Level 1: products, categories, attributes Level 2: skus, prices, media Level 3: productAttributes, categoryAssociations - Validation: Schema validation + reference validation (categories exist, SKUs exist, etc.)
- Error Handling: Row-level errors collected, source file regenerated with
_importErrorscolumn
Inventory Feeds
| Feed Type | Job Type | Direction | Input Format | Output Format | Max Concurrency | Processing Order |
|---|---|---|---|---|---|---|
| Inventory Multi-Sheet Import | INVENTORY_MULTI_SHEET_IMPORT |
Import | Excel (multi-sheet) | Error Excel | 5 | Sheet order: locations → SKUs → lots → policies → positions |
| Inventory Export | INVENTORY_EXPORT |
Export | — | Excel (9 sheets) | 20 | Entity extraction order (3 levels) |
Entity Extraction Order (Export):
Level 1 (Master): locations, skus, lots
Level 2 (Policy): locationChannelPolicy, replenishmentPolicy, reservations
Level 3 (Transactional): inventoryPositions, inventoryTransactions, transfers
Key Characteristics:
- Database: MySQL (relational) — uses SQL queries with
WHERE instance_id = ? - Tenant Isolation: SQL-based filtering (vs MongoDB composite IDs in PIM)
- Chunk Size: 100 rows per entity (configurable)
- Reference Validation: SKUs validated against master SKU table, locations validated, etc.
GDPR Feeds (Compliance)
| Feed Type | Job Type | Direction | Services | Output Format | Retention | Processing Order |
|---|---|---|---|---|---|---|
| GDPR Export | GDPR_EXPORT |
Export | User, Payment, Order, List | Excel (2 sheets: User, Orders) | S3 90-day presigned URL | Parallel (User + Orders) |
| GDPR Delete | GDPR_DELETE |
Delete | User, Payment, List, Consent | — | Retention period (configurable) | Sequential (anonymize + hard-delete) |
GDPR Export Details:
- Orchestrator: Foundation Service (Step Functions coordinator)
- Data Fetchers:
gdpr.export.fetchUser→ UserServices Lambda (readsuserdb_*)gdpr.export.fetchOrders→ OMS Lambda (readsomsdb_*)
- Output Sheets:
- User Sheet: First Name, Last Name, Email, Phone, Gender, DOB, Status, Addresses, Payment Cards, Custom Properties, Consents, Marketing Preferences
- Orders Sheet: Order ID, Order Date, Order Status, SKU ID, SKU Name, Quantity, Unit Price, Shipping Method, Item Status, Shipping Charges, Taxes, Discounts, Order Total
- Trigger: ONDEMAND schedule via UI or API
- Delivery: Presigned S3 URL (90-day expiry)
GDPR Delete Details:
- Trigger: Step Functions (scheduled retention check)
- Retention Period: Configurable days (passed as Step Function input)
- Actions:
gdpr.delete.initialize— Calculate expiry date, chunk sizegdpr.delete.fetchEligibleUsers— Query users withstatus=DELETEDanddeletedAt < expiryDategdpr.delete.anonymizeUser— Anonymize PII fields (name, email, phone → hashed values)gdpr.delete.aggregate— Summarize results (users anonymized, lists deleted)
- Outcome: User records remain in database with anonymized data; lists hard-deleted
Feed Type Comparison
| Dimension | PIM Catalog Import | Inventory Import | GDPR Export | GDPR Delete |
|---|---|---|---|---|
| Database | MongoDB | MySQL | MongoDB (multi-DB) | MongoDB (multi-DB) |
| Tenant Isolation | Composite _id |
SQL WHERE instanceId |
instanceId filter |
instanceId filter |
| Processing Model | Distributed Map | Sequential + Parallel | Parallel branches | Sequential chunks |
| Error Recovery | Chunk-level retry | Sheet-level retry | Full job retry | User-level retry |
| Output File | Source format + errors | Source format + errors | Excel (2 sheets) | None (anonymization) |
| Max Concurrency | 20 | 5 | 2 (User + Orders) | 10 (user chunks) |
Events
All events are published to AWS EventBridge. Source:
"foundation-service". Bus:EVENT_BUS_NAMEenv var.
Published viafastify.publishEvent({ type, data })from@equinox/event-bridge-implementationplugin.
Published Events (EventBridge)
Batch Lifecycle Events
| Event Type | Trigger | Key Data Fields |
|---|---|---|
batch.created |
Batch creation success | batchId, instanceId, name, serviceType, executionType, createdBy, timestamp |
batch.updated |
Batch update | batchId, instanceId, updatedFields, updatedBy, timestamp |
batch.deleted |
Batch deletion (soft-delete, cascades to jobs/schedules) | batchId, instanceId, deletedBy, timestamp |
Batch Job Lifecycle Events
| Event Type | Trigger | Key Data Fields |
|---|---|---|
batch.job.created |
Job creation success | batchId, jobId, instanceId, name, status, createdBy, timestamp |
batch.job.updated |
Job update | batchId, jobId, instanceId, updatedFields, updatedBy, timestamp |
batch.job.deleted |
Job deletion (cascades to schedules) | batchId, jobId, instanceId, cascadedSchedules, deletedBy, timestamp |
Batch Schedule Lifecycle Events
| Event Type | Trigger | Key Data Fields |
|---|---|---|
batch.schedule.created |
Schedule creation (EventBridge rule created) | batchId, jobId, scheduleId, instanceId, name, status, state, repeatInterval, eventBridgeRuleName, createdBy, timestamp |
batch.schedule.updated |
Schedule update (EventBridge rule updated) | batchId, jobId, scheduleId, instanceId, updatedFields, eventBridgeRuleName, updatedBy, timestamp |
batch.schedule.deleted |
Schedule deletion (EventBridge rule removed) | batchId, jobId, scheduleId, instanceId, eventBridgeRuleName, deletedBy, timestamp |
batch.schedule.state_changed |
Schedule state transition | batchId, jobId, scheduleId, instanceId, previousState, newState, eventBridgeRuleName, timestamp |
Batch Execution Events
| Event Type | Trigger | Key Data Fields |
|---|---|---|
batch.job.initiated |
Job execution initiated (ONDEMAND or scheduled) | batchId, jobId, runRequestId, instanceId, jobConfig, s3KeyPrefix, callbackBaseUrl, timestamp |
batch.execution.started |
Step Function execution started | runRequestId, batchId, jobId, scheduleId, status: "RUNNING", timestamp |
batch.execution.completed |
Execution completed successfully | runRequestId, batchId, jobId, status: "COMPLETED", result, duration, timestamp |
batch.execution.failed |
Execution failed (validation, threshold, timeout) | runRequestId, batchId, jobId, status: "FAILED", errorMessage, timestamp |
batch.execution.threshold_exceeded |
Error threshold exceeded during execution | runRequestId, batchId, jobId, recordsFailed, threshold, timestamp |
batch.execution.stopped |
Execution manually stopped | runRequestId, batchId, jobId, status: "STOPPED", stoppedBy, timestamp |
batch.execution.max_retries_exhausted |
All retry attempts failed | runRequestId, batchId, jobId, attemptNumber, maxRetries, timestamp |
batch.execution.retry_requested |
Retry triggered by policy | runRequestId, batchId, jobId, attemptNumber, retryDelay, timestamp |
batch.execution.retry_started |
Retry Lambda invoked successfully | runRequestId, batchId, jobId, attemptNumber, timestamp |
batch.execution.retry_failed |
Retry Lambda invocation failed | runRequestId, batchId, jobId, attemptNumber, error, timestamp |
Consumed Events (Inbound)
Inbound events arrive via the EventBridge Lambda handler (
/src/handlers/eventbridge.handler.ts).
| Detail Type | Source | Handler Action |
|---|---|---|
batch.job.initiated |
foundation-service (self-emitted) |
Job Initiator Lambda starts Step Function |
app.* (e.g., app.enabled, app.disabled) |
marketplace-service |
Marketplace event handler — updates installed connector configurations |
Payload Models (Key Events)
All events are wrapped in the EventBridge envelope. The
datafield below is thedetail.datapayload.
batch.job.initiated
Published when: ONDEMAND schedule created or scheduled execution triggers.
{
"type": "batch.job.initiated",
"data": {
"batchId": "pim-catalog-import",
"jobId": "product-full-refresh",
"runRequestId": "550e8400-e29b-41d4-a716-446655440000",
"instanceId": "prod-us-east",
"jobConfig": {
"jobType": "CATALOG_IMPORT",
"instanceId": "prod-us-east",
"catalogId": "master",
"fileUrl": "s3://bucket/imports/550e8400.../catalog.xlsx",
"chunkSize": 100,
"validateMode": "full",
"mapMaxConcurrency": 20
},
"s3KeyPrefix": "imports/550e8400-e29b-41d4-a716-446655440000",
"callbackBaseUrl": "https://api.equinox.shop/foundationservices",
"timestamp": "2026-08-07T10:00:00.000Z"
}
}
batch.execution.completed
Published when: Step Function completes successfully.
{
"type": "batch.execution.completed",
"data": {
"runRequestId": "550e8400-e29b-41d4-a716-446655440000",
"batchId": "pim-catalog-import",
"jobId": "product-full-refresh",
"scheduleId": "daily-midnight-sync",
"status": "COMPLETED",
"result": {
"totalRecords": 5000,
"successRecords": 5000,
"failedRecords": 0,
"totalChunks": 50,
"processedChunks": 50,
"failedChunks": 0,
"outputFiles": ["s3://bucket/results/550e8400.../catalog_result.json"]
},
"duration": 180,
"timestamp": "2026-08-07T10:03:00.000Z"
}
}
batch.execution.failed
Published when: Execution fails (validation, threshold exceeded, timeout).
{
"type": "batch.execution.failed",
"data": {
"runRequestId": "550e8400-e29b-41d4-a716-446655440000",
"batchId": "pim-catalog-import",
"jobId": "product-full-refresh",
"status": "FAILED",
"errorMessage": "Validation failed: Required column 'productId' missing from input file",
"errorCode": "BATCH_VALIDATION_FAILED",
"timestamp": "2026-08-07T10:01:00.000Z"
}
}
Feed Architecture Patterns
Common Import Flow
User/UI → Foundation API → S3 Upload → EventBridge → Job Initiator Lambda
↓
Step Function (Distributed Map)
↓
┌─────────────────────────────┼─────────────────────────────┐
▼ ▼ ▼
VALIDATE PARSE + CHUNK PROCESS CHUNKS
(validate.lambda) (parse.lambda) (process.lambda × N)
Check file format Stream CSV/XLSX Validate rows
Verify required columns Split into chunks Transform to domain
Validate file size Write to S3 chunks/ Insert to MongoDB/MySQL
Write manifest.jsonl Write results to S3
↓ ↓ ↓
└─────────────────────────────┼─────────────────────────────┘
↓
AGGREGATE
(aggregate.lambda)
Collect all results
Generate error file
Update history: COMPLETED
↓
FINALIZE
(finalize.lambda)
Publish completion event
Clean up temp files
Key Principles:
- Stateless Lambdas: No shared memory or database transactions across execution boundaries
- S3-Based Coordination: Raw files, chunk files, result files, error files all stored in S3
- Chunk-Level Retry: Failed chunks retry independently without reprocessing successful data
- Error Collection: Row-level errors collected, source file regenerated with
_importErrorscolumn - Event-Driven: EventBridge decouples services — Foundation publishes, Job Initiator subscribes
Distributed Map Pattern
AWS Step Functions Distributed Map enables high-throughput parallel processing:
{
"Type": "Map",
"ItemReader": {
"Resource": "arn:aws:states:::s3:getObject",
"ReaderConfig": {
"InputType": "MANIFEST",
"CSVHeaderLocation": "FIRST_ROW"
},
"Parameters": {
"Bucket": "batch-bucket",
"Key.$": "$.manifestKey"
}
},
"MaxConcurrency": 20,
"ItemProcessor": {
"ProcessorConfig": {
"Mode": "DISTRIBUTED",
"ExecutionType": "STANDARD"
},
"StartAt": "ProcessChunk",
"States": {
"ProcessChunk": {
"Type": "Task",
"Resource": "arn:aws:lambda:us-east-1:123456789012:function:process-chunk",
"Retry": [
{
"ErrorEquals": ["States.ALL"],
"IntervalSeconds": 2,
"MaxAttempts": 2,
"BackoffRate": 2
}
],
"End": true
}
}
}
}
Configuration:
- MaxConcurrency: 20 (default) — How many chunks process in parallel
- Retry: 2 attempts with exponential backoff — Chunk-level failure recovery
- Manifest File: S3 JSONL file listing all chunk S3 keys
- Mode: DISTRIBUTED — High-scale processing (up to 10,000 parallel executions)
Batch Execution Flow
ONDEMAND Schedule Flow
Trigger: User clicks “Import Now” in UI or API call with status: "ONDEMAND"
1. POST /v1/batches/:batchId/jobs/:jobId/schedules
Body: { status: "ONDEMAND", parameters: { ... } }
↓
2. batchSchedule.service.ts — createBatchSchedule()
├── Validate parent batch + job exist and are ACTIVE
├── Validate required parameters (instanceId, fileUrl, etc.)
├── Save BatchSchedule record { status: "ONDEMAND", state: "ACTIVE" }
├── Detect status === "ONDEMAND"
└── Immediately call executeBatchJob()
↓
3. batchExecution.service.ts — executeEventDrivenJob()
├── Generate runRequestId (UUID)
├── Save batchHistory record { status: "INITIATED" }
├── Enrich jobConfig with s3KeyPrefix, callbackBaseUrl, foundationLambdaArn
└── Publish EventBridge event: batch.job.initiated
↓
4. EventBridge Rule → Job Initiator Lambda (subscribed to batch.job.initiated)
↓
5. Job Initiator Lambda
├── Validate jobConfig
├── Determine Step Function ARN based on jobType
├── Start Step Function execution
└── Return (fire-and-forget)
↓
6. Step Function (e.g., CatalogImport.json)
├── NormalizeInput (Pass state)
├── VALIDATE → Foundation Lambda (action: batch.validate)
├── PARSE + CHUNK → Foundation Lambda (action: batch.parseChunk)
├── DISTRIBUTED MAP → process.lambda × N (action: batch.processChunk)
├── AGGREGATE → Foundation Lambda (action: batch.aggregate)
└── FINALIZE → Foundation Lambda (action: batch.finalize)
├── Update batchHistory { status: "COMPLETED", result: {...} }
└── Publish EventBridge event: batch.execution.completed
Scheduled Execution Flow
Trigger: EventBridge rule fires based on cron/rate expression
1. EventBridge Rule (e.g., dev-fnd-pim-catalog-import-product-daily)
Cron: cron(0 10 * * ? *) — Daily at 10:00 AM UTC
↓
2. Target: Foundation Lambda (registered as EventBridge rule target)
Event Payload: { batchId, jobId, scheduleId, parameters: {...} }
↓
3. Foundation Lambda — eventbridge.handler.ts
├── Parse incoming EventBridge event
├── Extract { batchId, jobId, scheduleId }
└── Call executeBatchJob(batchId, jobId, scheduleId, parameters)
↓
4. batchExecution.service.ts — executeEventDrivenJob()
└── [Same flow as ONDEMAND starting from step 3 above]
Step Functions Integration
Step Function Definitions
The services that include jobs keep Step Function JSON definitions in the step-functions/ directory:
| Step Function | File | Purpose | Max Duration |
|---|---|---|---|
| CatalogImport | catalog-import.asl.json |
PIM catalog import with Distributed Map | 1 hour |
| CategoryImport | category-import.asl.json |
Hierarchical category import (sequential) | 30 minutes |
| PriceImport | price-import.asl.json |
Price list import with date validation | 30 minutes |
| CatalogExport | catalog-export.asl.json |
Multi-sheet PIM catalog export | 1 hour |
| InventoryMultiSheetImport | inventory-multi-sheet-import.asl.json |
Multi-sheet inventory import | 1 hour |
| InventoryExport | inventory-export.asl.json |
Multi-sheet inventory export (9 entities) | 1 hour |
| GdprExport | gdpr-export.asl.json |
GDPR user data export (User + Orders) | 15 minutes |
| GdprDelete | gdpr-delete.asl.json |
GDPR PII anonymization after retention | 2 hours |
Step Function State Types
| State Type | Purpose | Example |
|---|---|---|
| Pass | Transform input, add metadata | NormalizeInput, PrepareChunkConfig |
| Choice | Conditional branching | CheckJobType, CheckInitialization |
| Task | Lambda invocation | VALIDATE, PARSE, ProcessChunk |
| Map | Distributed parallel processing | DISTRIBUTED MAP (ItemReader: S3 manifest) |
| Parallel | Independent parallel branches | FetchData (User branch + Orders branch) |
| Fail | Terminal failure state | ValidationFailed, ThresholdExceeded |
| Succeed | Terminal success state | SlimOutput |
Lambda Action Routing
Foundation Lambda handler (src/handlers/lambda.handler.ts) routes Step Function tasks based on action field:
const action = event.action; // From Step Function Task state Parameters
switch (action) {
// Import actions
case "batch.validate":
return validateHandler(event);
case "batch.parseChunk":
return parseChunkHandler(event);
case "batch.processChunk":
return processChunkHandler(event);
case "batch.aggregate":
return aggregateHandler(event);
case "batch.finalize":
return finalizeHandler(event);
// Export actions
case "batch.export.initialize":
return exportInitializeHandler(event);
case "batch.export.extract":
return exportExtractHandler(event);
case "batch.export.buildFile":
return exportBuildFileHandler(event);
case "batch.export.finalize":
return exportFinalizeHandler(event);
// GDPR actions
case "gdpr.export.initialize":
return gdprInitializeHandler(event);
case "gdpr.export.buildExcel":
return gdprBuildExcelHandler(event);
case "gdpr.export.finalize":
return gdprFinalizeHandler(event);
case "gdpr.delete.initialize":
return gdprDeleteInitHandler(event);
case "gdpr.delete.anonymizeUser":
return gdprAnonymizeUserHandler(event);
case "gdpr.delete.aggregate":
return gdprDeleteAggregateHandler(event);
default:
throw new Error(`Unknown action: ${action}`);
}
Error Handling & Retry
Retry Policy Configuration
Batch-level retry policy (default for all jobs in the batch):
{
"retryPolicy": {
"maxRetries": 3,
"retryDelay": 60,
"backoffMultiplier": 2,
"retryStrategy": "exponential"
}
}
Job-level retry policy (overrides batch-level):
{
"jobParams": {
"retryPolicy": {
"maxRetries": 5,
"retryDelay": 30,
"backoffMultiplier": 1.5,
"retryStrategy": "fixed"
}
}
}
Retry Strategies:
exponential— Delay doubles on each retry (60s → 120s → 240s)fixed— Constant delay between retries (60s → 60s → 60s)circuitBreaker— Stop retrying after threshold failures (prevents cascading failures)
Error Threshold & Toleration Policy
Error Threshold: Percentage of failures allowed before job fails overall.
{
"errorThreshold": 10, // 10% of chunks can fail
"tolerationPolicy": "LENIENT" // Continue processing remaining chunks
}
Example:
- Total chunks: 100
- Threshold: 10%
- Maximum allowed failures: 10 chunks
- If 11th chunk fails → Job status: FAILED, EventBridge event:
batch.execution.threshold_exceeded
Toleration Policies:
STRICT— Fail immediately on first chunk error (default for critical data)LENIENT— Continue processing remaining chunks, collect all errors (default for imports)
Error File Generation
For import jobs, Foundation Service generates an error file in the same format as the input file with an additional _importErrors column:
Original File (catalog.csv):
productId,name,status,categoryCode
PRD-001,T-Shirt,ACTIVE,CAT-TOPS
PRD-002,,ACTIVE,CAT-TOPS
PRD-003,Jeans,ACTIVE,CAT-NONE
Error File (catalog_errors.csv):
productId,name,status,categoryCode,_importErrors
PRD-002,,ACTIVE,CAT-TOPS,"name: Required field is missing"
PRD-003,Jeans,ACTIVE,CAT-NONE,"categoryCode: Category 'CAT-NONE' does not exist"
Error File Location:
- S3 path:
s3://bucket/results/{runRequestId}/catalog_errors.csv - Available via:
GET /v1/batches/.../history/{runRequestId}→result.errorFileUrl - Presigned URL: 7-day expiry (configurable)
FAQs
Q: What is the difference between a Batch, Job, and Schedule?
Batch is a logical grouping (e.g., “PIM Import Batch”). Job is an executable unit within a batch (e.g., “Product Full Refresh”). Schedule is a trigger mechanism for the job (cron, rate, or on-demand). One batch can have multiple jobs; one job can have multiple schedules.
Q: How does ONDEMAND execution work without EventBridge?
When
status: "ONDEMAND"is specified during schedule creation, Foundation Service creates the schedule record but skips EventBridge rule creation. Instead, it immediately callsexecuteBatchJob()and returns therunRequestId. This allows UI-triggered imports/exports without waiting for the next scheduled run.
Q: What happens if a job fails midway through chunk processing?
When
tolerationPolicy: "LENIENT", remaining chunks continue processing and an error file is generated with failed rows. WhentolerationPolicy: "STRICT", the job stops immediately on first chunk failure with statusFAILED.
Q: How does retry work for failed executions?
The retry policy (configured at batch or job level) determines retry behavior. After a job fails, Foundation Service checks the policy: if
attemptNumber < maxRetries, it publishes abatch.execution.retry_requestedevent, waits forretryDelayseconds (exponential backoff if configured), then re-invokes the Step Function withattemptNumberincremented.
Q: Can I import categories and products in the same feed?
Yes, using PIM Multi-Sheet Import. Categories must be in one sheet, products in another. Step Function processes sheets in order: categories first (with sequential MaxConcurrency=1 for hierarchy), then products (with MaxConcurrency=20). This ensures parent categories exist before child products reference them.
Q: How does Foundation Service handle multi-tenant isolation?
Every API requires
instanceIdin the query or body. MongoDB queries filter byinstanceId. S3 file paths includeinstanceIdin the prefix (s3://bucket/imports/{instanceId}/{runRequestId}/...). EventBridge events includeinstanceIdin the payload. Job Initiator Lambda validatesinstanceIdbefore starting Step Functions.
Q: What is the maximum file size for imports?
The validation step checks file size. Default limits:
- CSV/Excel imports: 100MB (configurable via batch
maxFileSizeproperty)- Multi-sheet imports: 50MB per sheet (total 200MB for 4 sheets)
- Larger files require chunked upload with multipart S3 API (not currently supported)
Q: How long are execution history records retained?
Batch history records have a 90-day TTL (Time To Live). MongoDB automatically deletes records older than 90 days. This ensures compliance with data retention policies and prevents unbounded database growth.
Q: Can I cancel a running execution?
Yes, via
POST /v1/batches/:batchId/jobs/:jobId/history/:runRequestId/stop. Foundation Service calls AWS Step FunctionsStopExecutionAPI, which terminates the execution. Status updates toSTOPPED. Partial results (already processed chunks) remain in S3.
Glossary
| Term | Definition |
|---|---|
Batch |
Logical grouping of related jobs (e.g., “PIM Import Batch”). Configuration includes execution type, parallel execution flag, max runtime. |
BatchJob |
Executable unit within a batch (e.g., “Product Full Refresh”). Contains job parameters, retry policy, error threshold. |
BatchSchedule |
Trigger mechanism for job execution. Types: SCHEDULED (cron/rate with EventBridge rule) or ONDEMAND (immediate execution). |
runRequestId |
Unique UUID identifying a single execution instance. Used to track status, retrieve results, and correlate logs. |
jobType |
Feed type identifier (e.g., CATALOG_IMPORT, INVENTORY_EXPORT, GDPR_EXPORT). Determines which Step Function to invoke. |
instanceId |
Tenant identifier. All queries, S3 paths, and EventBridge events are scoped to instanceId for multi-tenant isolation. |
jobParams |
Flat key-value object on BatchJob containing execution parameters (catalogId, fileUrl, chunkSize, etc.). Schedule parameters override job parameters. |
eventBridgeRuleName |
Auto-generated name for EventBridge schedule rule. Format: {stage}-fnd-{batchId}-{jobId}-{scheduleId}. |
Distributed Map |
AWS Step Functions feature for high-throughput parallel processing. Reads S3 manifest file, spawns up to 10,000 concurrent executions. |
Chunk |
Subset of input file rows (default: 100 rows). Each chunk processed independently by Lambda function. Failed chunks retry without reprocessing successful chunks. |
s3KeyPrefix |
S3 path prefix for job execution files. Format: imports/{runRequestId} or exports/{runRequestId} or gdpr-temp/{runRequestId}. |
errorThreshold |
Percentage of chunks allowed to fail before overall job fails. Example: 10% threshold = 10 failed chunks out of 100 total. |
tolerationPolicy |
Error handling strategy. STRICT = fail immediately on first error; LENIENT = continue processing, collect all errors. |
retryPolicy |
Configuration for automatic retry on failure. Includes maxRetries, retryDelay, backoffMultiplier, retryStrategy. |
ONDEMAND |
Schedule status for immediate one-time execution. No EventBridge rule created; executeBatchJob() called directly. |
INITIATED |
Initial execution status when job record created in MongoDB. Transitions to RUNNING when Step Function starts. |
callbackBaseUrl |
Foundation Service API base URL (e.g., https://api.equinox.shop/foundationservices). Lambda functions call back to update status and progress. |
Job Initiator Lambda |
Lambda function subscribed to batch.job.initiated EventBridge events. Starts appropriate Step Function based on jobType. |
entityExtractionOrder |
(Export only) Array of entity types defining extraction order. Example: ["products", "categories", "skus", "prices"]. |
exportConfig |
(Export only) Configuration object for export behavior. Includes sheets array, locale, onlyAttributes, filters, etc. |
manifest.jsonl |
S3 file listing all chunk S3 keys (JSONL format, one key per line). Used by Distributed Map ItemReader. |
Common Execution Sequence Diagram
Framework: Fastify + TypeScript + AWS Step Functions
sequenceDiagram
autonumber
participant User
participant FoundationAPI
participant MongoDB
participant EventBridge
participant JobInitiator
participant StepFunction
participant Lambda
participant S3
User->>FoundationAPI: POST /v1/batches/:batchId/jobs/:jobId/schedules<br/>{status: "ONDEMAND", parameters: {...}}
FoundationAPI->>MongoDB: Save BatchSchedule record
FoundationAPI->>FoundationAPI: Detect ONDEMAND → executeBatchJob()
FoundationAPI->>MongoDB: Save batchHistory {status: "INITIATED"}
FoundationAPI->>EventBridge: Publish batch.job.initiated<br/>{runRequestId, jobConfig, s3KeyPrefix}
FoundationAPI-->>User: 202 Accepted<br/>{runRequestId, status: "INITIATED"}
EventBridge->>JobInitiator: EventBridge Rule triggers<br/>Job Initiator Lambda
JobInitiator->>StepFunction: StartExecution(stateMachineArn, input)
StepFunction->>Lambda: VALIDATE action
Lambda->>S3: Read first 8KB (header check)
Lambda-->>StepFunction: {valid: true}
StepFunction->>Lambda: PARSE + CHUNK action
Lambda->>S3: Stream file, write chunks/
Lambda->>S3: Write manifest.jsonl
Lambda-->>StepFunction: {totalChunks: 50, manifestKey}
StepFunction->>Lambda: DISTRIBUTED MAP (20 concurrent)<br/>ProcessChunk action × 50
loop For each chunk
Lambda->>S3: Read chunk file
Lambda->>Lambda: Validate rows, transform to domain
Lambda->>MongoDB: bulkWrite (insert/update)
Lambda->>S3: Write result file
end
Lambda-->>StepFunction: All chunks complete
StepFunction->>Lambda: AGGREGATE action
Lambda->>S3: Read all result files
Lambda->>S3: Generate error file (if failures)
Lambda-->>StepFunction: {errorFileUrl, totalSuccess, totalFailed}
StepFunction->>Lambda: FINALIZE action
Lambda->>MongoDB: Update batchHistory<br/>{status: "COMPLETED", result, duration}
Lambda->>EventBridge: Publish batch.execution.completed
Lambda-->>StepFunction: Success
StepFunction-->>JobInitiator: Execution complete
User->>FoundationAPI: GET /v1/batches/.../history/:runRequestId
FoundationAPI->>MongoDB: Query batchHistory
MongoDB-->>FoundationAPI: {status: "COMPLETED", result: {...}}
FoundationAPI-->>User: 200 OK<br/>{status, result, errorFileUrl}
MongoDB Collections
Database:
foundationdb_<STAGE>(e.g.,foundationdb_dev).
Collection: batches
Repository: src/repository/batch.repository.ts
| Field | Type | Description |
|---|---|---|
_id |
ObjectId | Auto-generated MongoDB ID |
batchId |
string | Unique batch identifier (kebab-case) |
instanceId |
string | Tenant identifier (multi-tenancy) |
businessId |
string | Business identifier (deprecated, use instanceId) |
name |
string | Human-readable batch name |
description |
string | Batch purpose and usage notes |
serviceType |
string | Service domain (e.g., pim-import, inventory-export) |
executionType |
string | LAMBDA, STEP_FUNCTION, SPRING_BATCH, GLUE |
jobEndpoint |
string | Lambda ARN or API endpoint for execution |
allowParallelExecution |
boolean | false prevents concurrent executions for same job |
maxRuntime |
number | Maximum execution time in seconds |
executionCluster |
string | Execution environment identifier |
jobInformation |
object | Additional job metadata (legacy, use jobParams) |
metadata |
object | Custom key-value pairs for batch metadata |
isDeleted |
boolean | Soft-delete flag |
deletedAt |
Date | Soft-delete timestamp |
createdAt |
Date | Creation timestamp |
updatedAt |
Date | Last update timestamp |
createdBy |
string | User identifier |
updatedBy |
string | User identifier |
Indexes:
{ batchId: 1, instanceId: 1 }— Unique compound index{ instanceId: 1, isDeleted: 1 }— List query optimization
Collection: batch_jobs
Repository: src/repository/batchJob.repository.ts
| Field | Type | Description |
|---|---|---|
_id |
ObjectId | Auto-generated MongoDB ID |
batchId |
string | Parent batch identifier |
jobId |
string | Unique job identifier within batch |
instanceId |
string | Tenant identifier |
businessId |
string | Business identifier (deprecated) |
name |
string | Human-readable job name |
description |
string | Job purpose and usage notes |
status |
string | ACTIVE (can execute) or INACTIVE (disabled) |
jobParams |
object | Flat key-value object with execution parameters Required keys: jobType, instanceIdOptional keys: catalogId, fileUrl, chunkSize, etc. |
retryPolicy |
object | { maxRetries, retryDelay, backoffMultiplier, retryStrategy } |
errorThreshold |
number | Percentage of failures allowed (0-100) |
tolerationPolicy |
string | STRICT (fail fast) or LENIENT (collect errors) |
metadata |
object | Custom key-value pairs |
isDeleted |
boolean | Soft-delete flag (cascades from parent batch) |
deletedAt |
Date | Soft-delete timestamp |
createdAt |
Date | Creation timestamp |
updatedAt |
Date | Last update timestamp |
createdBy |
string | User identifier |
updatedBy |
string | User identifier |
Indexes:
{ batchId: 1, jobId: 1, instanceId: 1 }— Unique compound index{ instanceId: 1, status: 1, isDeleted: 1 }— List query optimization
Collection: batch_schedules
Repository: src/repository/batchSchedule.repository.ts
| Field | Type | Description |
|---|---|---|
_id |
ObjectId | Auto-generated MongoDB ID |
batchId |
string | Parent batch identifier |
jobId |
string | Parent job identifier |
scheduleId |
string | Unique schedule identifier within job |
instanceId |
string | Tenant identifier |
businessId |
string | Business identifier (deprecated) |
name |
string | Human-readable schedule name |
description |
string | Schedule purpose |
status |
string | SCHEDULED (cron/rate) or ONDEMAND (manual) |
state |
string | ACTIVE, PAUSED, STOPPED (lifecycle state) |
repeatInterval |
string | EventBridge cron/rate expression (null for ONDEMAND) |
startDate |
Date | Schedule validity start (null = immediate) |
endDate |
Date | Schedule validity end (null = no expiry) |
eventBridgeRuleName |
string | Auto-generated EventBridge rule name |
lastRunTime |
Date | Most recent execution timestamp |
nextRunTime |
Date | Next scheduled execution timestamp |
parameters |
object | Schedule-specific parameters (override jobParams) |
metadata |
object | Custom key-value pairs |
isDeleted |
boolean | Soft-delete flag (cascades from parent job) |
deletedAt |
Date | Soft-delete timestamp |
createdAt |
Date | Creation timestamp |
updatedAt |
Date | Last update timestamp |
createdBy |
string | User identifier |
updatedBy |
string | User identifier |
Indexes:
{ batchId: 1, jobId: 1, scheduleId: 1, instanceId: 1 }— Unique compound index{ instanceId: 1, state: 1, isDeleted: 1 }— List query optimization
Collection: batch_history
Repository: src/repository/batchHistory.repository.ts
| Field | Type | Description |
|---|---|---|
_id |
ObjectId | Auto-generated MongoDB ID |
runRequestId |
string | Unique execution identifier (UUID) |
batchId |
string | Parent batch identifier |
jobId |
string | Parent job identifier |
scheduleId |
string | Parent schedule identifier (null for on-demand) |
instanceId |
string | Tenant identifier |
businessId |
string | Business identifier (deprecated) |
status |
string | INITIATED → PENDING → RUNNING → COMPLETED/FAILED/STOPPED |
jobConfig |
object | Complete job configuration (merged jobParams + schedule parameters) |
totalChunks |
number | Total number of chunks (set after PARSE) |
processedChunks |
number | Successfully processed chunks |
failedChunks |
number | Failed chunks |
progress |
number | Percentage complete (0-100) |
startTime |
Date | Execution start timestamp |
endTime |
Date | Execution end timestamp |
duration |
number | Execution duration in seconds |
result |
object | Execution result (success output, file URLs, statistics) |
errorMessage |
string | Failure details (validation errors, exceptions) |
payload |
object | Original execution request payload (deprecated) |
executionType |
string | event-driven (Step Functions) or direct (Lambda) |
triggeredBy |
string | User identifier who triggered execution |
attemptNumber |
number | Retry attempt number (1 = first attempt) |
ttl |
Date | Time to live (90 days from endTime, auto-delete) |
createdAt |
Date | Creation timestamp |
updatedAt |
Date | Last update timestamp |
Indexes:
{ runRequestId: 1 }— Unique index for lookup{ batchId: 1, jobId: 1, status: 1 }— List query optimization{ instanceId: 1, status: 1, startTime: -1 }— History pagination{ ttl: 1 }— TTL index for automatic cleanup (expireAfterSeconds: 0)
Collection: batch_uploads
Repository: src/repository/batchUpload.repository.ts
| Field | Type | Description |
|---|---|---|
_id |
ObjectId | Auto-generated MongoDB ID |
uploadId |
string | Unique upload identifier (UUID) |
instanceId |
string | Tenant identifier |
businessId |
string | Business identifier (deprecated) |
fileName |
string | Original file name |
fileSize |
number | File size in bytes |
fileType |
string | MIME type (e.g., text/csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet) |
s3Key |
string | S3 object key (path) |
s3Bucket |
string | S3 bucket name |
presignedUrl |
string | Presigned PUT URL for upload |
urlExpiry |
Date | Presigned URL expiration timestamp (15 minutes) |
uploadStatus |
string | PENDING, UPLOADING, COMPLETED, FAILED |
metadata |
object | Custom key-value pairs (batchId, jobId, etc.) |
createdAt |
Date | Creation timestamp |
updatedAt |
Date | Last update timestamp |
createdBy |
string | User identifier |
Indexes:
{ uploadId: 1 }— Unique index for lookup{ instanceId: 1, uploadStatus: 1, createdAt: -1 }— List query optimization
Configuration & Properties
Environment Variables
| Variable | Type | Default | Description |
|---|---|---|---|
MONGODB_URI |
string | Required | MongoDB connection string (shared across services) |
MONGODB_DATABASE |
string | foundationdb_{STAGE} |
Database name |
STAGE |
string | development |
Environment stage (dev, staging, prod) |
EVENT_BUS_NAME |
string | Required | AWS EventBridge bus name |
ENABLE_EVENT_BRIDGE |
boolean | true |
Enable EventBridge event publishing |
S3_BUCKET_NAME |
string | Required | S3 bucket for batch file uploads and processing |
BATCH_UPLOAD_BUCKET |
string | Same as S3_BUCKET_NAME |
Legacy alias |
FOUNDATION_LAMBDA_ARN |
string | Required | Foundation Lambda ARN for Step Functions |
JOB_INITIATOR_LAMBDA_ARN |
string | Required | Job Initiator Lambda ARN for EventBridge target |
STEP_FUNCTION_CATALOG_IMPORT_ARN |
string | Required | Catalog Import Step Function ARN |
STEP_FUNCTION_INVENTORY_EXPORT_ARN |
string | Required | Inventory Export Step Function ARN |
STEP_FUNCTION_GDPR_EXPORT_ARN |
string | Required | GDPR Export Step Function ARN |
REGISTERED_PROCESSORS |
string | CSV list | Comma-separated list of registered processor aliases (e.g., pim-product-import,inventory-sync) |
SKIP_LAMBDA_INVOCATION |
boolean | false |
Skip Lambda invocation (dev/test only) |
CALLBACK_BASE_URL |
string | Auto-detect | Foundation Service API base URL for Lambda callbacks |
GDPR_EXPORT_PRESIGNED_URL_EXPIRY |
number | 86400 |
GDPR export presigned URL expiry in seconds (90 days = 7776000) |
Batch Configuration Templates
Foundation Service provides default batch configurations for common feed types. Seed data (Webbox migrations) pre-populates these templates.
Example: PIM Catalog Import Batch
{
"batchId": "pim-catalog-import",
"name": "PIM Catalog Import",
"serviceType": "pim-import",
"executionType": "STEP_FUNCTION",
"allowParallelExecution": false,
"maxRuntime": 3600,
"jobEndpoint": "${FOUNDATION_LAMBDA_ARN}",
"jobRequiredFields": ["jobType", "instanceId", "catalogId", "fileUrl"]
}
Example: Inventory Export Batch
{
"batchId": "inventory-export",
"name": "Inventory Export",
"serviceType": "inventory-export",
"executionType": "STEP_FUNCTION",
"allowParallelExecution": true,
"maxRuntime": 3600,
"jobEndpoint": "${FOUNDATION_LAMBDA_ARN}",
"jobRequiredFields": ["jobType", "instanceId"]
}
END OF DOCUMENT
Document Revision History
- v1.0 (2026-08-07): Initial comprehensive feed services documentation
- Based on eq-foundation-service v9.0 codebase
- Modeled after EQ_USER_SERVICE_DOCUMENTATION 4.md structure
Revision History
2026-08-12 | JP – Created the page and added the content.