Configuration

In addition to configuring your database connections in application.conf you can also set some global options in this file or through system properties (see the Typesafe Config documentation for details). These are the available options and their default values as defined in Slick’s own reference.conf:

source# These settings are read by slick.util.SlickConfig
slick {
  # Use ANSI color sequences in tree dumps (as used in log messages and
  # exceptions of type SlickTreeException).
  ansiDump = false

  # Use Unicode box characters in tree and table dumps (as used in log
  # messages). If this option is not enabled, ASCII approximations are used
  # instead.
  unicodeDump = false

  # Dump individual "Select" and "Ref" nodes instead of combining them into a
  # single "Path" element when creating a tree dump (as used in log messages
  # and exceptions of type SlickTreeException).
  dumpPaths = false

  # Use multi-line, indented formatting for SQL statements. If not enabled,
  # statements are generated without any linebreaks or indentation. This
  # option applies to all generated statements (but not to the Plain SQL API).
  sqlIndent = false

  # Verify types after each query compiler phase. This is useful for debugging
  # the query compiler but should generally not be enabled in production
  # environments because it makes query compilation considerably slower.
  verifyTypes = false

  # Detect unnecessary rebuilding of the AST after every query compiler phase.
  # This is useful for debugging the query compiler. Query compilation
  # performance is negatively affected by this if phase logging is enabled.
  detectRebuild = false
}

# Profile-specific settings for MySQLProfile
slick.jdbc.MySQLProfile {
  # The default SQL type for strings without an explicit size limit.
  # When set to null / undefined, pick "TEXT" where possible, otherwise fall back
  # to "VARCHAR(254)"
  defaultStringType = null
}

# Profile-specific settings for SQLServerProfile
slick.jdbc.SQLServerProfile {
  # The default SQL type for strings without an explicit size limit.
  # When set to null / undefined, pick "TEXT" where possible, otherwise fall back to "VARCHAR(254)"
  defaultStringType = null
}

Logging

Slick uses SLF4J for logging. How to configure loggers and appenders depends on the actual logging framework that you use in your application. The following Logback configuration is used internally for testing and debugging of Slick. It contains a list of all loggers that are used by Slick for debug output:

source<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>*** \(%logger{30}\)%green(%X{debugId}) %msg%n</pattern>
        </encoder>
    </appender>
    <root level="${log.root:-info}">
        <appender-ref ref="STDOUT" />
    </root>
    <logger name="slick.basic.BasicBackend.action"          level="${log.action:-info}" />
    <logger name="slick.basic.BasicBackend.stream"          level="${log.stream:-info}" />
    <logger name="slick.compiler"                           level="${log.qcomp:-info}" />
    <logger name="slick.compiler.QueryCompiler"             level="${log.qcomp.phases:-inherited}" />
    <logger name="slick.compiler.QueryCompilerBenchmark"    level="${log.qcomp.bench:-inherited}" />
    <logger name="slick.compiler.Inline"                    level="${log.qcomp.inline:-inherited}" />
    <logger name="slick.compiler.AssignUniqueSymbols"       level="${log.qcomp.assignUniqueSymbols:-inherited}" />
    <logger name="slick.compiler.InferTypes"                level="${log.qcomp.inferTypes:-inherited}" />
    <logger name="slick.compiler.ExpandTables"              level="${log.qcomp.expandTables:-inherited}" />
    <logger name="slick.compiler.EmulateOuterJoins"         level="${log.qcomp.emulateOuterJoins:-inherited}" />
    <logger name="slick.compiler.ForceOuterBinds"           level="${log.qcomp.forceOuterBinds:-inherited}" />
    <logger name="slick.compiler.RemoveMappedTypes"         level="${log.qcomp.removeMappedTypes:-inherited}" />
    <logger name="slick.compiler.CreateResultSetMapping"    level="${log.qcomp.createResultSetMapping:-inherited}" />
    <logger name="slick.compiler.ExpandSums"                level="${log.qcomp.expandSums:-inherited}" />
    <logger name="slick.compiler.ExpandRecords"             level="${log.qcomp.expandRecords:-inherited}" />
    <logger name="slick.compiler.ExpandConditionals"        level="${log.qcomp.expandConditionals:-inherited}" />
    <logger name="slick.compiler.FlattenProjections"        level="${log.qcomp.flattenProjections:-inherited}" />
    <logger name="slick.compiler.CreateAggregates"          level="${log.qcomp.createAggregates:-inherited}" />
    <logger name="slick.compiler.RewriteJoins"              level="${log.qcomp.rewriteJoins:-inherited}" />
    <logger name="slick.compiler.RemoveTakeDrop"            level="${log.qcomp.removeTakeDrop:-inherited}" />
    <logger name="slick.compiler.ResolveZipJoins"           level="${log.qcomp.resolveZipJoins:-inherited}" />
    <logger name="slick.compiler.HoistClientOps"            level="${log.qcomp.hoistClientOps:-inherited}" />
    <logger name="slick.compiler.ReorderOperations"         level="${log.qcomp.reorderOperations:-inherited}" />
    <logger name="slick.compiler.MergeToComprehensions"     level="${log.qcomp.mergeToComprehensions:-inherited}" />
    <logger name="slick.compiler.OptimizeScalar"            level="${log.qcomp.optimizeScalar:-inherited}" />
    <logger name="slick.compiler.FixRowNumberOrdering"      level="${log.qcomp.fixRowNumberOrdering:-inherited}" />
    <logger name="slick.compiler.PruneProjections"          level="${log.qcomp.pruneProjections:-inherited}" />
    <logger name="slick.compiler.RewriteDistinct"           level="${log.qcomp.rewriteDistinct:-inherited}" />
    <logger name="slick.compiler.RewriteBooleans"           level="${log.qcomp.rewriteBooleans:-inherited}" />
    <logger name="slick.compiler.SpecializeParameters"      level="${log.qcomp.specializeParameters:-inherited}" />
    <logger name="slick.compiler.CodeGen"                   level="${log.qcomp.codeGen:-inherited}" />
    <logger name="slick.compiler.RemoveFieldNames"          level="${log.qcomp.removeFieldNames:-inherited}" />
    <logger name="slick.compiler.InsertCompiler"            level="${log.qcomp.insertCompiler:-inherited}" />
    <logger name="slick.compiler.VerifyTypes"               level="${log.qcomp.verifyTypes:-inherited}" />
    <logger name="slick.jdbc.DriverDataSource"              level="${log.jdbc.driver:-info}" />
    <logger name="slick.jdbc.JdbcBackend.statement"         level="${log.jdbc.statement:-info}" />
    <logger name="slick.jdbc.JdbcBackend.parameter"         level="${log.jdbc.parameter:-info}" />
    <logger name="slick.jdbc.JdbcBackend.benchmark"         level="${log.jdbc.bench:-info}" />
    <logger name="slick.jdbc.StatementInvoker.result"       level="${log.jdbc.result:-info}" />
    <logger name="slick.jdbc.JdbcModelBuilder"              level="${log.createModel:-info}" />
    <logger name="slick.memory.HeapBackend"                 level="${log.heap:-inherited}" />
    <logger name="slick.memory.QueryInterpreter"            level="${log.interpreter:-inherited}" />
    <logger name="slick.relational.ResultConverterCompiler" level="${log.resultConverter:-inherited}" />
    <logger name="slick.util.AsyncExecutor"                 level="${log.asyncExecutor:-inherited}" />
</configuration>
Note

Messages on WARNING and ERROR levels may also be emitted by loggers that are not explicitly mentioned in this configuration.

You should generally enable logging for the root package slick at level INFO (currently unused) or WARNING. Debug logging should only be enabled selectively for individual loggers, otherwise you will get a huge amount of log output.

The following loggers are particularly interesting:

  • slick.basic.BasicBackend.action: Shows the execution of every Database I/O Action.

  • slick.compiler.QueryCompiler: Shows a dump of the AST after every phase of the query compiler when compiling a query.

  • slick.jdbc.DriverDataSource: Shows information about JDBC drivers being loaded by DriverDataSource. Does not apply when using a connection pool unless you explicitly use a DriverDataSource as the source for the connection pool.

  • slick.jdbc.JdbcBackend.statement: Shows all SQL statements which are executed.

  • slick.jdbc.JdbcBackend.parameter: Shows bind variable contents (for supported types) of all SQL statements which are executed.

  • slick.jdbc.JdbcBackend.benchmark: Shows execution times for SQL statements.

  • slick.jdbc.StatementInvoker.result: Shows the first rows of the result set when a query is executed. Does not apply to streaming results.

Monitoring

Slick does not expose its own JMX bean in Slick 4. Observability is provided at two levels:

  1. Connection pool (HikariCP): When a Database object has the registerMbeans option enabled, the HikariCP pool implementation registers JMX management beans. See the HikariCP monitoring documentation for details.

  2. Application runtime: Runtime-level metrics depend on the facade and runtime you use (for example, Cats Effect, ZIO, or framework-provided runtime tooling). Use your runtime’s standard observability integration (for example, Micrometer or Prometheus).

In addition to pool/runtime observability, Slick 4’s execution limits are configured directly on the database config section (for DatabaseConfig.forConfig / forProfileConfig):

  • maxConnections: maximum concurrent JDBC connections.
  • maxInflightActions (default 2 * maxConnections): maximum concurrently running DBIO chains.
  • queueSize (default 1000): maximum callers waiting for in-flight admission.
  • inflightAdmissionTimeout (optional): max time waiting for an in-flight slot.
  • connectionAcquireTimeout (optional): max time waiting for a connection slot.

For programmatic configs (forDataSource, forSource, forName, forURL) use ControlsConfig and .withControls instead of config-file keys:

DatabaseConfig.forDataSource(MyProfile, ds)
  .withControls(ControlsConfig(maxConnections = 10, queueSize = 500))

When queueSize is exhausted, Slick rejects immediately with SlickException("DBIOAction queue full").

When configured timeout limits are exceeded, Slick fails with SlickException as well:

  • SlickException("Timed out waiting for inflight admission after ...")
  • SlickException("Timed out waiting for connection slot after ...")

Slick exposes runtime concurrency counters through Database[F].controlStatus. The returned snapshot contains:

  • availableConnectionSlots: free connection slots in the connection arbiter.
  • pendingConnectionSlots: callers currently waiting for a connection slot.
  • availableAdmissionQueueSlots: free waiting-room slots before queue-full rejection.
  • availableInflightSlots: free in-flight DBIO action slots.

These values are useful to distinguish pressure points: admission saturation, inflight saturation, or connection-slot contention.

The management bean names registered by HikariCP are qualified with the poolName from the database configuration, or the config path if poolName has not been set explicitly.

Example: Including the following configuration options in the database configuration

connectionPool = "HikariCP"
registerMbeans = true
poolName = "myDb"

results in these two HikariCP management beans being registered:

  • com.zaxxer.hikari:type=PoolConfig (myDb)
  • com.zaxxer.hikari:type=Pool (myDb)
The source code for this page can be found here.