@forzalabs/remora 2.4.0 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1150 @@
1
+ # Remora - Sources
2
+
3
+ ## **Overview**
4
+
5
+ Sources in Remora define the connection configurations to your data storage systems. They act as the foundation for data extraction through producers and serve as the bridge between Remora and your various data stores.
6
+
7
+ Each source configuration specifies:
8
+
9
+ - **Connection details** (host, credentials, region, etc.)
10
+ - **Authentication method** (how to securely connect)
11
+ - **Engine type** (what kind of data store it is)
12
+
13
+ ## **Source Types (Engines)**
14
+
15
+ Remora supports the following source engines:
16
+
17
+ | Engine | Description | Use Cases |
18
+ | --- | --- | --- |
19
+ | `local` | Local file system | Development, testing, file-based data processing |
20
+ | `aws-s3` | Amazon S3 storage | Cloud object storage, data lakes, file archives |
21
+ | `aws-redshift` | Amazon Redshift data warehouse | SQL analytics, business intelligence, data warehousing |
22
+ | `postgres` | PostgreSQL server (RDS, Aurora, or self-hosted) | Operational databases, application data, SQL extraction |
23
+ | `delta-share` | Delta Share protocol | Data sharing across organizations, Databricks integration |
24
+ | `http-api` | REST / HTTP API endpoint | External services, SaaS integrations |
25
+ | `presigned-url` | A file reached through a URL signed on demand by an API | Reading from or writing to a bucket Remora holds no credentials for |
26
+ | `aws-sqs` | Amazon SQS queue | Queue-triggered consumer execution (see consumer QUEUE triggers) |
27
+
28
+ ---
29
+
30
+ ## **Authentication Methods**
31
+
32
+ The `authentication.method` field selects how Remora connects. The methods available depend on the engine:
33
+
34
+ | Method | Used by | Description |
35
+ | --- | --- | --- |
36
+ | `implicit` | `local` | No credentials — read/write a local path |
37
+ | `access-secret-key` | `aws-s3`, `aws-redshift`, `aws-sqs` | Static AWS access key + secret (optionally a session token) |
38
+ | `iam` | `aws-s3`, `aws-redshift`, `aws-sqs`, `postgres` | Use the AWS SDK default credential chain (EC2/ECS/EKS instance or task role, SSO, env vars) — no static keys stored. On `postgres` this signs a short-lived RDS IAM auth token instead of sending a password |
39
+ | `arn` | `aws-s3`, `aws-redshift`, `aws-sqs`, `postgres` | Assume an IAM role via STS (`roleArn`); base identity comes from the SDK default chain |
40
+ | `bearer-token` | `delta-share`, `http-api`, `presigned-url` | Static bearer token |
41
+ | `oidc` | `delta-share`, `presigned-url` | OAuth2 client-credentials grant (e.g. Okta/Cognito) that mints a short-lived token. This is what machine-to-machine (M2M) authentication on an API Gateway means |
42
+ | `api-key` | `http-api`, `presigned-url` | API key sent in a header |
43
+ | `username-password` | `http-api`, `postgres`, `presigned-url` | HTTP Basic authentication, or a database user and password |
44
+ | `none` | `http-api`, `presigned-url` | No authentication (public endpoints) |
45
+
46
+ > **Security tip:** never hard-code secrets. Reference environment variables with the `{ENV_VAR}` notation (e.g. `"accessKey": "{AWS_ACCESS_KEY_ID}"`), and prefer `iam`/`arn` over static keys on AWS.
47
+
48
+ ---
49
+
50
+ ## **Local Sources**
51
+
52
+ Local sources connect to files on your local file system or network-accessible directories.
53
+
54
+ ### **Configuration Schema**
55
+
56
+ ```json
57
+ {
58
+ "$schema": "https://raw.githubusercontent.com/ForzaLabs/remora-public/refs/heads/main/json_schemas/source-schema.json",
59
+ "name": "source-name",
60
+ "engine": "local",
61
+ "authentication": {
62
+ "method": "implicit",
63
+ "path": "/path/to/data/directory"
64
+ },
65
+ "_version": 1
66
+ }
67
+ ```
68
+
69
+ ### **Authentication Properties**
70
+
71
+ | Property | Required | Description | Example |
72
+ | --- | --- | --- | --- |
73
+ | `method` | ✅ | Must be `"implicit"` | `"implicit"` |
74
+ | `path` | ✅ | Directory path containing data files | `"./data"`, `"/Users/john/datasets"` |
75
+
76
+ ### **Supported File Types**
77
+
78
+ Local sources can process:
79
+
80
+ - **JSON** files (`.json`)
81
+ - **JSON Lines** files (`.jsonl`, `.ndjson`)
82
+ - **CSV** files (`.csv`)
83
+ - **Text** files (`.txt`)
84
+ - **Excel** files (`.xlsx`, `.xls`)
85
+ - **XML** files (`.xml`)
86
+
87
+ ## Supported compression type
88
+
89
+ Local sources can process:
90
+
91
+ - GZ files (`'GZ'`)
92
+ - TAR files (`'TAR'`)
93
+ - ZIP files (`'ZIP'`)
94
+
95
+ ### **Example Configurations**
96
+
97
+ **Development Data Source:**
98
+
99
+ ```json
100
+ {
101
+ "$schema": "https://raw.githubusercontent.com/ForzaLabs/remora-public/refs/heads/main/json_schemas/source-schema.json",
102
+ "name": "local-dev",
103
+ "description": "Local development data files",
104
+ "engine": "local",
105
+ "authentication": {
106
+ "method": "implicit",
107
+ "path": "./demo"
108
+ },
109
+ "_version": 1
110
+ }
111
+ ```
112
+
113
+ **Output Destination:**
114
+
115
+ ```json
116
+ {
117
+ "$schema": "https://raw.githubusercontent.com/ForzaLabs/remora-public/refs/heads/main/json_schemas/source-schema.json",
118
+ "name": "output-folder",
119
+ "description": "Local directory for processed results",
120
+ "engine": "local",
121
+ "authentication": {
122
+ "method": "implicit",
123
+ "path": "./output"
124
+ },
125
+ "_version": 1
126
+ }
127
+ ```
128
+
129
+ ### **Best Practices**
130
+
131
+ - Use **relative paths** for portability across environments
132
+ - Ensure the path exists and has appropriate read/write permissions
133
+ - Use descriptive names that indicate the data purpose
134
+ - Consider file organization within the specified directory
135
+
136
+ ---
137
+
138
+ ## **AWS S3 Sources**
139
+
140
+ AWS S3 sources connect to Amazon Simple Storage Service buckets for cloud-based object storage.
141
+
142
+ ### **Configuration Schema**
143
+
144
+ ```json
145
+ {
146
+ "$schema": "https://raw.githubusercontent.com/ForzaLabs/remora-public/refs/heads/main/json_schemas/source-schema.json",
147
+ "name": "source-name",
148
+ "engine": "aws-s3",
149
+ "authentication": {
150
+ "method": "access-secret-key",
151
+ "region": "aws-region",
152
+ "accessKey": "{AWS_ACCESS_KEY_ID}",
153
+ "secretKey": "{AWS_SECRET_ACCESS_KEY}",
154
+ "sessionToken": "{AWS_SESSION_TOKEN}",
155
+ "bucket": "bucket-name"
156
+ },
157
+ "_version": 1
158
+ }
159
+ ```
160
+
161
+ ### **Authentication Properties**
162
+
163
+ | Property | Required | Description | Example |
164
+ | --- | --- | --- | --- |
165
+ | `method` | ✅ | `"access-secret-key"` for static keys, or `"iam"` / `"arn"` for IAM roles | `"access-secret-key"` |
166
+ | `region` | ✅ | AWS region where the bucket is located | `"us-east-1"`, `"eu-west-1"` |
167
+ | `accessKey` | ✅ | AWS Access Key ID (use environment variables) | `"{AWS_ACCESS_KEY_ID}"` |
168
+ | `secretKey` | ✅ | AWS Secret Access Key (use environment variables) | `"{AWS_SECRET_ACCESS_KEY}"` |
169
+ | `bucket` | ✅ | S3 bucket name | `"my-data-bucket"` |
170
+ | `sessionToken` | ❌ | AWS Session Token for temporary credentials | `"{AWS_SESSION_TOKEN}"` |
171
+
172
+ > `method` can also be `"iam"` or `"arn"` — see [IAM Role Authentication](#iam-role-authentication) below. With those, `accessKey`/`secretKey` are not required.
173
+
174
+ ### **IAM Role Authentication**
175
+
176
+ Instead of static keys, AWS sources (`aws-s3`, `aws-redshift`, `aws-sqs`) can authenticate through IAM roles — the recommended approach for anything running on AWS:
177
+
178
+ - **`method: "iam"`** — use the AWS SDK default credential chain (EC2/ECS/EKS instance or task role, SSO, or `AWS_*` env vars). No keys are stored in the config.
179
+
180
+ ```json
181
+ {
182
+ "authentication": {
183
+ "method": "iam",
184
+ "region": "us-east-1",
185
+ "bucket": "company-data-lake"
186
+ }
187
+ }
188
+ ```
189
+
190
+ - **`method: "arn"`** — assume a specific IAM role via STS. The base identity that performs the AssumeRole call still comes from the SDK default chain (no data-access keys in the config). Useful for cross-account access.
191
+
192
+ | Property | Required | Description |
193
+ | --- | --- | --- |
194
+ | `roleArn` | ✅ | ARN of the role to assume, e.g. `arn:aws:iam::123456789012:role/remora-reader` |
195
+ | `roleSessionName` | ❌ | Session name for the assumed credentials (defaults to `remora`) |
196
+ | `externalId` | ❌ | STS ExternalId for third-party / cross-account trust policies |
197
+
198
+ ```json
199
+ {
200
+ "authentication": {
201
+ "method": "arn",
202
+ "region": "eu-west-1",
203
+ "bucket": "analytics-exports",
204
+ "roleArn": "arn:aws:iam::123456789012:role/remora-s3-reader",
205
+ "externalId": "{REMORA_STS_EXTERNAL_ID}"
206
+ }
207
+ }
208
+ ```
209
+
210
+ ### **Security Best Practices**
211
+
212
+ **Environment Variables (Recommended):**
213
+
214
+ ```json
215
+ {
216
+ "authentication": {
217
+ "method": "access-secret-key",
218
+ "region": "us-east-1",
219
+ "accessKey": "{AWS_ACCESS_KEY_ID}",
220
+ "secretKey": "{AWS_SECRET_ACCESS_KEY}",
221
+ "sessionToken": "{AWS_SESSION_TOKEN}",
222
+ "bucket": "my-data-bucket"
223
+ }
224
+ }
225
+ ```
226
+
227
+ Set these environment variables:
228
+
229
+ ```bash
230
+ export AWS_ACCESS_KEY_ID=your_access_key_here
231
+ export AWS_SECRET_ACCESS_KEY=your_secret_key_here
232
+ export AWS_SESSION_TOKEN=your_session_token_here# Optional
233
+ ```
234
+
235
+ ### **IAM Permissions Required**
236
+
237
+ Your AWS credentials need the following S3 permissions:
238
+
239
+ ```json
240
+ {
241
+ "Version": "2012-10-17",
242
+ "Statement": [
243
+ {
244
+ "Effect": "Allow",
245
+ "Action": [
246
+ "s3:GetObject",
247
+ "s3:ListBucket",
248
+ "s3:PutObject",
249
+ "s3:DeleteObject"
250
+ ],
251
+ "Resource": [
252
+ "arn:aws:s3:::your-bucket-name",
253
+ "arn:aws:s3:::your-bucket-name/*"
254
+ ]
255
+ }
256
+ ]
257
+ }
258
+ ```
259
+
260
+ ### **Example Configurations**
261
+
262
+ **Data Lake Source:**
263
+
264
+ ```json
265
+ {
266
+ "$schema": "https://raw.githubusercontent.com/ForzaLabs/remora-public/refs/heads/main/json_schemas/source-schema.json",
267
+ "name": "data-lake",
268
+ "description": "Production data lake in S3",
269
+ "engine": "aws-s3",
270
+ "authentication": {
271
+ "method": "access-secret-key",
272
+ "region": "us-east-1",
273
+ "accessKey": "{AWS_ACCESS_KEY_ID}",
274
+ "secretKey": "{AWS_SECRET_ACCESS_KEY}",
275
+ "bucket": "company-data-lake"
276
+ },
277
+ "_version": 1
278
+ }
279
+ ```
280
+
281
+ **Archive Storage:**
282
+
283
+ ```json
284
+ {
285
+ "$schema": "https://raw.githubusercontent.com/ForzaLabs/remora-public/refs/heads/main/json_schemas/source-schema.json",
286
+ "name": "archive-storage",
287
+ "description": "Historical data archive",
288
+ "engine": "aws-s3",
289
+ "authentication": {
290
+ "method": "access-secret-key",
291
+ "region": "us-west-2",
292
+ "accessKey": "{ARCHIVE_ACCESS_KEY}",
293
+ "secretKey": "{ARCHIVE_SECRET_KEY}",
294
+ "bucket": "historical-data-archive"
295
+ },
296
+ "_version": 1
297
+ }
298
+ ```
299
+
300
+ ### **Supported Operations**
301
+
302
+ - **Reading files** from S3 buckets
303
+ - **Writing processed results** back to S3
304
+ - **Listing objects** within bucket prefixes
305
+ - **Streaming large files** for memory-efficient processing
306
+
307
+ ---
308
+
309
+ ## **AWS Redshift Sources**
310
+
311
+ AWS Redshift sources connect to Amazon Redshift data warehouses for SQL-based analytics and data processing.
312
+
313
+ ### **Configuration Schema**
314
+
315
+ ```json
316
+ {
317
+ "$schema": "https://raw.githubusercontent.com/ForzaLabs/remora-public/refs/heads/main/json_schemas/source-schema.json",
318
+ "name": "source-name",
319
+ "engine": "aws-redshift",
320
+ "authentication": {
321
+ "method": "access-secret-key",
322
+ "region": "aws-region",
323
+ "accessKey": "{AWS_ACCESS_KEY_ID}",
324
+ "secretKey": "{AWS_SECRET_ACCESS_KEY}",
325
+ "sessionToken": "{AWS_SESSION_TOKEN}",
326
+ "database": "database-name",
327
+ "workgroup": "workgroup-name"
328
+ },
329
+ "_version": 1
330
+ }
331
+ ```
332
+
333
+ ### **Authentication Properties**
334
+
335
+ | Property | Required | Description | Example |
336
+ | --- | --- | --- | --- |
337
+ | `method` | ✅ | `"access-secret-key"` for static keys, or `"iam"` / `"arn"` for IAM roles | `"access-secret-key"` |
338
+ | `region` | ✅ | AWS region where Redshift cluster is located | `"us-east-1"`, `"eu-west-1"` |
339
+ | `accessKey` | ✅ | AWS Access Key ID (use environment variables) | `"{AWS_ACCESS_KEY_ID}"` |
340
+ | `secretKey` | ✅ | AWS Secret Access Key (use environment variables) | `"{AWS_SECRET_ACCESS_KEY}"` |
341
+ | `database` | ✅ | Redshift database name | `"analytics_db"`, `"data_warehouse"` |
342
+ | `workgroup` | ✅ | Redshift workgroup name | `"primary"`, `"analytics-workgroup"` |
343
+ | `sessionToken` | ❌ | AWS Session Token for temporary credentials | `"{AWS_SESSION_TOKEN}"` |
344
+
345
+ ### **IAM Permissions Required**
346
+
347
+ Your AWS credentials need the following Redshift permissions:
348
+
349
+ ```json
350
+ {
351
+ "Version": "2012-10-17",
352
+ "Statement": [
353
+ {
354
+ "Effect": "Allow",
355
+ "Action": [
356
+ "redshift-data:ExecuteStatement",
357
+ "redshift-data:DescribeStatement",
358
+ "redshift-data:GetStatementResult",
359
+ "redshift-data:ListStatements"
360
+ ],
361
+ "Resource": "*"
362
+ },
363
+ {
364
+ "Effect": "Allow",
365
+ "Action": [
366
+ "redshift-serverless:GetWorkgroup",
367
+ "redshift-serverless:GetNamespace"
368
+ ],
369
+ "Resource": "*"
370
+ }
371
+ ]
372
+ }
373
+ ```
374
+
375
+ ### **Example Configurations**
376
+
377
+ **Analytics Data Warehouse:**
378
+
379
+ ```json
380
+ {
381
+ "$schema": "https://raw.githubusercontent.com/ForzaLabs/remora-public/refs/heads/main/json_schemas/source-schema.json",
382
+ "name": "analytics-warehouse",
383
+ "description": "Main analytics data warehouse",
384
+ "engine": "aws-redshift",
385
+ "authentication": {
386
+ "method": "access-secret-key",
387
+ "region": "us-east-1",
388
+ "accessKey": "{REDSHIFT_ACCESS_KEY}",
389
+ "secretKey": "{REDSHIFT_SECRET_KEY}",
390
+ "database": "analytics_db",
391
+ "workgroup": "analytics-workgroup"
392
+ },
393
+ "_version": 1
394
+ }
395
+ ```
396
+
397
+ **Development Environment:**
398
+
399
+ ```json
400
+ {
401
+ "$schema": "https://raw.githubusercontent.com/ForzaLabs/remora-public/refs/heads/main/json_schemas/source-schema.json",
402
+ "name": "dev-redshift",
403
+ "description": "Development Redshift environment",
404
+ "engine": "aws-redshift",
405
+ "authentication": {
406
+ "method": "access-secret-key",
407
+ "region": "us-west-2",
408
+ "accessKey": "{DEV_ACCESS_KEY}",
409
+ "secretKey": "{DEV_SECRET_KEY}",
410
+ "database": "dev_database",
411
+ "workgroup": "dev-workgroup"
412
+ },
413
+ "_version": 1
414
+ }
415
+ ```
416
+
417
+ ### **How a run reads a table**
418
+
419
+ A producer on a Redshift source names its table with `sqlTable` and lists the columns it wants as
420
+ dimensions — there is no `fileKey` and no `fileType`. Remora builds the `SELECT` from those
421
+ dimensions (a dimension's `alias` is the column name when it differs from the dimension name), runs
422
+ it through the Redshift Data API, and stages the result as a local dataset file that the rest of the
423
+ pipeline reads. The staging read follows the Data API's `NextToken` pages to the end of the result
424
+ and compares what it staged against the row count the cluster reports, so a result larger than one
425
+ page can never come back short without an error.
426
+
427
+ ```json
428
+ {
429
+ "name": "p_customers",
430
+ "source": "analytics-warehouse",
431
+ "settings": { "sqlTable": "analytics.customers" },
432
+ "dimensions": [
433
+ { "name": "id", "type": "string", "pk": true },
434
+ { "name": "firstName", "type": "string", "alias": "first_name" },
435
+ { "name": "monthlySpend", "type": "number", "alias": "monthly_spend" }
436
+ ],
437
+ "_version": 1
438
+ }
439
+ ```
440
+
441
+ `sqlTable` may be `table` or `schema.table`. An unqualified name falls back to the source's `schema`.
442
+
443
+ ### **SQL Query Limitations**
444
+
445
+ - **Maximum query rows**: `SQL_MAX_QUERY_ROWS` (default `10000`) caps the ad-hoc reads behind
446
+ `remora sample` and `remora discover`, which return rows in memory. It does **not** cap a run: a run
447
+ stages the whole table a page at a time, bounded by disk rather than by this setting
448
+ - **Statement timeout**: a staging statement is polled for up to 30 minutes before it is abandoned
449
+ - **Concurrent queries**: Limited by Redshift workgroup configuration
450
+ - **Memory usage**: no page of the result is held once it has been written to the staged file
451
+
452
+ ### **Performance Considerations**
453
+
454
+ - **Index usage** in underlying tables improves query performance
455
+ - **Workgroup sizing** affects concurrent query capacity
456
+ - Producers query the source directly; use the producer-level `direct: true` setting to signal read-only access (see the Producers guide)
457
+
458
+ > **IAM authentication:** Redshift sources can also use `method: "iam"` (or `"arn"`). In that case supply `host`, `clusterId`, `port`, and an `iamProfile` (or `roleArn` for `arn`) instead of static keys.
459
+
460
+ ---
461
+
462
+ ## **PostgreSQL Sources**
463
+
464
+ `postgres` sources read from a PostgreSQL server over the native wire protocol — Amazon RDS, Aurora
465
+ PostgreSQL, or a self-hosted instance. The engine is not named `aws-postgres` because nothing about
466
+ it requires AWS; the IAM auth token below is the only AWS-specific part, and it is optional.
467
+
468
+ Unlike Redshift, which is reached over an HTTPS API, a `postgres` source needs network reachability
469
+ to the database: a security group that admits the machine running remora, and a route to it (a VPC,
470
+ a peering connection or a VPN) when the database is not public.
471
+
472
+ ### **Configuration Schema**
473
+
474
+ ```json
475
+ {
476
+ "$schema": "https://raw.githubusercontent.com/ForzaLabs/remora-public/refs/heads/main/json_schemas/source-schema.json",
477
+ "name": "source-name",
478
+ "engine": "postgres",
479
+ "authentication": {
480
+ "method": "username-password",
481
+ "host": "{PG_HOST}",
482
+ "port": "5432",
483
+ "database": "analytics",
484
+ "schema": "public",
485
+ "user": "{PG_USER}",
486
+ "password": "{PG_PASSWORD}",
487
+ "sslMode": "require"
488
+ },
489
+ "_version": 1
490
+ }
491
+ ```
492
+
493
+ ### **Authentication Properties**
494
+
495
+ | Property | Required | Description | Example |
496
+ | --- | --- | --- | --- |
497
+ | `method` | ✅ | `"username-password"` for a password, or `"iam"` / `"arn"` for an RDS IAM auth token | `"username-password"` |
498
+ | `host` | ✅ | Hostname of the server or cluster endpoint | `"db.cluster-abc.eu-west-1.rds.amazonaws.com"` |
499
+ | `database` | ✅ | Database to connect to | `"analytics"` |
500
+ | `user` | ✅ | Database user | `"remora_reader"` |
501
+ | `password` | ⚠️ | Required unless the method signs an IAM token. Use the `{ENV_VAR}` notation | `"{PG_PASSWORD}"` |
502
+ | `region` | ⚠️ | Required when the method is `"iam"` or `"arn"`, to sign the token | `"eu-west-1"` |
503
+ | `roleArn` | ⚠️ | Required when the method is `"arn"` | `"arn:aws:iam::123456789012:role/remora-reader"` |
504
+ | `port` | ❌ | Defaults to `5432` | `"5432"` |
505
+ | `schema` | ❌ | Default schema for producers whose `sqlTable` is unqualified | `"public"` |
506
+ | `sslMode` | ❌ | `disable`, `require` (default for a remote host) or `verify-full` | `"require"` |
507
+ | `connectionTimeoutMs` | ❌ | Connection and handshake timeout in milliseconds, default `30000` | `10000` |
508
+
509
+ ⚠️ = required depending on `method`. `remora verify` reports which of these is missing for the method the source declares.
510
+
511
+ ### **TLS**
512
+
513
+ `sslMode` defaults to `require` for a remote host and `disable` for `localhost` / `127.0.0.1`, since
514
+ a database on the same machine usually speaks no TLS at all.
515
+
516
+ - `require` encrypts the connection but does not verify the server certificate. This is what RDS
517
+ accepts with nothing else configured
518
+ - `verify-full` also verifies the certificate chain against the process trust store. Point
519
+ `NODE_EXTRA_CA_CERTS` at the RDS CA bundle when you use it, or the handshake will fail
520
+
521
+ ### **IAM authentication (RDS and Aurora)**
522
+
523
+ With `method: "iam"` there is no database password anywhere in the configuration: remora signs a
524
+ short-lived RDS auth token for each connection and sends that instead. The AWS credentials that sign
525
+ it come from the SDK default credential chain — an ECS task role, an EC2 instance role, SSO, or
526
+ environment variables — exactly as for every other AWS engine. Use `method: "arn"` with a `roleArn`
527
+ to sign it with an assumed role instead.
528
+
529
+ This requires IAM authentication to be enabled on the instance or cluster, a database user granted
530
+ `rds_iam`, and the following permission:
531
+
532
+ ```json
533
+ {
534
+ "Version": "2012-10-17",
535
+ "Statement": [
536
+ {
537
+ "Effect": "Allow",
538
+ "Action": ["rds-db:connect"],
539
+ "Resource": "arn:aws:rds-db:eu-west-1:123456789012:dbuser:cluster-ABCDEFGH/remora_reader"
540
+ }
541
+ ]
542
+ }
543
+ ```
544
+
545
+ ### **Example — Aurora with IAM authentication**
546
+
547
+ ```json
548
+ {
549
+ "$schema": "https://raw.githubusercontent.com/ForzaLabs/remora-public/refs/heads/main/json_schemas/source-schema.json",
550
+ "name": "aurora-analytics",
551
+ "description": "Aurora PostgreSQL read replica, no stored password",
552
+ "engine": "postgres",
553
+ "authentication": {
554
+ "method": "iam",
555
+ "host": "analytics.cluster-ro-abc123.eu-west-1.rds.amazonaws.com",
556
+ "port": "5432",
557
+ "database": "analytics",
558
+ "schema": "public",
559
+ "user": "remora_reader",
560
+ "region": "eu-west-1",
561
+ "sslMode": "require"
562
+ },
563
+ "_version": 1
564
+ }
565
+ ```
566
+
567
+ ### **How a run reads a table**
568
+
569
+ Exactly as for Redshift: the producer names its table with `sqlTable` and its columns as dimensions,
570
+ and remora builds the `SELECT` and stages the result as a local dataset file. The read goes through a
571
+ server-side cursor inside a `READ ONLY` transaction, pulling 10 000 rows per round trip and writing
572
+ each batch to disk before asking for the next, so staging a large table costs disk and not memory.
573
+
574
+ ### **Performance Considerations**
575
+
576
+ - The staging query is a plain `SELECT` of the producer's columns. Narrow the producer's dimensions
577
+ rather than selecting columns the consumer discards
578
+ - Point the source at a **read replica** where one exists: a full-table read competes with the
579
+ primary's operational traffic
580
+ - Filters and limits are not yet pushed into the `WHERE` / `LIMIT` of the staging query, so the whole
581
+ table is read and narrowed by the pipeline
582
+
583
+ ---
584
+
585
+ ## **Delta Share Sources**
586
+
587
+ Delta Share sources connect to Delta Share endpoints for secure data sharing across organizations and platforms.
588
+
589
+ ### **Configuration Schema**
590
+
591
+ ```json
592
+ {
593
+ "$schema": "https://raw.githubusercontent.com/ForzaLabs/remora-public/refs/heads/main/json_schemas/source-schema.json",
594
+ "name": "source-name",
595
+ "engine": "delta-share",
596
+ "authentication": {
597
+ "method": "bearer-token",
598
+ "host": "https://sharing-endpoint.com/api/2.0/delta-sharing/metastores/...",
599
+ "bearerToken": "{DELTA_TOKEN}",
600
+ "share": "share-name",
601
+ "schema": "schema-name",
602
+ "table": "table-name"
603
+ },
604
+ "_version": 1
605
+ }
606
+ ```
607
+
608
+ ### **Authentication Properties**
609
+
610
+ | Property | Required | Description | Example |
611
+ | --- | --- | --- | --- |
612
+ | `method` | ✅ | `"bearer-token"` for a static token, or `"oidc"` for OAuth2 client-credentials | `"bearer-token"` |
613
+ | `host` | ✅ | Delta Share endpoint URL | `"https://oregon.cloud.databricks.com/api/2.0/delta-sharing/metastores/..."` |
614
+ | `bearerToken` | ✅ | Delta Share authentication token | `"{DELTA_TOKEN}"` |
615
+ | `share` | ✅ | Share name in Delta Share | `"analytics_share"`, `"customer_data"` |
616
+ | `schema` | ✅ | Schema within the share | `"default"`, `"production"` |
617
+ | `table` | ✅ | Table name within the schema | `"customer_orders"`, `"product_catalog"` |
618
+
619
+ ### **OIDC Authentication**
620
+
621
+ Instead of a static `bearerToken`, Delta Share sources can use `method: "oidc"` to obtain a short-lived token via the OAuth2 client-credentials grant (e.g. Okta or Cognito). Remora fetches and refreshes the token automatically.
622
+
623
+ | Property | Required | Description |
624
+ | --- | --- | --- |
625
+ | `tokenEndpoint` | ✅ | OAuth2 token endpoint that issues the access token |
626
+ | `clientId` | ✅ | OAuth2 client identifier |
627
+ | `clientSecret` | ✅ | OAuth2 client secret |
628
+ | `scope` | ❌ | Space-delimited scopes (required by Okta/Cognito for client-credentials) |
629
+ | `audience` | ❌ | Audience/resource parameter for IdPs that require it |
630
+ | `clientAuthMethod` | ❌ | How client credentials are sent: `"basic"` (default) or `"post"` (request body) |
631
+
632
+ ```json
633
+ {
634
+ "engine": "delta-share",
635
+ "authentication": {
636
+ "method": "oidc",
637
+ "host": "https://sharing.example.com/delta-sharing",
638
+ "share": "my_share",
639
+ "schema": "my_schema",
640
+ "table": "my_table",
641
+ "tokenEndpoint": "https://example.okta.com/oauth2/default/v1/token",
642
+ "clientId": "{DELTA_SHARE_CLIENT_ID}",
643
+ "clientSecret": "{DELTA_SHARE_CLIENT_SECRET}",
644
+ "scope": "delta_sharing"
645
+ }
646
+ }
647
+ ```
648
+
649
+
650
+ ### **Security Configuration**
651
+
652
+ **Environment Variables (Recommended):**
653
+
654
+ ```json
655
+ {
656
+ "authentication": {
657
+ "method": "bearer-token",
658
+ "host": "https://oregon.cloud.databricks.com/api/2.0/delta-sharing/metastores/f53bde37-1e8b-4668-a1e4-e62333110018",
659
+ "bearerToken": "{DELTA_TOKEN}",
660
+ "share": "analytics_share",
661
+ "schema": "default",
662
+ "table": "customer_data"
663
+ }
664
+ }
665
+ ```
666
+
667
+ Set the environment variable:
668
+
669
+ ```bash
670
+ export DELTA_TOKEN=your_delta_share_token_here
671
+ ```
672
+
673
+ ### **Example Configurations**
674
+
675
+ **External Data Share:**
676
+
677
+ ```json
678
+ {
679
+ "$schema": "https://raw.githubusercontent.com/ForzaLabs/remora-public/refs/heads/main/json_schemas/source-schema.json",
680
+ "name": "partner-data",
681
+ "description": "Shared data from business partner",
682
+ "engine": "delta-share",
683
+ "authentication": {
684
+ "method": "bearer-token",
685
+ "host": "https://partner.cloud.databricks.com/api/2.0/delta-sharing/metastores/abc123-def4-5678-90ab-cdef12345678",
686
+ "bearerToken": "{PARTNER_DELTA_TOKEN}",
687
+ "share": "customer_insights",
688
+ "schema": "public",
689
+ "table": "demographic_data"
690
+ },
691
+ "_version": 1
692
+ }
693
+ ```
694
+
695
+ **Internal Data Sharing:**
696
+
697
+ ```json
698
+ {
699
+ "$schema": "https://raw.githubusercontent.com/ForzaLabs/remora-public/refs/heads/main/json_schemas/source-schema.json",
700
+ "name": "internal-analytics",
701
+ "description": "Internal analytics data via Delta Share",
702
+ "engine": "delta-share",
703
+ "authentication": {
704
+ "method": "bearer-token",
705
+ "host": "https://oregon.cloud.databricks.com/api/2.0/delta-sharing/metastores/internal-metastore-id",
706
+ "bearerToken": "{INTERNAL_DELTA_TOKEN}",
707
+ "share": "company_analytics",
708
+ "schema": "processed",
709
+ "table": "quarterly_metrics"
710
+ },
711
+ "_version": 1
712
+ }
713
+ ```
714
+
715
+ ### **Delta Share Features**
716
+
717
+ - **Version control**: Access to historical versions of shared data
718
+ - **Incremental updates**: Efficient processing of data changes
719
+ - **Schema evolution**: Automatic handling of schema changes
720
+ - **Access control**: Token-based security with fine-grained permissions
721
+
722
+ ---
723
+
724
+ ## **HTTP API Sources**
725
+
726
+ HTTP API sources read data from a REST endpoint. The source holds the base `url` and connection settings; a producer using this source sets `fileKey` to the endpoint path and `fileType` to the response format (see the Producers guide).
727
+
728
+ ### **Configuration Schema**
729
+
730
+ ```json
731
+ {
732
+ "$schema": "https://raw.githubusercontent.com/ForzaLabs/remora-public/refs/heads/main/json_schemas/source-schema.json",
733
+ "name": "rest-api",
734
+ "engine": "http-api",
735
+ "authentication": {
736
+ "method": "bearer-token",
737
+ "url": "https://api.example.com",
738
+ "bearerToken": "{API_BEARER_TOKEN}",
739
+ "headers": { "Accept": "application/json" },
740
+ "timeout": 30000
741
+ },
742
+ "_version": 1
743
+ }
744
+ ```
745
+
746
+ ### **Authentication Properties**
747
+
748
+ | Property | Required | Description | Example |
749
+ | --- | --- | --- | --- |
750
+ | `method` | ✅ | `"none"`, `"api-key"`, `"bearer-token"`, or `"username-password"` (HTTP Basic) | `"bearer-token"` |
751
+ | `url` | ✅ | Base URL of the API | `"https://api.example.com"` |
752
+ | `headers` | ❌ | Custom headers sent with every request | `{ "Accept": "application/json" }` |
753
+ | `queryParams` | ❌ | Default query parameters sent with every request | `{ "version": "2" }` |
754
+ | `httpMethod` | ❌ | HTTP method (default `GET`) | `"GET"`, `"POST"` |
755
+ | `timeout` | ❌ | Request timeout in milliseconds (default `30000`) | `30000` |
756
+ | `bearerToken` | ❌ | Token for `bearer-token` | `"{API_BEARER_TOKEN}"` |
757
+ | `apiKey` | ❌ | Key for `api-key` | `"{API_KEY}"` |
758
+ | `apiKeyHeader` | ❌ | Header name for the API key (default `X-API-Key`) | `"X-API-Key"` |
759
+ | `user` / `password` | ❌ | Credentials for `username-password` (HTTP Basic) | `"{API_USER}"` / `"{API_PASSWORD}"` |
760
+
761
+ ### **Example — API-key authentication**
762
+
763
+ ```json
764
+ {
765
+ "engine": "http-api",
766
+ "authentication": {
767
+ "method": "api-key",
768
+ "url": "https://api.example.com",
769
+ "apiKey": "{SERVICE_API_KEY}",
770
+ "apiKeyHeader": "X-API-Key",
771
+ "headers": { "Accept": "application/json" }
772
+ }
773
+ }
774
+ ```
775
+
776
+ ### **Example — Public API (no auth)**
777
+
778
+ ```json
779
+ {
780
+ "engine": "http-api",
781
+ "authentication": {
782
+ "method": "none",
783
+ "url": "https://api.publicapis.org",
784
+ "httpMethod": "GET"
785
+ }
786
+ }
787
+ ```
788
+
789
+ ---
790
+
791
+ ## **Presigned URL Sources**
792
+
793
+ Use this engine when the bucket is reachable only through a URL that something else signs: an API — typically a Lambda behind API Gateway — mints a presigned URL for one file, and Remora transfers against it. Remora needs no AWS credentials at all, because a signed URL authenticates itself.
794
+
795
+ It works in both directions. Referenced by a producer it **downloads**; referenced as a consumer output's `exportDestination` it **uploads**.
796
+
797
+ ### **How it works**
798
+
799
+ Every transfer is two calls:
800
+
801
+ 1. **Mint** — Remora calls your endpoint with the file name and reads the signed URL out of the JSON response.
802
+ 2. **Transfer** — Remora GETs or PUTs that URL directly. No credentials are sent; the signature in the query string is the authentication.
803
+
804
+ The URL is minted immediately before each transfer, per file. That is deliberate: a URL in a config file would expire, and would address only one object — but a consumer that splits its output (`split.maxFileSizeGb`, or `split.by`) writes several files, and each gets its own URL.
805
+
806
+ ### **Configuration Schema**
807
+
808
+ ```json
809
+ {
810
+ "name": "partner_upload",
811
+ "engine": "presigned-url",
812
+ "authentication": {
813
+ "method": "oidc",
814
+ "url": "https://api.example.com/v1/uploads/presign",
815
+ "httpMethod": "POST",
816
+ "fileNameParam": "filename",
817
+ "signedUrlField": "uploadUrl",
818
+ "tokenEndpoint": "https://example.auth.eu-west-1.amazoncognito.com/oauth2/token",
819
+ "clientId": "{PRESIGN_CLIENT_ID}",
820
+ "clientSecret": "{PRESIGN_CLIENT_SECRET}",
821
+ "scope": "uploads/write"
822
+ },
823
+ "_version": 1
824
+ }
825
+ ```
826
+
827
+ ### **Authentication Properties**
828
+
829
+ Everything here configures the **mint call only**. The signed URL that comes back is transferred unauthenticated.
830
+
831
+ | Property | Required | Description |
832
+ | --- | --- | --- |
833
+ | `method` | Yes | How to authenticate to the minting endpoint: `oidc`, `bearer-token`, `api-key`, `username-password` or `none` |
834
+ | `url` | Yes | The minting endpoint |
835
+ | `httpMethod` | No | Method for the mint call. Defaults to `POST` |
836
+ | `fileNameParam` | No | Field carrying the file name — in the JSON body on `POST`/`PUT`/`PATCH`, as a query parameter otherwise. Defaults to `filename` |
837
+ | `signedUrlField` | No | Dot path to the URL in the response, e.g. `data.uploadUrl`. Defaults to `url` |
838
+ | `signedHeadersField` | No | Dot path to an object of headers in the response. Set it when your minter signs headers (see below) |
839
+ | `signedUrlMethod` | No | Method used against the signed URL. Defaults to `GET` when reading and `PUT` when exporting |
840
+ | `headers`, `queryParams`, `timeout` | No | Sent with the mint call, as for `http-api` |
841
+
842
+ An M2M-protected API Gateway is the `oidc` method: set `tokenEndpoint`, `clientId`, `clientSecret` and `scope`, and the token is cached and refreshed shortly before it expires rather than fetched per file.
843
+
844
+ ### **What your endpoint must return**
845
+
846
+ A JSON response holding the URL. Anything else in it is ignored:
847
+
848
+ ```json
849
+ { "uploadUrl": "https://bucket.s3.eu-west-1.amazonaws.com/exports/report.csv?X-Amz-Signature=..." }
850
+ ```
851
+
852
+ If the signature covers headers — a `Content-Type`, any `x-amz-*` — return them too and point `signedHeadersField` at them, because they must be sent back verbatim or S3 answers `403 SignatureDoesNotMatch`:
853
+
854
+ ```json
855
+ { "uploadUrl": "https://...", "headers": { "content-type": "text/csv" } }
856
+ ```
857
+
858
+ ### **Example — reading a file**
859
+
860
+ ```json
861
+ {
862
+ "name": "partner_download",
863
+ "engine": "presigned-url",
864
+ "authentication": {
865
+ "method": "api-key",
866
+ "url": "https://api.example.com/v1/downloads/presign",
867
+ "httpMethod": "GET",
868
+ "apiKey": "{PRESIGN_API_KEY}",
869
+ "apiKeyHeader": "x-api-key",
870
+ "fileNameParam": "key",
871
+ "signedUrlField": "data.url"
872
+ },
873
+ "_version": 1
874
+ }
875
+ ```
876
+
877
+ The producer's `settings.fileKey` is the name sent to the minting endpoint. All the usual file types and compression apply — the file is staged locally and parsed exactly as one from S3 or disk.
878
+
879
+ ### **Limits**
880
+
881
+ - **One file per name, no patterns.** A `%` pattern in `fileKey` is refused: the minting endpoint signs one named object and Remora cannot list the others. Use `aws-s3` or `local` when you need a pattern.
882
+ - **5 GB per object.** A signed `PUT` is a single request, which is S3's limit for one. Set the consumer's `split.maxFileSizeGb` below 5 and the normal rotation ships larger exports as several objects, each with its own URL. Exceeding 5 GB in a *single* object would need presigned multipart, which your endpoint would have to implement as three separate operations.
883
+ - **No resume.** A dropped connection restarts the file, so prefer a smaller `split.maxFileSizeGb` here than you would on `aws-s3`, which uploads in 5 MB parts.
884
+ - **No connection test at startup.** Unlike `http-api`, this engine does not probe on `init`: minting is not a free health check, since each call leaves a live signed URL behind. The first real transfer is the test.
885
+
886
+ ---
887
+
888
+ ## **AWS SQS Sources**
889
+
890
+ SQS sources point at an Amazon SQS queue. They are used to drive consumers from queue messages (see consumer **QUEUE triggers**) rather than to extract producer data.
891
+
892
+ ### **Configuration Schema**
893
+
894
+ ```json
895
+ {
896
+ "$schema": "https://raw.githubusercontent.com/ForzaLabs/remora-public/refs/heads/main/json_schemas/source-schema.json",
897
+ "name": "execute-queue",
898
+ "engine": "aws-sqs",
899
+ "authentication": {
900
+ "method": "access-secret-key",
901
+ "queue": "remora-execute-consumer",
902
+ "accountId": "{AWS_ACCOUNT_ID}",
903
+ "region": "us-east-1",
904
+ "accessKey": "{AWS_ACCESS_KEY_ID}",
905
+ "secretKey": "{AWS_SECRET_ACCESS_KEY}"
906
+ },
907
+ "_version": 1
908
+ }
909
+ ```
910
+
911
+ ### **Authentication Properties**
912
+
913
+ | Property | Required | Description | Example |
914
+ | --- | --- | --- | --- |
915
+ | `method` | ✅ | `"access-secret-key"`, `"iam"`, or `"arn"` | `"access-secret-key"` |
916
+ | `queue` | ✅ | Queue URL, or queue name (combined with `accountId` + `region`) | `"remora-execute-consumer"` |
917
+ | `region` | ✅ | AWS region of the queue | `"us-east-1"` |
918
+ | `accountId` | ❌ | AWS account ID, used to build the queue URL from a queue name | `"{AWS_ACCOUNT_ID}"` |
919
+ | `accessKey` / `secretKey` | ❌ | Static credentials (for `access-secret-key`) | `"{AWS_ACCESS_KEY_ID}"` |
920
+ | `roleArn` | ❌ | Role to assume for `arn` (see [IAM Role Authentication](#iam-role-authentication)) | `"arn:aws:iam::...:role/remora-sqs"` |
921
+
922
+ ### **As the execute-consumer API queue**
923
+
924
+ Pointing the project's `API_QUEUE` setting at an SQS source turns that queue into an alternative to
925
+ the HTTP execute-consumer API: each message names a consumer to run.
926
+
927
+ A message may also carry an `options` object asking the run for extra filters and a record limit,
928
+ on the same terms as the HTTP API — see
929
+ [Run Options](Remora%20-%20Consumers.md) under the consumer's data filtering. The options are
930
+ checked against the named consumer before the run reads anything, and a command carrying an invalid
931
+ one fails without executing.
932
+
933
+ ```json
934
+ {
935
+ "settings": {
936
+ "SQL_MAX_QUERY_ROWS": 10000,
937
+ "API_QUEUE": {
938
+ "source": "execute-queue",
939
+ "deadLetterQueue": "remora-execute-consumer-dlq"
940
+ }
941
+ }
942
+ }
943
+ ```
944
+
945
+ | Property | Required | Description |
946
+ | --- | --- | --- |
947
+ | `source` | ✅ | Name of the `aws-sqs` source to poll |
948
+ | `deadLetterQueue` | ❌ | Queue URL, or queue name resolved against the source's `region` and `accountId`. A failed command is moved here instead of being deleted, so it can be inspected and replayed |
949
+
950
+ ### **Failed commands**
951
+
952
+ Each message on this queue is a **command**: it asks for one consumer run. So it is removed from the
953
+ queue once it has run, whether the run succeeded or failed — a redelivery would be a second
954
+ execution, not a resumption of the first, and the usual failures here (a consumer that no longer
955
+ exists, a malformed payload, a source that is down) are not ones another delivery fixes.
956
+
957
+ That is the opposite of a consumer `QUEUE` trigger, where a failed message *is* retried — see
958
+ [Failed messages](Remora%20-%20Consumers.md) under the consumer QUEUE triggers. There is therefore no
959
+ delivery count to bound here, only a destination: with `deadLetterQueue` set, a failed command is
960
+ copied there (carrying `remoraSourceQueue`, `remoraSourceMessageId` and `remoraReceiveCount` as
961
+ message attributes) and then deleted; without one, it is deleted outright and the only trace is the
962
+ worker's log. Configuring one is worth it for anything that has to be diagnosed or replayed.
963
+
964
+ ---
965
+
966
+
967
+ ## **Common Configuration Patterns**
968
+
969
+ ### **Environment Variable Usage**
970
+
971
+ **Recommended Pattern:**
972
+
973
+ ```json
974
+ {
975
+ "authentication": {
976
+ "accessKey": "{AWS_ACCESS_KEY_ID}",
977
+ "secretKey": "{AWS_SECRET_ACCESS_KEY}",
978
+ "sessionToken": "{AWS_SESSION_TOKEN}"
979
+ }
980
+ }
981
+ ```
982
+
983
+ **Environment Setup:**
984
+
985
+ ```bash
986
+ # AWS Credentialsexport AWS_ACCESS_KEY_ID=AKIA...
987
+ export AWS_SECRET_ACCESS_KEY=wJa...
988
+ export AWS_SESSION_TOKEN=IQoJ...
989
+
990
+ # Delta Shareexport DELTA_TOKEN=dapi...
991
+
992
+ # Custom Variablesexport PROD_DATABASE_HOST=prod-db.company.com
993
+ export DEV_BUCKET_NAME=dev-data-bucket
994
+ ```
995
+
996
+ ### **Multi-Environment Configuration**
997
+
998
+ **Development:**
999
+
1000
+ ```json
1001
+ {
1002
+ "name": "dev-data",
1003
+ "description": "Development environment data source",
1004
+ "engine": "local",
1005
+ "authentication": {
1006
+ "method": "implicit",
1007
+ "path": "./dev-data"
1008
+ }
1009
+ }
1010
+ ```
1011
+
1012
+ **Staging:**
1013
+
1014
+ ```json
1015
+ {
1016
+ "name": "staging-s3",
1017
+ "description": "Staging environment S3 bucket",
1018
+ "engine": "aws-s3",
1019
+ "authentication": {
1020
+ "method": "access-secret-key",
1021
+ "region": "us-east-1",
1022
+ "accessKey": "{STAGING_ACCESS_KEY}",
1023
+ "secretKey": "{STAGING_SECRET_KEY}",
1024
+ "bucket": "staging-data-bucket"
1025
+ }
1026
+ }
1027
+ ```
1028
+
1029
+ **Production:**
1030
+
1031
+ ```json
1032
+ {
1033
+ "name": "prod-warehouse",
1034
+ "description": "Production data warehouse",
1035
+ "engine": "aws-redshift",
1036
+ "authentication": {
1037
+ "method": "access-secret-key",
1038
+ "region": "us-east-1",
1039
+ "accessKey": "{PROD_ACCESS_KEY}",
1040
+ "secretKey": "{PROD_SECRET_KEY}",
1041
+ "database": "production_db",
1042
+ "workgroup": "production-workgroup"
1043
+ }
1044
+ }
1045
+ ```
1046
+
1047
+ ---
1048
+
1049
+ ## **Validation and Testing**
1050
+
1051
+ ### **Configuration Validation**
1052
+
1053
+ Use the Remora CLI to validate your source configurations:
1054
+
1055
+ ```bash
1056
+ # Compile & validate every resource configuration in the project
1057
+ # (includes source checks, e.g. required AWS credential fields per method)
1058
+ remora compile
1059
+ ```
1060
+
1061
+ ### **Connection Testing**
1062
+
1063
+ There is no standalone source-connectivity command. To exercise a source end-to-end, run a producer that uses it and inspect the extracted rows:
1064
+
1065
+ ```bash
1066
+ # Read a few records through a producer that uses the source
1067
+ remora sample my-producer -s 10
1068
+ ```
1069
+
1070
+ If the source is misconfigured (bad credentials, missing bucket, expired token, …) the command fails with the underlying connection error.
1071
+
1072
+ ### **Common Validation Errors**
1073
+
1074
+ | Error | Cause | Solution |
1075
+ | --- | --- | --- |
1076
+ | `Invalid AWS credentials` | Wrong access keys | Check environment variables |
1077
+ | `Bucket not found` | Incorrect bucket name | Verify bucket exists and region |
1078
+ | `Permission denied` | Insufficient IAM permissions | Review and update IAM policies |
1079
+ | `Invalid workgroup` | Wrong Redshift workgroup | Check workgroup name and region |
1080
+ | `Invalid token` | Expired Delta Share token | Refresh authentication token |
1081
+
1082
+ ---
1083
+
1084
+ ## **Performance Optimization**
1085
+
1086
+ ### **Memory Management**
1087
+
1088
+ - **File Processing**: Large files are streamed to minimize memory usage
1089
+ - **Query Results**: Limited by `SQL_MAX_QUERY_ROWS` setting
1090
+ - **Parallel Processing**: Remora automatically multithread large file for computing optimization
1091
+
1092
+ ### **Connection Pooling**
1093
+
1094
+ - **Reuse connections** across multiple operations
1095
+ - **Connection warming** during initialization
1096
+ - **Automatic retry** for transient failures
1097
+
1098
+ ### **Best Practices**
1099
+
1100
+ 1. **Use appropriate source types** for your data storage pattern
1101
+ 2. **Configure memory limits** based on available system resources
1102
+ 3. **Implement proper error handling** in your data pipelines
1103
+ 4. **Monitor connection health** in production environments
1104
+ 5. **Use environment variables** for sensitive configuration values
1105
+
1106
+ ---
1107
+
1108
+ ## **Troubleshooting**
1109
+
1110
+ ### **Common Issues**
1111
+
1112
+ **Connection Timeouts:**
1113
+
1114
+ - Increase `DEFAULT_TIMEOUT_SECONDS` in project configuration
1115
+ - Check network connectivity to source systems
1116
+ - Verify firewall and security group settings
1117
+
1118
+ **Authentication Failures:**
1119
+
1120
+ - Verify environment variables are set correctly
1121
+ - Check IAM permissions for AWS sources
1122
+ - Ensure tokens are not expired for Delta Share
1123
+
1124
+ **File Not Found Errors:**
1125
+
1126
+ - Verify file paths exist for local sources
1127
+ - Check S3 object keys and bucket permissions
1128
+ - Ensure proper case sensitivity in file names
1129
+
1130
+ ### **Debug Mode**
1131
+
1132
+ Enable debug logging in your project configuration:
1133
+
1134
+ ```json
1135
+ {
1136
+ "settings": {
1137
+ "LOG_LEVEL": "DEBUG",
1138
+ "DEBUG_MODE": true}
1139
+ }
1140
+
1141
+ ```
1142
+
1143
+ ### **Support Resources**
1144
+
1145
+ - **Schema Validation**: All configurations are validated against JSON schemas
1146
+ - **CLI Help**: Run `remora --help` for command documentation
1147
+ - **Error Messages**: Include specific guidance for resolution
1148
+ - **Connection errors**: Run a producer with `remora sample <producer>` to surface source connection issues
1149
+
1150
+ ---