メインコンテンツまでスキップ
に最終更新

S3 notification ingestion

Notification ingestion uses NOTIFICATION to consume S3 object-created events from SQS and continuously ingest new files into Doris. It suits UUID filenames and files arriving in any order, without relying on filename ordering.

Only AWS S3 notifications sent directly to an SQS Standard Queue in the same Region are supported. Each job needs a dedicated queue. Historical objects are not scanned or backfilled. End-to-end delivery is at-least-once: an object can be ingested more than once, and file ingestion order is not guaranteed.

Quick start​

The example uses s3://example-bucket/data/*.csv in us-east-1. Replace the bucket, account, queue, and credentials with your values.

Prepare the Doris target table​

The account needs LOAD on the target table and the corresponding database/table creation privileges. Use a separate empty table to avoid overlap with other examples.

CREATE DATABASE IF NOT EXISTS db1;
CREATE TABLE db1.tbl1 (
id INT,
name STRING
)
DUPLICATE KEY(id)
DISTRIBUTED BY HASH(id) BUCKETS 1
PROPERTIES ("replication_num" = "1");

This single-BE example uses one replica. Adjust the replica count for production.

Step 1: Create an SQS Standard Queue​

Create a Standard Queue in the same Region as the S3 bucket and record its URL and ARN. A 14-day message retention period is recommended to cover pauses and failures. SQS deletes messages after the retention period expires.

Step 2: Allow S3 to send notifications​

Merge the following statement into the queue access policy, replacing the account, bucket, and queue identifiers:

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowS3ToSendMessage",
"Effect": "Allow",
"Principal": {"Service": "s3.amazonaws.com"},
"Action": "sqs:SendMessage",
"Resource": "arn:aws:sqs:us-east-1:<account-id>:<queue-name>",
"Condition": {
"ArnEquals": {"aws:SourceArn": "arn:aws:s3:::example-bucket"},
"StringEquals": {"aws:SourceAccount": "<account-id>"}
}
}
]
}

Step 3: Grant Doris access​

Grant the job's IAM user or role the following permissions. FE needs SQS and S3 access; BE needs to read S3 objects. AssumeRole also requires STS connectivity.

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::example-bucket"
},
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::example-bucket/data/*"
},
{
"Effect": "Allow",
"Action": [
"sqs:ReceiveMessage",
"sqs:DeleteMessage",
"sqs:GetQueueAttributes",
"sqs:ChangeMessageVisibility"
],
"Resource": "arn:aws:sqs:us-east-1:<account-id>:<queue-name>"
}
]
}

Step 4: Configure S3 event notifications​

Create a rule under the bucket's Event notifications:

  • Select All object create events (s3:ObjectCreated:*).
  • Set Prefix to data/ and Suffix to .csv, without wildcards. The rule must cover the job's URI pattern.
  • Select the SQS queue as the destination. Send S3 messages directly without an SNS envelope.

Enable the rule before uploading files to ingest. Creating a notification rule does not generate events for existing objects.

Step 5: Create the Streaming Job​

S3 TVF needs matching files for schema inference during job creation. After enabling notifications, upload a non-empty data/001.csv containing:

1,Alice
2,Bob

Then create the job:

CREATE JOB s3_event_job
PROPERTIES (
"s3.ingestion_mode" = "NOTIFICATION",
"s3.event.source" = "SQS",
"s3.sqs.queue_url" = "https://sqs.us-east-1.amazonaws.com/<account-id>/<queue-name>",
"max_interval" = "10"
)
ON STREAMING DO
INSERT INTO db1.tbl1
SELECT * FROM S3(
"uri" = "s3://example-bucket/data/*.csv",
"format" = "csv",
"column_separator" = ",",
"provider" = "S3",
"s3.region" = "us-east-1",
"s3.endpoint" = "https://s3.us-east-1.amazonaws.com",
"s3.access_key" = "<access-key>",
"s3.secret_key" = "<secret-key>"
);

This file generates an SQS notification. Objects uploaded before notifications were configured can supply schema inference, but are not automatically backfilled. At least one matching file must remain readable when creating the job.

To use an IAM role, replace the access-key and secret-key options with the following; s3.external_id is optional depending on the trust policy:

"s3.role_arn" = "arn:aws:iam::<account-id>:role/<role-name>",
"s3.external_id" = "<external-id>"

FE calls AssumeRole using its configured AWS credentials. The role needs S3 and SQS permissions, the caller needs sts:AssumeRole, and the role's trust policy must allow that caller.

After processing the notification for data/001.csv, the table contains the corresponding two rows. Later files are ingested through notifications even if their keys are smaller than previously processed keys. Repeated notifications can affect the row count depending on the target table model.

Step 6: Monitor the queue backlog​

SELECT Name, Status, CurrentOffset, EndOffset, LagBytes,
LastSourceEventTimestamp, LastTaskSuccessTime
FROM jobs("type" = "insert")
WHERE Name = 's3_event_job';

Example CurrentOffset: {"fileName":"data/a.csv"}. Example EndOffset: {"fileName":"data/b.csv","lagMessages":12}. These keys describe batch positions, not lexicographical watermarks, and cannot determine whether ingestion has caught up.

FieldMeaning in notification mode
LagBytes-1: the byte size of queued objects is unavailable.
EndOffset.lagMessagesApproximate visible SQS messages, excluding in-flight and delayed messages. It is not a file count.
LastSourceEventTimestampMaximum S3 event timestamp in the most recently committed batch, in Unix seconds. It does not prove that all earlier events have been processed.

FE also exposes per-job metrics:

doris_fe_streaming_job_per_job_lag_messages
doris_fe_streaming_job_per_job_last_source_event_timestamp_seconds

Acknowledgment and limitations​

  • Only retained SQS notifications are consumed. Historical objects are not scanned.
  • Job creation requires a matching, readable, non-empty file for S3 TVF schema inference.
  • Each queue must be exclusive to one job. Doris skips and acknowledges out-of-scope records, malformed or unsupported notifications, and S3 test events. Jobs with different URI patterns must not share a queue.
  • For valid files, messages are deleted after the INSERT transaction commits. Visibility is extended during processing, and failed batches can be retried. FE recovery can use persisted keys from the most recently committed batch to handle its redelivery; Doris does not persist every historical key for global deduplication.
  • S3 and SQS can deliver duplicates. End-to-end semantics are at-least-once and file ingestion order is not guaranteed. Use a Unique Key table for business deduplication and a Sequence column for order-sensitive updates as needed.
  • Keep object keys unique and content immutable and readable. Doris reads the content at processing time, not necessarily the version present when the event was emitted. Deleting objects early causes failures and retries.

Parameters​

Configure the following in Job PROPERTIES. S3 connection, credentials, and file format options belong in S3(...).

ParameterTypeDefaultRequiredDescription
s3.ingestion_modeStringORDERED_LISTYesSet to NOTIFICATION. Cannot be changed after creation.
s3.event.sourceStringNoneYesMust be SQS. Cannot be changed after creation.
s3.sqs.queue_urlStringNoneYesURL of the dedicated SQS queue. Cannot be changed after creation.
s3.max_batch_filesPositive integer256NoFile count threshold per batch.
s3.max_batch_bytesInteger10737418240NoByte threshold per batch, from 104857600 to 10737418240. Unit suffixes are not accepted.
max_intervalPositive integer10NoIdle scheduling interval in seconds. Must be less than 7200.

Batch thresholds are soft and do not require waiting for a full batch. Already received messages stay in the same batch; the next receive stops after a threshold is reached, so a batch can exceed either threshold. offset is prohibited during creation and ALTER JOB. The S3 URI cannot be changed. Create another job to change the path or queue.

Troubleshooting and best practices​

SymptomChecks and action
Job creation failsCheck matching non-empty files, S3/SQS permissions, and network connectivity.
The job runs without ingesting filesCheck that notifications preceded uploads, s3:ObjectCreated:* is selected, filters cover the URI, and no other consumer reads the queue.
Historical files are missingNotification rules do not replay historical events. Use a separate prefix and one-time ingestion.
Files are missing after a pauseCheck SQS message retention and backfill missing files separately if needed.
Repeated read failuresInspect ErrorMsg and task errors. Check object availability, immutability, and format compatibility.
Duplicate rowsReview business keys and the target table model. Do not rely on global historical file deduplication.

Set sufficient message retention, keep objects immutable and readable, and monitor approximate backlog, last success time, and task errors. For job management, see Continuous Load Overview and ALTER JOB.