Poolboy is a lightweight, generic pooling library for Erlang with a focus on simplicity, performance, and rock-solid disaster recovery.
This is Supabase's fork of devinus/poolboy. It includes the following changes on top of upstream v1.5.2:
Overflow workers are no longer killed immediately when checked back in.
Instead, they stay available for a configurable period (default: 5 minutes)
before being dismissed. This reduces churn under bursty workloads. Set the
idle_timeout pool option (in milliseconds) to control how long idle overflow
workers are kept around.
Each pool now runs under a proper OTP supervision tree, making it compatible with hot code upgrades and standard OTP release tooling.
poolboy:start/1,2has been removed. Usepoolboy:start_link/2.- Pools now require a name.
- Requires OTP 21+.
1> Worker = poolboy:checkout(PoolName).
<0.9001.0>
2> gen_server:call(Worker, Request).
ok
3> poolboy:checkin(PoolName, Worker).
ok
This is an example application showcasing database connection pools using Poolboy and epgsql.
{application, example, [
{description, "An example application"},
{vsn, "0.1"},
{applications, [kernel, stdlib, sasl, crypto, ssl]},
{modules, [example, example_worker]},
{registered, [example]},
{mod, {example, []}},
{env, [
{pools, [
{pool1, [
{size, 10},
{max_overflow, 20}
], [
{hostname, "127.0.0.1"},
{database, "db1"},
{username, "db1"},
{password, "abc123"}
]},
{pool2, [
{size, 5},
{max_overflow, 10}
], [
{hostname, "127.0.0.1"},
{database, "db2"},
{username, "db2"},
{password, "abc123"}
]}
]}
]}
]}.-module(example).
-behaviour(application).
-behaviour(supervisor).
-export([start/0, stop/0, squery/2, equery/3]).
-export([start/2, stop/1]).
-export([init/1]).
start() ->
application:start(?MODULE).
stop() ->
application:stop(?MODULE).
start(_Type, _Args) ->
supervisor:start_link({local, example_sup}, ?MODULE, []).
stop(_State) ->
ok.
init([]) ->
{ok, Pools} = application:get_env(example, pools),
PoolSpecs = lists:map(fun({Name, SizeArgs, WorkerArgs}) ->
PoolArgs = [{name, {local, Name}},
{worker_module, example_worker}] ++ SizeArgs,
poolboy:child_spec(Name, PoolArgs, WorkerArgs)
end, Pools),
{ok, {{one_for_one, 10, 10}, PoolSpecs}}.
squery(PoolName, Sql) ->
poolboy:transaction(PoolName, fun(Worker) ->
gen_server:call(Worker, {squery, Sql})
end).
equery(PoolName, Stmt, Params) ->
poolboy:transaction(PoolName, fun(Worker) ->
gen_server:call(Worker, {equery, Stmt, Params})
end).-module(example_worker).
-behaviour(gen_server).
-behaviour(poolboy_worker).
-export([start_link/1]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
code_change/3]).
-record(state, {conn}).
start_link(Args) ->
gen_server:start_link(?MODULE, Args, []).
init(Args) ->
process_flag(trap_exit, true),
Hostname = proplists:get_value(hostname, Args),
Database = proplists:get_value(database, Args),
Username = proplists:get_value(username, Args),
Password = proplists:get_value(password, Args),
{ok, Conn} = epgsql:connect(Hostname, Username, Password, [
{database, Database}
]),
{ok, #state{conn=Conn}}.
handle_call({squery, Sql}, _From, #state{conn=Conn}=State) ->
{reply, epgsql:squery(Conn, Sql), State};
handle_call({equery, Stmt, Params}, _From, #state{conn=Conn}=State) ->
{reply, epgsql:equery(Conn, Stmt, Params), State};
handle_call(_Request, _From, State) ->
{reply, ok, State}.
handle_cast(_Msg, State) ->
{noreply, State}.
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, #state{conn=Conn}) ->
ok = epgsql:close(Conn),
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.name: the pool nameworker_module: the module that represents the workerssize: maximum pool sizemax_overflow: maximum number of workers created if pool is emptystrategy:lifoorfifo, determines whether checked in workers should be placed first or last in the line of available workers. So,lifooperates like a traditional stack;fifolike a queue. Default islifo.idle_timeout: time in milliseconds to keep idle overflow workers alive before dismissing them. Default is300000(5 minutes). Can be changed at runtime withpoolboy:set_idle_timeout/2, which also restarts the countdown for workers that are already idle.
- Devin Torres (devinus) devin@devintorres.com
- Andrew Thompson (Vagabond) andrew@hijacked.us
- Kurt Williams (onkel-dirtus) kurt.r.williams@gmail.com
Poolboy is available in the public domain (see UNLICENSE).
Poolboy is also optionally available under the ISC license (see LICENSE),
meant especially for jurisdictions that do not recognize public domain works.