Direct Answer
Yes, you can meaningfully reduce Ecto repository connection costs for a low-traffic workload by tuning pool_size, disabling the query cache, and turning off SQL logging. However, each setting has trade-offs that depend on your expected concurrency and observability needs. The key is to match the pool to your actual request rate while keeping enough headroom for occasional bursts.
Pool Size and Pool Count
Setting pool_size to 1 limits the repository to a single database connection. For a truly low-traffic app where requests are serialized or infrequent, this is safe and minimizes idle connections. The main risk is that concurrent requests will queue on the single connection, increasing latency. If your workload occasionally spikes to 5–10 simultaneous requests, a pool of 1 will cause noticeable waits. A pool of 2–3 often strikes a better balance.
pool_count is typically left at 1—it only matters when you configure multiple pools (e.g., for read/write replicas). Lowering it below 1 is not valid, and keeping it at 1 has no cost impact.
Query Cache
Disabling :query_cache saves memory because Ecto no longer stores compiled query plans. For rare or one-off queries, the performance impact is negligible—the cache only helps when the same query runs repeatedly. If your workload is sparse and queries are diverse, disabling it is a reasonable memory saving. If you have a few hot queries that run often, you might see a small CPU increase from recompiling them, but it's rarely significant at low traffic.
Logging
Setting log: false eliminates per-query logging overhead, which includes formatting, I/O, and potential log volume. In production, this is safe as long as you have alternative observability (e.g., metrics, tracing). You lose the ability to see slow queries in logs, so consider enabling a slower-query threshold instead of full logging if you still want some visibility.
Additional Tuning
Beyond the settings you mentioned, consider queue_target and queue_interval. These control how long a request waits for a connection before timing out. For low traffic, a shorter queue_target (e.g., 50ms) can fail fast under unexpected bursts rather than piling up. Also, set a reasonable timeout for queries to reclaim stuck connections.
What to Verify
After adjusting settings, monitor the database server's active connection count (e.g., pg_stat_activity for PostgreSQL) and watch for DBConnection.ConnectionError or timeout errors under simulated load. The optimal pool size depends on your expected concurrency—if you can share that, I can give a more specific recommendation.