0
# Notifications
1
2
This document covers the MinIO notification system, including bucket notification configuration, event types, polling mechanisms, and notification target setup for real-time event processing.
3
4
## Notification Overview
5
6
MinIO supports bucket notifications that trigger when specific events occur on objects. Notifications can be sent to various targets like SNS topics, SQS queues, or Lambda functions, and can also be consumed via polling.
7
8
## Event Types
9
10
### Standard S3 Events
11
12
```javascript { .api }
13
// Import event type constants
14
import {
15
ObjectCreatedAll,
16
ObjectCreatedPut,
17
ObjectCreatedPost,
18
ObjectCreatedCopy,
19
ObjectCreatedCompleteMultipartUpload,
20
ObjectRemovedAll,
21
ObjectRemovedDelete,
22
ObjectRemovedDeleteMarkerCreated,
23
ObjectReducedRedundancyLostObject
24
} from 'minio'
25
26
// Event type values
27
ObjectCreatedAll = 's3:ObjectCreated:*'
28
ObjectCreatedPut = 's3:ObjectCreated:Put'
29
ObjectCreatedPost = 's3:ObjectCreated:Post'
30
ObjectCreatedCopy = 's3:ObjectCreated:Copy'
31
ObjectCreatedCompleteMultipartUpload = 's3:ObjectCreated:CompleteMultipartUpload'
32
ObjectRemovedAll = 's3:ObjectRemoved:*'
33
ObjectRemovedDelete = 's3:ObjectRemoved:Delete'
34
ObjectRemovedDeleteMarkerCreated = 's3:ObjectRemoved:DeleteMarkerCreated'
35
ObjectReducedRedundancyLostObject = 's3:ReducedRedundancyLostObject'
36
```
37
38
#### Event Type Usage
39
40
```javascript { .api }
41
// Listen for all object creation events
42
const events = [ObjectCreatedAll]
43
44
// Listen for specific events
45
const specificEvents = [
46
ObjectCreatedPut,
47
ObjectCreatedPost,
48
ObjectRemovedDelete
49
]
50
51
// Listen for all events (creation and deletion)
52
const allEvents = [ObjectCreatedAll, ObjectRemovedAll]
53
```
54
55
## Notification Configuration
56
57
### NotificationConfig Class
58
59
```typescript { .api }
60
import { NotificationConfig } from 'minio'
61
62
class NotificationConfig {
63
// Methods
64
add(target: TargetConfig): void // Add notification target
65
}
66
```
67
68
### Base TargetConfig Class
69
70
```typescript { .api }
71
abstract class TargetConfig {
72
// Methods
73
setId(id: unknown): void // Set target identifier
74
addEvent(newevent: Event): void // Add event type to listen for
75
addFilterSuffix(suffix: string): void // Add object suffix filter
76
addFilterPrefix(prefix: string): void // Add object prefix filter
77
}
78
```
79
80
### Target Types
81
82
#### TopicConfig (SNS)
83
84
```typescript { .api }
85
import { TopicConfig } from 'minio'
86
87
class TopicConfig extends TargetConfig {
88
constructor(arn: string) // SNS topic ARN
89
}
90
```
91
92
#### QueueConfig (SQS)
93
94
```typescript { .api }
95
import { QueueConfig } from 'minio'
96
97
class QueueConfig extends TargetConfig {
98
constructor(arn: string) // SQS queue ARN
99
}
100
```
101
102
#### CloudFunctionConfig (Lambda)
103
104
```typescript { .api }
105
import { CloudFunctionConfig } from 'minio'
106
107
class CloudFunctionConfig extends TargetConfig {
108
constructor(arn: string) // Lambda function ARN
109
}
110
```
111
112
### Set Bucket Notification
113
114
```javascript { .api }
115
client.setBucketNotification(bucketName, config, callback)
116
117
// Parameters
118
bucketName: string // Bucket name
119
config: object // Notification configuration object
120
callback: function // Callback function (err) => void
121
122
// Note: This method uses callback pattern only
123
```
124
125
### Get Bucket Notification
126
127
```javascript { .api }
128
client.getBucketNotification(bucketName, callback)
129
130
// Parameters
131
bucketName: string // Bucket name
132
callback: function // Callback function (err, config) => void
133
```
134
135
### Remove All Notifications
136
137
```javascript { .api }
138
client.removeAllBucketNotification(bucketName, callback)
139
140
// Parameters
141
bucketName: string // Bucket name
142
callback: function // Callback function (err) => void
143
```
144
145
### Notification Configuration Examples
146
147
```javascript { .api }
148
import {
149
NotificationConfig,
150
TopicConfig,
151
QueueConfig,
152
CloudFunctionConfig,
153
ObjectCreatedAll,
154
ObjectRemovedAll
155
} from 'minio'
156
157
// Configure SNS topic notification
158
const topicConfig = new TopicConfig('arn:aws:sns:us-east-1:123456789012:my-topic')
159
topicConfig.addEvent(ObjectCreatedAll)
160
topicConfig.addFilterPrefix('photos/')
161
topicConfig.addFilterSuffix('.jpg')
162
163
const notificationConfig = new NotificationConfig()
164
notificationConfig.add(topicConfig)
165
166
// Set bucket notification
167
client.setBucketNotification('my-bucket', notificationConfig, (err) => {
168
if (err) throw err
169
console.log('Notification configured successfully')
170
})
171
172
// Configure multiple notification targets
173
const snsConfig = new TopicConfig('arn:aws:sns:us-east-1:123456789012:uploads-topic')
174
snsConfig.addEvent(ObjectCreatedPut)
175
snsConfig.addEvent(ObjectCreatedPost)
176
snsConfig.addFilterPrefix('uploads/')
177
178
const sqsConfig = new QueueConfig('arn:aws:sqs:us-east-1:123456789012:deletions-queue')
179
sqsConfig.addEvent(ObjectRemovedDelete)
180
181
const lambdaConfig = new CloudFunctionConfig('arn:aws:lambda:us-east-1:123456789012:function:processImage')
182
lambdaConfig.addEvent(ObjectCreatedAll)
183
lambdaConfig.addFilterSuffix('.jpg')
184
lambdaConfig.addFilterSuffix('.png')
185
186
const multiTargetConfig = new NotificationConfig()
187
multiTargetConfig.add(snsConfig)
188
multiTargetConfig.add(sqsConfig)
189
multiTargetConfig.add(lambdaConfig)
190
191
client.setBucketNotification('multi-notifications', multiTargetConfig, (err) => {
192
if (err) throw err
193
console.log('Multiple notifications configured')
194
})
195
196
// Get current notification configuration
197
client.getBucketNotification('my-bucket', (err, config) => {
198
if (err) throw err
199
console.log('Current notification config:', JSON.stringify(config, null, 2))
200
})
201
202
// Remove all notifications
203
client.removeAllBucketNotification('my-bucket', (err) => {
204
if (err) throw err
205
console.log('All notifications removed')
206
})
207
```
208
209
## Notification Polling
210
211
### NotificationPoller Class
212
213
```typescript { .api }
214
import { NotificationPoller } from 'minio'
215
216
class NotificationPoller extends EventEmitter {
217
constructor(
218
client: TypedClient, // MinIO client instance
219
bucketName: string, // Bucket to monitor
220
prefix: string, // Object prefix filter
221
suffix: string, // Object suffix filter
222
events: NotificationEvent[] // Events to listen for
223
)
224
225
// Methods
226
start(): void // Start polling for notifications
227
stop(): void // Stop polling for notifications
228
229
// Events (extends EventEmitter)
230
on('notification', listener: (notification) => void): this
231
on('error', listener: (error) => void): this
232
}
233
```
234
235
### Listen for Notifications
236
237
```javascript { .api }
238
const notificationStream = client.listenBucketNotification(bucketName, prefix, suffix, events)
239
240
// Parameters
241
bucketName: string // Bucket name
242
prefix: string // Object prefix filter (empty string for all)
243
suffix: string // Object suffix filter (empty string for all)
244
events: string[] // Array of event types to listen for
245
246
// Returns: EventEmitter
247
```
248
249
### Polling Examples
250
251
```javascript { .api }
252
// Listen for all object creation events
253
const notificationStream = client.listenBucketNotification(
254
'my-bucket',
255
'', // No prefix filter (all objects)
256
'', // No suffix filter (all objects)
257
[ObjectCreatedAll]
258
)
259
260
notificationStream.on('notification', (record) => {
261
console.log('New object created:', record.s3.object.key)
262
console.log('Event name:', record.eventName)
263
console.log('Bucket:', record.s3.bucket.name)
264
console.log('Object size:', record.s3.object.size)
265
})
266
267
notificationStream.on('error', (err) => {
268
console.error('Notification error:', err)
269
})
270
271
// Listen for photo uploads only
272
const photoNotifications = client.listenBucketNotification(
273
'photos',
274
'uploads/', // Only objects with 'uploads/' prefix
275
'.jpg', // Only .jpg files
276
[ObjectCreatedPut, ObjectCreatedPost]
277
)
278
279
photoNotifications.on('notification', (record) => {
280
const objectKey = record.s3.object.key
281
const bucketName = record.s3.bucket.name
282
283
console.log(`New photo uploaded: ${objectKey}`)
284
285
// Process the uploaded photo
286
processNewPhoto(bucketName, objectKey)
287
})
288
289
// Listen for deletion events
290
const deletionNotifications = client.listenBucketNotification(
291
'documents',
292
'important/', // Monitor important documents
293
'', // All file types
294
[ObjectRemovedDelete, ObjectRemovedDeleteMarkerCreated]
295
)
296
297
deletionNotifications.on('notification', (record) => {
298
console.log('Document deleted:', record.s3.object.key)
299
300
// Log deletion for audit
301
auditLog.record({
302
event: 'document_deleted',
303
object: record.s3.object.key,
304
timestamp: record.eventTime,
305
source: record.eventSource
306
})
307
})
308
309
// Advanced notification handling with filtering
310
async function processNewPhoto(bucketName, objectKey) {
311
try {
312
// Get object metadata
313
const stat = await client.statObject(bucketName, objectKey)
314
315
// Process only if file is reasonable size
316
if (stat.size > 10 * 1024 * 1024) { // > 10MB
317
console.log('Photo too large, skipping processing')
318
return
319
}
320
321
// Download and process photo
322
const photoStream = await client.getObject(bucketName, objectKey)
323
// ... image processing logic
324
325
} catch (error) {
326
console.error('Failed to process photo:', error)
327
}
328
}
329
```
330
331
### Advanced Polling Patterns
332
333
```javascript { .api }
334
// Multiple concurrent listeners
335
function setupMultipleListeners(bucketName) {
336
// Listen for uploads
337
const uploadListener = client.listenBucketNotification(
338
bucketName, '', '', [ObjectCreatedAll]
339
)
340
341
// Listen for deletions
342
const deleteListener = client.listenBucketNotification(
343
bucketName, '', '', [ObjectRemovedAll]
344
)
345
346
// Separate handlers for different event types
347
uploadListener.on('notification', handleUpload)
348
deleteListener.on('notification', handleDeletion)
349
350
// Common error handling
351
[uploadListener, deleteListener].forEach(listener => {
352
listener.on('error', (err) => {
353
console.error('Notification listener error:', err)
354
355
// Implement retry logic
356
setTimeout(() => {
357
console.log('Restarting notification listener...')
358
// Restart listeners if needed
359
}, 5000)
360
})
361
})
362
363
return { uploadListener, deleteListener }
364
}
365
366
function handleUpload(record) {
367
const { eventName, s3: { bucket, object } } = record
368
369
console.log(`Upload event: ${eventName}`)
370
console.log(`Bucket: ${bucket.name}, Object: ${object.key}`)
371
372
// Route to appropriate handler based on object type
373
if (object.key.endsWith('.jpg') || object.key.endsWith('.png')) {
374
processImage(bucket.name, object.key)
375
} else if (object.key.endsWith('.pdf')) {
376
processDocument(bucket.name, object.key)
377
} else if (object.key.endsWith('.csv')) {
378
processData(bucket.name, object.key)
379
}
380
}
381
382
function handleDeletion(record) {
383
const { eventName, s3: { bucket, object } } = record
384
385
console.log(`Deletion event: ${eventName}`)
386
387
// Clean up related resources
388
cleanupRelatedData(bucket.name, object.key)
389
390
// Update search index
391
updateSearchIndex('remove', bucket.name, object.key)
392
}
393
394
// Graceful shutdown
395
process.on('SIGINT', () => {
396
console.log('Shutting down notification listeners...')
397
398
// Stop all listeners
399
Object.values(listeners).forEach(listener => {
400
if (listener && listener.stop) {
401
listener.stop()
402
}
403
})
404
405
process.exit(0)
406
})
407
```
408
409
## ARN Building Utility
410
411
```javascript { .api }
412
import { buildARN } from 'minio'
413
414
const arn = buildARN(partition, service, region, accountId, resource)
415
416
// Parameters
417
partition: string // AWS partition ('aws', 'aws-cn', 'aws-us-gov')
418
service: string // AWS service ('sns', 'sqs', 'lambda')
419
region: string // AWS region ('us-east-1', 'eu-west-1', etc.)
420
accountId: string // AWS account ID
421
resource: string // Resource identifier
422
423
// Returns: string - Complete ARN
424
```
425
426
### ARN Examples
427
428
```javascript { .api }
429
// Build SNS topic ARN
430
const snsArn = buildARN('aws', 'sns', 'us-east-1', '123456789012', 'my-topic')
431
console.log(snsArn) // arn:aws:sns:us-east-1:123456789012:my-topic
432
433
// Build SQS queue ARN
434
const sqsArn = buildARN('aws', 'sqs', 'us-west-2', '123456789012', 'my-queue')
435
console.log(sqsArn) // arn:aws:sqs:us-west-2:123456789012:my-queue
436
437
// Build Lambda function ARN
438
const lambdaArn = buildARN('aws', 'lambda', 'eu-west-1', '123456789012', 'function:myFunction')
439
console.log(lambdaArn) // arn:aws:lambda:eu-west-1:123456789012:function:myFunction
440
441
// Use built ARNs in notification config
442
const config = new NotificationConfig()
443
444
const topic = new TopicConfig(buildARN('aws', 'sns', 'us-east-1', '123456789012', 'uploads'))
445
topic.addEvent(ObjectCreatedAll)
446
447
const queue = new QueueConfig(buildARN('aws', 'sqs', 'us-east-1', '123456789012', 'processing'))
448
queue.addEvent(ObjectCreatedPut)
449
450
config.add(topic)
451
config.add(queue)
452
```
453
454
## Notification Record Format
455
456
When notifications are received, they follow the S3 notification record format:
457
458
```javascript { .api }
459
// Example notification record structure
460
const notificationRecord = {
461
eventVersion: '2.1',
462
eventSource: 'minio:s3',
463
eventTime: '2023-01-01T12:00:00.000Z',
464
eventName: 's3:ObjectCreated:Put',
465
userIdentity: {
466
principalId: 'minio'
467
},
468
requestParameters: {
469
principalId: 'minio',
470
region: 'us-east-1',
471
sourceIPAddress: '192.168.1.100'
472
},
473
responseElements: {
474
'x-amz-request-id': '17C5B45A35D8CB22',
475
'x-minio-deployment-id': '9b777c1a-3b3d-4f3c-b1c3-8f5b3a1e9c2d'
476
},
477
s3: {
478
s3SchemaVersion: '1.0',
479
configurationId: 'Config',
480
bucket: {
481
name: 'my-bucket',
482
ownerIdentity: {
483
principalId: 'minio'
484
},
485
arn: 'arn:aws:s3:::my-bucket'
486
},
487
object: {
488
key: 'photos/vacation.jpg',
489
size: 2048576,
490
eTag: 'd41d8cd98f00b204e9800998ecf8427e',
491
contentType: 'image/jpeg',
492
userMetadata: {
493
'x-amz-meta-uploader': 'mobile-app'
494
},
495
sequencer: '17C5B45A35D8CB23'
496
}
497
}
498
}
499
```
500
501
## Error Handling
502
503
```javascript { .api }
504
import { S3Error } from 'minio'
505
506
// Handle notification configuration errors
507
client.setBucketNotification('my-bucket', config, (err) => {
508
if (err) {
509
if (err instanceof S3Error) {
510
switch (err.code) {
511
case 'InvalidArgument':
512
console.error('Invalid notification configuration:', err.message)
513
break
514
case 'UnsupportedNotification':
515
console.error('Notification type not supported:', err.message)
516
break
517
default:
518
console.error('S3 notification error:', err.code, err.message)
519
}
520
} else {
521
console.error('Notification error:', err.message)
522
}
523
}
524
})
525
526
// Handle polling errors
527
const listener = client.listenBucketNotification('bucket', '', '', [ObjectCreatedAll])
528
529
listener.on('error', (err) => {
530
console.error('Notification polling error:', err)
531
532
// Implement exponential backoff retry
533
const retryDelay = Math.min(1000 * Math.pow(2, retryCount), 30000)
534
535
setTimeout(() => {
536
console.log('Retrying notification listener...')
537
// Restart listener
538
}, retryDelay)
539
})
540
```
541
542
## Best Practices
543
544
### 1. Event Filtering
545
- Use prefix and suffix filters to reduce notification volume
546
- Filter events at the source rather than in handlers
547
- Consider object naming strategies that support filtering
548
- Monitor notification volume and costs
549
550
### 2. Reliability
551
- Implement error handling and retry logic
552
- Use dead letter queues for failed notifications
553
- Monitor notification delivery rates
554
- Set appropriate timeouts for processing
555
556
### 3. Performance
557
- Process notifications asynchronously
558
- Use appropriate batching for high-volume events
559
- Consider fan-out patterns for multiple consumers
560
- Monitor processing latency and throughput
561
562
### 4. Security
563
- Use IAM policies to restrict notification access
564
- Validate notification sources
565
- Encrypt sensitive notification data
566
- Audit notification configuration changes
567
568
### 5. Monitoring
569
- Track notification delivery and processing metrics
570
- Set up alerts for notification failures
571
- Monitor resource usage of notification handlers
572
- Log notification events for troubleshooting
573
574
---
575
576
**Next:** [Types and Errors](./types-and-errors.md) - Complete reference for all error classes, types, and interfaces