Bulk API Operations
Synchronous vs Asynchronous
Synchronous: Client -> API -> Process -> Response (blocks)
Asynchronous: Client -> API -> Queue -> Response (immediate)
Bulk API Endpoint
POST /rest/async/bulk
Content-Type: application/json
[
{
"httpMethod": "POST",
"requestUri": "/rest/V1/products",
"body": {"product": {"sku": "SKU1", "name": "Product 1"}}
},
{
"httpMethod": "POST",
"requestUri": "/rest/V1/products",
"body": {"product": {"sku": "SKU2", "name": "Product 2"}}
}
]
Response
{
"bulk_id": "3a1b2c3d-4e5f-6789-abcd-ef0123456789",
"status_link": "/rest/V1/bulk/3a1b2c3d-4e5f-6789-abcd-ef0123456789/status"
}
Check Bulk Status
GET /rest/V1/bulk/{bulk_id}/status
{
"bulk_id": "3a1b2c3d-4e5f-6789-abcd-ef0123456789",
"status": "complete",
"result": {
"success_count": 2,
"error_count": 0
}
}
Async Indexation
Enable Async Indexing
// app/etc/env.php
return [
'indexer' => [
'async_indexing' => true
]
];
How Async Indexing Works
- Product save triggers index update message
- Message published to queue
- Consumer processes batch reindex
- Index updated in background
// Automatic with async_indexing enabled
$this->product->save(); // Triggers async index update
// Response returned immediately
Manual Async Reindex
# Queue reindex operations
php bin/magento indexer:set-mode realtime catalog_product_flat
# Process queued reindex
php bin/magento queue:consumers:start index.update products --max-messages=1000
Benefits
- Faster page loads (no index wait)
- Better API response times
- Reduced database locks
- Improved scalability
Async Operation Patterns
Fire and Forget
namespace Vendor\Module\Service;
use Magento\Framework\MessageQueue\PublisherInterface;
class OrderNotifier
{
public function __construct(
private PublisherInterface $publisher
) {}
public function notify(int $orderId): void
{
$this->publisher->publish(
'vendor.order.notify',
json_encode(['order_id' => $orderId])
);
// Return immediately, process in background
}
}
Request-Reply Pattern
// Publish request
$requestId = $this->uuid->generate();
$this->publisher->publish(
'vendor.export.request',
json_encode(['request_id' => $requestId, 'data' => $data])
);
// Wait for reply (poll)
while (!$this->isComplete($requestId)) {
sleep(1);
}
return $this->getResult($requestId);
Saga Pattern (Multi-Step)
// Step 1: Validate
$this->publisher->publish('order.validate', $data);
// Consumer triggers Step 2 on success
// Step 2: Process payment
$this->publisher->publish('order.payment', $data);
// Consumer triggers Step 3 on success
// Step 3: Ship
$this->publisher->publish('order.ship', $data);
Throttling
class ThrottledPublisher
{
private int $count = 0;
private int $limit = 100;
public function publish(string $topic, string $body): void
{
$this->publisher->publish($topic, $body);
$this->count++;
if ($this->count >= $this->limit) {
sleep(1); // Throttle
$this->count = 0;
}
}
}
Performance Optimization
Async vs Sync Decision Matrix
| Scenario | Approach | Reason |
|---|---|---|
| User-facing API | Async | Fast response time |
| Bulk import | Async | No timeout, parallel processing |
| Email sending | Async | Non-blocking |
| Inventory update | Async | Reduce DB locks |
| Real-time data | Sync | Immediate consistency needed |
Batch Size Optimization
// Too small: overhead per message
$batchSize = 1;
// Too large: memory issues
$batchSize = 100000;
// Optimal: balance throughput and memory
$batchSize = 500;
Performance Metrics
-- Queue depth monitoring
SELECT queue_name, COUNT(*) as pending
FROM queue_message
WHERE status = 'new'
GROUP BY queue_name
ORDER BY pending DESC;
-- Processing rate
SELECT
DATE(created_at) as day,
COUNT(*) as messages_processed
FROM queue_message
WHERE status = 'complete'
GROUP BY DATE(created_at);
Monitoring Dashboard
-- Consumer performance
SELECT
consumer_name,
COUNT(*) as processed,
AVG(TIMESTAMPDIFF(SECOND, started_at, finished_at)) as avg_time
FROM queue_consumer
WHERE finished_at > DATE_SUB(NOW(), INTERVAL 24 HOUR)
GROUP BY consumer_name;
Practice Problems
Design an async operation for sending order confirmation emails with retry logic and monitoring.
Quiz
1. What is the bulk API endpoint?
2. How do you enable async indexing?
3. What pattern is best for multi-step async workflows?
4. What should you monitor for async operations?
Flashcards
Question
What is the bulk API endpoint?
Click to reveal answer
Answer
/rest/async/bulk for asynchronous batch operations
Question
How to enable async indexing?
Click to reveal answer
Answer
Set async_indexing: true in env.php under indexer
Question
What is fire-and-forget?
Click to reveal answer
Answer
Publish message and return immediately without waiting for completion
Question
What is the saga pattern?
Click to reveal answer
Answer
Multi-step workflow where each step triggers the next asynchronously
Question
What metrics to monitor?
Click to reveal answer
Answer
Queue depth, processing rate, error rate, consumer performance
Revision Notes
Key Takeaways
- 1. Bulk API at /rest/async/bulk for batch async operations
- 2. Async indexing enabled via env.php for background reindex
- 3. Fire-and-forget, request-reply, and saga are common async patterns
- 4. Monitor queue depth, processing rate, and error rate
- 5. Batch size affects throughput and memory usage
- 6. Async operations improve API response times and scalability
Interview Tips
- • Explain the difference between sync and async operations
- • Describe the saga pattern for multi-step workflows
- • Discuss when to use async vs sync approaches
- • Know how to monitor async operation health
Cheat Sheet
Async Operations Cheat Sheet
Bulk API:
POST /rest/async/bulk
Async indexing:
'async_indexing' => true in env.php
Patterns:
- Fire-and-forget: immediate return
- Request-reply: poll for result
- Saga: multi-step chain
Monitor:
SELECT queue_name, COUNT(*) FROM queue_message
WHERE status = 'new' GROUP BY queue_name;
Optimal batch size: 500 (balance throughput/memory)