or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

authorization-security.mdconfiguration-management.mddatabase-connection.mdentity-models.mdindex.mdmetadata-management.mdnative-operations.mdscala-functional-api.md

configuration-management.mddocs/

0

# Configuration Management

1

2

The configuration management system provides centralized configuration for database connections, authorization settings, operational parameters, and LakeSoul-specific options. The system supports both global and local configuration with environment variable and system property support.

3

4

## Capabilities

5

6

### GlobalConfig Class

7

8

Singleton configuration manager for system-wide settings, particularly authorization configuration.

9

10

```java { .api }

11

/**

12

* Global configuration management for LakeSoul system

13

* Singleton pattern with database-backed configuration storage

14

*/

15

public class GlobalConfig {

16

// Configuration keys

17

public static final String authZEnabledKey = "lakesoul.authz.enabled";

18

public static final boolean authZEnabledDefault = false;

19

public static final String authZCasbinModelKey = "lakesoul.authz.casbin.model";

20

21

/**

22

* Get singleton GlobalConfig instance

23

* Loads configuration from database on first access

24

* @return GlobalConfig singleton instance

25

*/

26

public static synchronized GlobalConfig get();

27

28

/**

29

* Check if authorization is enabled

30

* @return boolean true if authorization is enabled, false otherwise

31

*/

32

public boolean isAuthZEnabled();

33

34

/**

35

* Set authorization enabled status

36

* @param enabled true to enable authorization, false to disable

37

*/

38

public void setAuthZEnabled(boolean enabled);

39

40

/**

41

* Get Casbin model configuration

42

* @return String path to Casbin model file or model content

43

*/

44

public String getAuthZCasbinModel();

45

}

46

```

47

48

### DBConfig Class

49

50

Abstract class containing database and LakeSoul operational constants and configuration keys.

51

52

```java { .api }

53

/**

54

* Configuration constants for LakeSoul database operations

55

* Contains operational parameters and formatting constants

56

*/

57

public abstract class DBConfig {

58

// Namespace and partitioning constants

59

public static final String LAKESOUL_DEFAULT_NAMESPACE = "default";

60

public static final String LAKESOUL_NAMESPACE_LEVEL_SPLITTER = ".";

61

public static final String LAKESOUL_NULL_STRING = "__L@KE$OUL_NULL__";

62

public static final String LAKESOUL_PARTITION_SPLITTER_OF_RANGE_AND_HASH = ";";

63

public static final String LAKESOUL_RANGE_PARTITION_SPLITTER = ",";

64

public static final String LAKESOUL_NON_PARTITION_TABLE_PART_DESC = "-5";

65

66

// Operational constants

67

public static final int MAX_COMMIT_ATTEMPTS = 3;

68

public static final int DEFAULT_CONNECTION_TIMEOUT = 30000;

69

public static final int DEFAULT_QUERY_TIMEOUT = 60000;

70

71

// Table metadata property keys

72

public static final String LAKESOUL_TABLE_PROPERTY_PREFIX = "lakesoul.";

73

public static final String LAKESOUL_HASH_PARTITION_NUM = "lakesoul.hash.partition.num";

74

public static final String LAKESOUL_RANGE_PARTITION_COLUMNS = "lakesoul.range.partition.columns";

75

}

76

```

77

78

### TableInfoProperty Constants

79

80

Nested class in DBConfig containing table-specific property constants.

81

82

```java { .api }

83

/**

84

* Table information property constants

85

* Keys for table metadata properties stored as JSON

86

*/

87

public static class TableInfoProperty {

88

/** Hash bucket number for hash partitioning */

89

public static final String HASH_BUCKET_NUM = "hashBucketNum";

90

91

/** Dropped column names (comma-separated) */

92

public static final String DROPPED_COLUMN = "droppedColumn";

93

94

/** Delimiter for dropped column names */

95

public static final String DROPPED_COLUMN_SPLITTER = ",";

96

97

/** Timestamp of last schema change */

98

public static final String LAST_TABLE_SCHEMA_CHANGE_TIME = "last_schema_change_time";

99

100

/** Table format specification (parquet, delta, etc.) */

101

public static final String TABLE_FORMAT = "table.format";

102

103

/** Compression codec for data files */

104

public static final String COMPRESSION_CODEC = "compression.codec";

105

106

/** Data retention period in days */

107

public static final String RETENTION_DAYS = "retention.days";

108

109

/** Table owner information */

110

public static final String TABLE_OWNER = "table.owner";

111

112

/** Table creation timestamp */

113

public static final String CREATION_TIME = "creation.time";

114

115

/** Last access timestamp */

116

public static final String LAST_ACCESS_TIME = "last.access.time";

117

}

118

```

119

120

### LakeSoulOptions (Scala Object)

121

122

Scala object containing configuration constants and options for LakeSoul operations.

123

124

```scala { .api }

125

/**

126

* Configuration constants and options for LakeSoul operations

127

* Centralized location for all LakeSoul-specific configuration keys

128

*/

129

object LakeSoulOptions {

130

// Write operation options

131

val REPLACE_WHERE_OPTION = "replaceWhere"

132

val MERGE_SCHEMA_OPTION = "mergeSchema"

133

val OVERWRITE_SCHEMA_OPTION = "overwriteSchema"

134

val UPSERT_OPTION = "upsert"

135

val DELETE_WHERE_OPTION = "deleteWhere"

136

137

// Partitioning options

138

val PARTITION_BY = "__partition_columns"

139

val RANGE_PARTITIONS = "rangePartitions"

140

val HASH_PARTITIONS = "hashPartitions"

141

val HASH_BUCKET_NUM = "hashBucketNum"

142

val DYNAMIC_PARTITION = "dynamicPartition"

143

144

// Table naming options

145

val SHORT_TABLE_NAME = "shortTableName"

146

val TABLE_PATH = "tablePath"

147

val TABLE_NAMESPACE = "tableNamespace"

148

149

// Read operation options

150

val READ_TYPE = "readtype"

151

val START_VERSION = "startVersion"

152

val END_VERSION = "endVersion"

153

val START_TIMESTAMP = "startTimestamp"

154

val END_TIMESTAMP = "endTimestamp"

155

val INCREMENTAL_PARTITION_DESC = "incrementalPartitionDesc"

156

157

// Data format options

158

val DATA_FORMAT = "dataFormat"

159

val COMPRESSION = "compression"

160

val FILE_SIZE_THRESHOLD = "fileSizeThreshold"

161

val ROW_GROUP_SIZE = "rowGroupSize"

162

val DICTIONARY_ENCODING = "dictionaryEncoding"

163

164

// Performance tuning options

165

val BATCH_SIZE = "batchSize"

166

val PARALLELISM = "parallelism"

167

val MEMORY_FRACTION = "memoryFraction"

168

val SPILL_THRESHOLD = "spillThreshold"

169

170

// CDC (Change Data Capture) options

171

val CDC_CHANGE_COLUMN = "cdcChangeColumn"

172

val CDC_PARTITION_COLUMN = "cdcPartitionColumn"

173

val CDC_START_TIMESTAMP = "cdcStartTimestamp"

174

val CDC_END_TIMESTAMP = "cdcEndTimestamp"

175

}

176

```

177

178

### ReadType Constants

179

180

Nested object in LakeSoulOptions defining read operation types.

181

182

```scala { .api }

183

/**

184

* Read operation type constants

185

* Defines different modes for reading LakeSoul tables

186

*/

187

object ReadType {

188

/** Full table read including all historical data */

189

val FULL_READ = "fullread"

190

191

/** Snapshot read at specific point in time */

192

val SNAPSHOT_READ = "snapshot"

193

194

/** Incremental read of changes between time ranges */

195

val INCREMENTAL_READ = "incremental"

196

197

/** Stream read for continuous processing */

198

val STREAM_READ = "stream"

199

200

/** Change data capture read */

201

val CDC_READ = "cdc"

202

}

203

```

204

205

### Database Configuration

206

207

Database connection configuration through DBUtil and DataBaseProperty classes.

208

209

```java { .api }

210

/**

211

* Utility class for database configuration management

212

* Handles configuration loading and database connection parameters

213

*/

214

public class DBUtil {

215

// Database connection configuration keys

216

public static final String urlKey = "lakesoul.pg.url";

217

public static final String usernameKey = "lakesoul.pg.username";

218

public static final String passwordKey = "lakesoul.pg.password";

219

public static final String driverKey = "lakesoul.pg.driver";

220

public static final String domainKey = "lakesoul.current.domain";

221

222

// Connection pool configuration keys

223

public static final String maxPoolSizeKey = "lakesoul.pg.pool.maxSize";

224

public static final String minPoolSizeKey = "lakesoul.pg.pool.minSize";

225

public static final String connectionTimeoutKey = "lakesoul.pg.pool.connectionTimeout";

226

public static final String idleTimeoutKey = "lakesoul.pg.pool.idleTimeout";

227

public static final String maxLifetimeKey = "lakesoul.pg.pool.maxLifetime";

228

229

// Default values

230

public static final String DEFAULT_DRIVER = "org.postgresql.Driver";

231

public static final String DEFAULT_DOMAIN = "public";

232

public static final int DEFAULT_MAX_POOL_SIZE = 10;

233

public static final int DEFAULT_MIN_POOL_SIZE = 2;

234

public static final long DEFAULT_CONNECTION_TIMEOUT = 30000L;

235

public static final long DEFAULT_IDLE_TIMEOUT = 600000L;

236

public static final long DEFAULT_MAX_LIFETIME = 1800000L;

237

238

/**

239

* Get database connection information from configuration

240

* Loads from system properties, environment variables, or configuration files

241

* @return DataBaseProperty object with connection details

242

*/

243

public static DataBaseProperty getDBInfo();

244

245

/**

246

* Fill HikariCP configuration with connection parameters

247

* @param config HikariConfig object to populate

248

*/

249

public static void fillDataSourceConfig(HikariConfig config);

250

251

/**

252

* Convert Java UUID to protobuf UUID

253

* @param uuid Java UUID instance

254

* @return Uuid protobuf UUID representation

255

*/

256

public static Uuid toProtoUuid(UUID uuid);

257

258

/**

259

* Convert protobuf UUID to Java UUID

260

* @param uuid Protobuf UUID instance

261

* @return UUID Java UUID representation

262

*/

263

public static UUID toJavaUUID(Uuid uuid);

264

265

/**

266

* Get configuration value with fallback to default

267

* @param key Configuration key

268

* @param defaultValue Default value if key not found

269

* @return String configuration value

270

*/

271

public static String getConfigValue(String key, String defaultValue);

272

273

/**

274

* Get boolean configuration value

275

* @param key Configuration key

276

* @param defaultValue Default value if key not found

277

* @return boolean configuration value

278

*/

279

public static boolean getBooleanConfigValue(String key, boolean defaultValue);

280

281

/**

282

* Get integer configuration value

283

* @param key Configuration key

284

* @param defaultValue Default value if key not found

285

* @return int configuration value

286

*/

287

public static int getIntConfigValue(String key, int defaultValue);

288

289

/**

290

* Get long configuration value

291

* @param key Configuration key

292

* @param defaultValue Default value if key not found

293

* @return long configuration value

294

*/

295

public static long getLongConfigValue(String key, long defaultValue);

296

}

297

298

/**

299

* Data transfer object for database connection properties

300

* Contains all necessary information for establishing database connections

301

*/

302

public class DataBaseProperty {

303

/**

304

* Get JDBC driver class name

305

* @return String driver class name

306

*/

307

public String getDriver();

308

309

/**

310

* Set JDBC driver class name

311

* @param driver Driver class name

312

*/

313

public void setDriver(String driver);

314

315

/**

316

* Get database connection URL

317

* @return String JDBC connection URL

318

*/

319

public String getUrl();

320

321

/**

322

* Set database connection URL

323

* @param url JDBC connection URL

324

*/

325

public void setUrl(String url);

326

327

/**

328

* Get database username

329

* @return String username for authentication

330

*/

331

public String getUsername();

332

333

/**

334

* Set database username

335

* @param username Username for authentication

336

*/

337

public void setUsername(String username);

338

339

/**

340

* Get database password

341

* @return String password for authentication

342

*/

343

public String getPassword();

344

345

/**

346

* Set database password

347

* @param password Password for authentication

348

*/

349

public void setPassword(String password);

350

351

/**

352

* Get database name

353

* @return String target database name

354

*/

355

public String getDbName();

356

357

/**

358

* Set database name

359

* @param dbName Target database name

360

*/

361

public void setDbName(String dbName);

362

363

/**

364

* Get database host

365

* @return String hostname or IP address

366

*/

367

public String getHost();

368

369

/**

370

* Set database host

371

* @param host Hostname or IP address

372

*/

373

public void setHost(String host);

374

375

/**

376

* Get database port

377

* @return int port number

378

*/

379

public int getPort();

380

381

/**

382

* Set database port

383

* @param port Port number

384

*/

385

public void setPort(int port);

386

387

/**

388

* Get maximum commit attempt count

389

* @return int maximum retry attempts for commits

390

*/

391

public int getMaxCommitAttempt();

392

393

/**

394

* Set maximum commit attempt count

395

* @param maxCommitAttempt Maximum retry attempts

396

*/

397

public void setMaxCommitAttempt(int maxCommitAttempt);

398

399

/**

400

* String representation of database properties

401

* Password is masked for security

402

* @return String formatted connection details

403

*/

404

public String toString();

405

}

406

```

407

408

**Usage Examples:**

409

410

```java

411

import com.dmetasoul.lakesoul.meta.*;

412

import com.dmetasoul.lakesoul.meta.LakeSoulOptions;

413

import java.util.Properties;

414

415

public class ConfigurationExample {

416

417

public void globalConfigurationExample() {

418

// Get global configuration

419

GlobalConfig globalConfig = GlobalConfig.get();

420

421

// Check authorization configuration

422

if (globalConfig.isAuthZEnabled()) {

423

System.out.println("Authorization enabled");

424

System.out.println("Casbin model: " + globalConfig.getAuthZCasbinModel());

425

426

// Initialize authorization system

427

initializeAuthorization();

428

} else {

429

System.out.println("Authorization disabled");

430

}

431

432

// Programmatically enable authorization

433

globalConfig.setAuthZEnabled(true);

434

System.out.println("Authorization now enabled: " + globalConfig.isAuthZEnabled());

435

}

436

437

public void databaseConfigurationExample() {

438

// Get database configuration

439

DataBaseProperty dbProps = DBUtil.getDBInfo();

440

441

System.out.println("Database Configuration:");

442

System.out.println(" Driver: " + dbProps.getDriver());

443

System.out.println(" URL: " + dbProps.getUrl());

444

System.out.println(" Host: " + dbProps.getHost());

445

System.out.println(" Port: " + dbProps.getPort());

446

System.out.println(" Database: " + dbProps.getDbName());

447

System.out.println(" Username: " + dbProps.getUsername());

448

System.out.println(" Max Commit Attempts: " + dbProps.getMaxCommitAttempt());

449

450

// Create custom database configuration

451

DataBaseProperty customProps = new DataBaseProperty();

452

customProps.setDriver("org.postgresql.Driver");

453

customProps.setHost("localhost");

454

customProps.setPort(5432);

455

customProps.setDbName("lakesoul_prod");

456

customProps.setUsername("lakesoul_user");

457

customProps.setPassword("secure_password");

458

customProps.setMaxCommitAttempt(5);

459

460

// Build URL from components

461

String url = String.format("jdbc:postgresql://%s:%d/%s",

462

customProps.getHost(),

463

customProps.getPort(),

464

customProps.getDbName());

465

customProps.setUrl(url);

466

467

System.out.println("Custom configuration: " + customProps.toString());

468

}

469

470

public void lakeSoulOptionsExample() {

471

// Create configuration map for LakeSoul operations

472

Map<String, String> options = new HashMap<>();

473

474

// Write operation configuration

475

options.put(LakeSoulOptions.MERGE_SCHEMA_OPTION(), "true");

476

options.put(LakeSoulOptions.REPLACE_WHERE_OPTION(), "date >= '2023-01-01'");

477

options.put(LakeSoulOptions.UPSERT_OPTION(), "true");

478

479

// Partitioning configuration

480

options.put(LakeSoulOptions.RANGE_PARTITIONS(), "date,region");

481

options.put(LakeSoulOptions.HASH_PARTITIONS(), "user_id");

482

options.put(LakeSoulOptions.HASH_BUCKET_NUM(), "16");

483

484

// Table configuration

485

options.put(LakeSoulOptions.SHORT_TABLE_NAME(), "user_events");

486

options.put(LakeSoulOptions.TABLE_NAMESPACE(), "analytics");

487

488

// Read operation configuration

489

options.put(LakeSoulOptions.READ_TYPE(), LakeSoulOptions.ReadType.INCREMENTAL_READ());

490

options.put(LakeSoulOptions.START_TIMESTAMP(), "1672531200000"); // 2023-01-01

491

options.put(LakeSoulOptions.END_TIMESTAMP(), "1672617600000"); // 2023-01-02

492

493

// Performance tuning

494

options.put(LakeSoulOptions.BATCH_SIZE(), "10000");

495

options.put(LakeSoulOptions.PARALLELISM(), "8");

496

options.put(LakeSoulOptions.MEMORY_FRACTION(), "0.8");

497

498

// Data format options

499

options.put(LakeSoulOptions.DATA_FORMAT(), "parquet");

500

options.put(LakeSoulOptions.COMPRESSION(), "snappy");

501

options.put(LakeSoulOptions.FILE_SIZE_THRESHOLD(), "134217728"); // 128MB

502

503

System.out.println("LakeSoul options configured: " + options.size() + " settings");

504

505

// Use options in operations

506

processWithOptions(options);

507

}

508

509

public void tablePropertiesExample() {

510

// Create table properties using DBConfig constants

511

JSONObject tableProps = new JSONObject();

512

513

// Hash partitioning configuration

514

tableProps.put(DBConfig.TableInfoProperty.HASH_BUCKET_NUM, "32");

515

516

// Schema evolution settings

517

tableProps.put(DBConfig.TableInfoProperty.LAST_TABLE_SCHEMA_CHANGE_TIME,

518

String.valueOf(System.currentTimeMillis()));

519

520

// Data format and compression

521

tableProps.put(DBConfig.TableInfoProperty.TABLE_FORMAT, "parquet");

522

tableProps.put(DBConfig.TableInfoProperty.COMPRESSION_CODEC, "zstd");

523

524

// Retention and ownership

525

tableProps.put(DBConfig.TableInfoProperty.RETENTION_DAYS, "90");

526

tableProps.put(DBConfig.TableInfoProperty.TABLE_OWNER, "data_team");

527

tableProps.put(DBConfig.TableInfoProperty.CREATION_TIME,

528

String.valueOf(System.currentTimeMillis()));

529

530

// Dropped columns (if any)

531

List<String> droppedColumns = Arrays.asList("old_column1", "deprecated_field");

532

tableProps.put(DBConfig.TableInfoProperty.DROPPED_COLUMN,

533

String.join(DBConfig.TableInfoProperty.DROPPED_COLUMN_SPLITTER, droppedColumns));

534

535

System.out.println("Table properties: " + tableProps.toJSONString());

536

537

// Use in table creation

538

createTableWithProperties("table_001", tableProps);

539

}

540

541

public void environmentBasedConfigurationExample() {

542

// Get configuration from various sources with fallbacks

543

544

// Database configuration with environment fallbacks

545

String dbUrl = DBUtil.getConfigValue(DBUtil.urlKey,

546

System.getenv().getOrDefault("LAKESOUL_PG_URL",

547

"jdbc:postgresql://localhost:5432/lakesoul"));

548

549

String dbUser = DBUtil.getConfigValue(DBUtil.usernameKey,

550

System.getenv().getOrDefault("LAKESOUL_PG_USERNAME", "lakesoul"));

551

552

String dbPassword = DBUtil.getConfigValue(DBUtil.passwordKey,

553

System.getenv().getOrDefault("LAKESOUL_PG_PASSWORD", "lakesoul"));

554

555

String domain = DBUtil.getConfigValue(DBUtil.domainKey,

556

System.getenv().getOrDefault("LAKESOUL_DOMAIN", "public"));

557

558

// Connection pool configuration

559

int maxPoolSize = DBUtil.getIntConfigValue(DBUtil.maxPoolSizeKey,

560

Integer.parseInt(System.getenv().getOrDefault("LAKESOUL_PG_POOL_MAX_SIZE", "10")));

561

562

long connectionTimeout = DBUtil.getLongConfigValue(DBUtil.connectionTimeoutKey,

563

Long.parseLong(System.getenv().getOrDefault("LAKESOUL_PG_CONNECTION_TIMEOUT", "30000")));

564

565

// Authorization configuration

566

boolean authEnabled = DBUtil.getBooleanConfigValue(GlobalConfig.authZEnabledKey,

567

Boolean.parseBoolean(System.getenv().getOrDefault("LAKESOUL_AUTHZ_ENABLED", "false")));

568

569

System.out.println("Configuration loaded from environment:");

570

System.out.println(" DB URL: " + maskUrl(dbUrl));

571

System.out.println(" DB User: " + dbUser);

572

System.out.println(" Domain: " + domain);

573

System.out.println(" Max Pool Size: " + maxPoolSize);

574

System.out.println(" Connection Timeout: " + connectionTimeout + "ms");

575

System.out.println(" Authorization Enabled: " + authEnabled);

576

}

577

578

public void configurationValidationExample() {

579

try {

580

// Validate database configuration

581

DataBaseProperty dbProps = DBUtil.getDBInfo();

582

validateDatabaseConfig(dbProps);

583

584

// Validate global configuration

585

GlobalConfig globalConfig = GlobalConfig.get();

586

validateGlobalConfig(globalConfig);

587

588

System.out.println("Configuration validation passed");

589

590

} catch (IllegalArgumentException e) {

591

System.err.println("Configuration validation failed: " + e.getMessage());

592

System.exit(1);

593

}

594

}

595

596

private void validateDatabaseConfig(DataBaseProperty dbProps) {

597

if (dbProps.getUrl() == null || dbProps.getUrl().isEmpty()) {

598

throw new IllegalArgumentException("Database URL is required");

599

}

600

601

if (dbProps.getUsername() == null || dbProps.getUsername().isEmpty()) {

602

throw new IllegalArgumentException("Database username is required");

603

}

604

605

if (dbProps.getPassword() == null || dbProps.getPassword().isEmpty()) {

606

throw new IllegalArgumentException("Database password is required");

607

}

608

609

if (dbProps.getPort() <= 0 || dbProps.getPort() > 65535) {

610

throw new IllegalArgumentException("Invalid database port: " + dbProps.getPort());

611

}

612

613

if (dbProps.getMaxCommitAttempt() <= 0) {

614

throw new IllegalArgumentException("Max commit attempts must be positive");

615

}

616

}

617

618

private void validateGlobalConfig(GlobalConfig config) {

619

if (config.isAuthZEnabled()) {

620

String casbinModel = config.getAuthZCasbinModel();

621

if (casbinModel == null || casbinModel.isEmpty()) {

622

throw new IllegalArgumentException("Casbin model is required when authorization is enabled");

623

}

624

}

625

}

626

627

private String maskUrl(String url) {

628

// Mask password in URL for logging

629

if (url != null && url.contains("://")) {

630

return url.replaceAll("://[^:]*:[^@]*@", "://***:***@");

631

}

632

return url;

633

}

634

635

private void initializeAuthorization() {

636

// Implementation for authorization setup

637

}

638

639

private void processWithOptions(Map<String, String> options) {

640

// Implementation using LakeSoul options

641

}

642

643

private void createTableWithProperties(String tableId, JSONObject properties) {

644

// Implementation for table creation

645

}

646

}

647

```

648

649

**Configuration Files:**

650

651

**System Properties (application.properties):**

652

```properties

653

# Database connection

654

lakesoul.pg.url=jdbc:postgresql://localhost:5432/lakesoul

655

lakesoul.pg.username=lakesoul_user

656

lakesoul.pg.password=lakesoul_password

657

lakesoul.pg.driver=org.postgresql.Driver

658

659

# Connection pool settings

660

lakesoul.pg.pool.maxSize=20

661

lakesoul.pg.pool.minSize=5

662

lakesoul.pg.pool.connectionTimeout=30000

663

lakesoul.pg.pool.idleTimeout=600000

664

lakesoul.pg.pool.maxLifetime=1800000

665

666

# Security domain

667

lakesoul.current.domain=production

668

669

# Authorization settings

670

lakesoul.authz.enabled=true

671

lakesoul.authz.casbin.model=/config/rbac_model.conf

672

lakesoul.authz.casbin.policy=/config/policy.csv

673

674

# Native operations

675

lakesoul.native.metadata.query.enabled=true

676

lakesoul.native.metadata.update.enabled=true

677

lakesoul.native.metadata.max.retry.attempts=3

678

```

679

680

**Environment Variables:**

681

```bash

682

# Database configuration

683

export LAKESOUL_PG_URL="jdbc:postgresql://prod-db:5432/lakesoul"

684

export LAKESOUL_PG_USERNAME="lakesoul_prod"

685

export LAKESOUL_PG_PASSWORD="secure_prod_password"

686

687

# Security

688

export LAKESOUL_DOMAIN="production"

689

export LAKESOUL_AUTHZ_ENABLED="true"

690

691

# Performance tuning

692

export LAKESOUL_PG_POOL_MAX_SIZE="50"

693

export LAKESOUL_PG_POOL_MIN_SIZE="10"

694

```

695

696

**Configuration Priority:**

697

698

The configuration system follows this priority order (highest to lowest):

699

700

1. **System Properties** (`-Dlakesoul.pg.url=...`)

701

2. **Environment Variables** (`LAKESOUL_PG_URL`)

702

3. **Configuration Files** (`application.properties`, `lakesoul.conf`)

703

4. **Database Configuration** (global_config table)

704

5. **Default Values** (built-in defaults)

705

706

**Thread Safety:**

707

708

Configuration management is designed for concurrent access:

709

710

- **Singleton Initialization**: Thread-safe lazy initialization with double-checked locking

711

- **Immutable Configuration**: Configuration objects are immutable after creation

712

- **Read-Only Access**: Most configuration access is read-only after initialization

713

- **Global State**: Global configuration changes are synchronized

714

- **Environment Independence**: No shared mutable state between threads