Skip to content

S3 Triggers

defineS3Handler creates Lambda handlers triggered by S3 object events. Import from @mantleframework/core.

The factory normalises both direct (S3→Lambda) and EventBridge-routed (S3→EventBridge→Lambda) event shapes into the same S3RecordContext so your handler code is identical regardless of trigger mode.

Pattern

typescript
import { defineS3Handler } from '@mantleframework/core'
import { getObject } from '@mantleframework/aws'

const s3 = defineS3Handler({
  bucket: 'uploads',
  operationName: 'ProcessUpload',
})
export const handler = s3(async (record, metadata) => {
  const { bucket, key, size } = record
  const object = await getObject({ Bucket: bucket, Key: key })
  await processUpload(object.Body, key)
})

Options

OptionTypeDefaultDescription
bucketstring--Bucket name — matches config.storage[].name for CLI infra wiring
trigger'direct' | 'eventbridge''direct'Trigger mechanism
operationNamestringfunction nameName for metrics and tracing
loggingLoggingConfig--Fixture logging configuration
timeoutnumber--Lambda timeout in seconds
memorySizenumber128Lambda memory in MB
reservedConcurrencynumber--Reserved concurrent executions
ephemeralStoragenumber512Ephemeral storage in MB
deadLetterQueueboolean | { targetArn? }--true = auto-generate SQS DLQ
retryAttemptsnumber--Max retry attempts (0-2)

Per-Record Callback

The inner handler is called once per S3 record and receives S3RecordContext:

typescript
interface S3RecordContext {
  bucket: string          // S3 bucket name
  key: string             // S3 object key (URL-decoded)
  size: number            // Object size in bytes
  eventName: string       // e.g. 'ObjectCreated:Put'
  eventTime: string       // ISO timestamp of the event
  rawRecord: S3EventRecord
}

The second argument is WrapperMetadata:

typescript
interface WrapperMetadata {
  traceId: string
  correlationId: string
}

Trigger Modes

Direct (S3 → Lambda)

The default. S3 invokes Lambda directly via a bucket notification configuration.

typescript
const s3 = defineS3Handler({ bucket: 'uploads', trigger: 'direct' })

EventBridge (S3 → EventBridge → Lambda)

S3 emits events to EventBridge, which routes them to Lambda. Useful when multiple consumers need to react to the same S3 event, or when you want centralised event routing.

typescript
const s3 = defineS3Handler({ bucket: 'uploads', trigger: 'eventbridge' })

The handler code is identical in both modes — the factory normalises the event shape.

Bucket Config

The bucket option must match a storage entry in mantle.config.ts:

typescript
export default defineConfig({
  storage: [
    { name: 'uploads' },
    { name: 'exports' },
  ],
})

The CLI uses this to wire S3 notifications and IAM permissions automatically.

File Location

S3 handlers live under src/lambdas/s3/<HandlerName>/index.ts:

src/lambdas/s3/
  ProcessUpload/
    index.ts
  ProcessExport/
    index.ts

See Also