---
title: AWS S3
slug: telemetry-pipeline/aws-s3
docTags: 
createdAt: 2025-04-21T00:56:41.050Z
---

## AWS S3 sink&#x20;

The **AWS S3 sink&#x20;**&#x77;rites observability events (logs / metrics / traces) into **Amazon S3 objects**. It’s a **batch** sink, so it accumulates events and periodically uploads them as object files.

### Destination

- **bucket**
  &#x20;The target S3 bucket name. This is the only “where” that is mandatory.&#x20;
- **region**
  &#x20;Which AWS region S3 API calls go to. If wrong, you’ll see auth/signing errors or it’ll try the wrong regional endpoint.&#x20;
- **endpoint**
  &#x20;Overrides the AWS S3 endpoint. Used for:&#x20;
  - S3-compatible storage (MinIO, Ceph RGW, etc.)&#x20;
  - special AWS partitions / private endpoints
    &#x20;If set, worker talks to *that* URL instead of AWS’s default.&#x20;
- **force\_path\_style**
  &#x20;Controls URL style:&#x20;
  - **true**: endpoint/bucket/key (path-style)&#x20;
  - **false**: bucket.endpoint/key (virtual-hosted style)
    &#x20;Many S3-compatible systems prefer path-style; AWS generally supports both (but behavior can vary with TLS/DNS).&#x20;

### Object naming (this defines your “folder structure”)

- **key\_prefix**
  &#x20;Prefix prepended to every object key. Think “directory”.
  &#x20;Best used to partition by date/env/cluster/tenant to keep listing/querying sane.&#x20;
- **filename\_time\_format**
  &#x20;Controls the timestamp portion in the object name (strftime-like).
  &#x20;If you want predictable rotation and time-based grouping, this is the knob.&#x20;
- **filename\_append\_uuid**
  &#x20;If enabled, appends a UUID to the generated object name.
  &#x20;Meaning: avoids collisions when multiple writers create objects in the same second/time-bucket.
  &#x20;Tradeoff: harder to visually scan names, but safer at scale.&#x20;
- **filename\_extension**
  &#x20;Forces a specific file extension (e.g., .json, .log, .txt).
  &#x20;Useful if downstream tooling relies on extensions. Otherwise, optional.&#x20;

### Batching (how often objects are uploaded + how big they are)

- **batch.max\_bytes**
  &#x20;Upper bound on batch size (pre-compression).
  &#x20;Larger → fewer, bigger objects (cheaper + more throughput).
  &#x20;Smaller → more objects (more PUT/list overhead, lower latency).&#x20;
- **batch.max\_events**
  &#x20;Upper bound on number of events per object.
  &#x20;This protects you from huge objects when events are small.&#x20;
- **batch.timeout\_secs**
  &#x20;Maximum time worker waits before it “flushes” the batch even if size/event limits aren’t hit.
  &#x20;Smaller → more near-real-time uploads.
  &#x20;Larger → better efficiency, more latency.&#x20;

### Buffering (what happens if S3 is slow/unreachable)

- **buffer.type** (memory or disk)&#x20;
  - memory: fastest, but you lose buffered data on crash/restart&#x20;
  - disk: slower, but survives restarts&#x20;
- **buffer.max\_size**
  &#x20;Hard cap of buffer storage. When you hit this, you’re “out of cushion”.&#x20;
- **buffer.max\_events** *(only relevant for memory buffer)*
  &#x20;Limit by event count instead of bytes.&#x20;
- **buffer.when\_full** (block or drop\_newest)&#x20;
  - block: apply backpressure upstream (safer, no intentional loss)&#x20;
  - drop\_newest: intentionally drop newest events to keep running (only if you accept loss)&#x20;

### Compression + HTTP metadata

- **compression** (gzip, zstd, snappy, zlib, none)
  &#x20;Controls how payload is compressed before upload.&#x20;
  - gzip: common & widely compatible&#x20;
  - zstd: often best compression ratio/speed balance, but some tooling expects gzip&#x20;
  - none: bigger objects, higher cost&#x20;
- **content\_encoding**
  &#x20;Forces the HTTP Content-Encoding metadata on the object.
  &#x20;Normally this matches your compression; override only if you have a special consumer that expects a specific value.&#x20;
- **content\_type**
  &#x20;Sets object Content-Type.
  &#x20;Useful for browsers/tools or certain pipelines; not critical for most log pipelines.&#x20;

### Storage class + encryption + access control

- **storage\_class**
  &#x20;Sets the S3 storage tier of uploaded objects (STANDARD, IA, Glacier variants, etc.).
  &#x20;This affects cost + retrieval latency. Many teams leave STANDARD and use lifecycle rules later.&#x20;
- **server\_side\_encryption** (AES256 or aws\:kms)
  &#x20;Enables server-side encryption:&#x20;
  - AES256 = SSE-S3 (AWS managed keys)&#x20;
  - aws\:kms = SSE-KMS (KMS keys/policies/audit)&#x20;
- **ssekms\_key\_id**
  &#x20;Which KMS key to use when server\_side\_encryption = aws\:kms.
  &#x20;Critical for compliance / cross-account setups.&#x20;
- **acl** (canned ACL)
  &#x20;Applies an S3 canned ACL to created objects/bucket.
  &#x20;In modern AWS setups, bucket policies + IAM are preferred; ACL is for legacy/cross-account corner cases.&#x20;
- **grant\_read / grant\_full\_control / grant\_read\_acp / grant\_write\_acp**
  &#x20;Adds explicit ACL grants to specific grantees.
  &#x20;Only use when you *must* share object-level permissions via ACLs (rare today).&#x20;
- **tags**
  &#x20;Adds object tags. Useful for lifecycle policies, cost allocation, and governance.&#x20;

### Outbound request behavior (performance + resilience knobs)

- **request.concurrency** (none, fixed number, or adaptive)
  &#x20;How many uploads/requests worker can have in-flight.
  &#x20;More concurrency → more throughput, more pressure on S3/network.&#x20;
- **request.rate\_limit\_num / request.rate\_limit\_duration\_secs**
  &#x20;Caps request rate. Used to avoid throttling or to be nice to S3-compatible backends.&#x20;
- **request.timeout\_secs**
  &#x20;Per-request timeout. Too low can cause retries and duplicates; too high can stall recovery.&#x20;
- **request.retry\_attempts / retry\_strategy**
  &#x20;How aggressively to retry failures.
  &#x20;retry\_strategy.type controls whether to retry everything, nothing, or a custom set (like only certain HTTP codes).&#x20;
- **request.retry\_initial\_backoff\_secs / request.retry\_max\_duration\_secs / request.retry\_jitter\_mode**
  &#x20;Shapes the retry backoff curve (how fast it ramps and whether retries are randomized to avoid retry storms).&#x20;
- **request.adaptive\_concurrency.\***
  &#x20;Controls worker's “auto-tuning” concurrency. Usually leave defaults unless you’re tuning around a flaky endpoint.&#x20;

### Proxy + TLS (network path / trust)

- **proxy.enabled / proxy.http / proxy.https / proxy.no\_proxy**
  &#x20;Routes requests via HTTP(S) proxy; no\_proxy bypass list.&#x20;
- **tls.ca\_file / tls.crt\_file / tls.key\_file / tls.key\_pass**
  &#x20;TLS trust and client cert configuration.&#x20;
- **tls.verify\_certificate**
  &#x20;Whether to verify the certificate chain (should generally be on).&#x20;
- **tls.verify\_hostname**
  &#x20;Whether to verify hostname matches cert (should generally be on).&#x20;
- **tls.server\_name**
  &#x20;Override SNI / hostname used for TLS verification (useful behind proxies or S3-compatible endpoints).&#x20;
- **tls.alpn\_protocols**
  &#x20;Advanced TLS negotiation detail; rarely needed unless a proxy/backend requires specific ALPN.&#x20;

### Timezone (only affects templated date fields)

- **timezone**
  &#x20;Controls what timezone is used when your templated strings include date/time specifiers.
  &#x20;Important if you partition by day and you want day boundaries in UTC vs local time.
