<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[How the service is built and what runs out first: pools, connections, large folders]]></title><description><![CDATA[<p dir="auto"><em>Written for 6.3.4. hMailServer 6.3.7 (17 October 2026) changes three things this guide touches. On MySQL and MariaDB a lost database connection is reconnected and the statement run again, so the statement after a database restart, a failover or <code>wait_timeout</code> no longer fails, and an insert that forgives a duplicate key forgives that alone, so an error log that was quiet may now name failures that were hidden. On Windows a stop or a reinitialise no longer waits past a work queue's ten seconds for a thread held by a host or a database that has stopped answering, and setup, the live update's silent install and the uninstaller wait <code>ShutdownDrainSeconds</code> plus 90 seconds for the stop, where they waited plus 30. The ACME HTTP-01 challenge responder, which served one connection at a time, serves up to 64 at once. See <a href="/topic/28277">the 6.3.7 announcement</a>.</em></p>
<p dir="auto">This topic describes a running hMailServer 6.3.4 service: its parts and pools, the connection ceilings in front of them, the scheduled work behind them, what the machine needs, and what a folder of a hundred thousand messages costs the webmail. The one thing to know first: <strong>nothing in the server is unbounded.</strong> There is no thread per connection and no pool that grows. Every piece of work runs on a pool of a set size, and a dependency that stops answering uses up a pool long before it uses up the processor, the memory or the disk. What it cannot give you is a throughput figure: none has been measured yet.</p>
<h3><a class="anchor-offset" name="the-parts-of-the-running-service"></a>The parts of the running service</h3>
<p dir="auto">Everything runs in one process: the Windows service <code>hMailServer</code>, or the systemd unit <code>hmailserver</code> on Linux.</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Part</th>
<th>What it is</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td>Mail listeners</td>
<td>SMTP, POP3 and IMAP on <code>IOService</code> + <code>TCPServer</code></td>
<td>Boost.Asio</td>
</tr>
<tr>
<td><code>HttpServer</code></td>
<td>The engine under two listeners: REST (<code>/api/v1</code>, the webmail at <code>/portal</code>, the Control Deck) and web services (MTA-STS policy, autoconfig, ACME http-01)</td>
<td>Its own <code>io_context</code>, so a request storm cannot starve SMTP accept. Since 6.2.28</td>
</tr>
<tr>
<td>Metrics listener</td>
<td><code>/metrics</code> and the health probes</td>
<td>Raw sockets, one worker thread</td>
</tr>
<tr>
<td>ManageSieve</td>
<td>Sieve script management</td>
<td>Raw sockets, a thread of its own</td>
</tr>
<tr>
<td>SNMP agent</td>
<td>Read-only, UDP 161</td>
<td>Since 6.3.4; off, and answering nobody until <code>SnmpAllowedAddresses</code> names a manager</td>
</tr>
<tr>
<td>Background</td>
<td><code>Scheduler</code>, <code>SMTPDeliveryManager</code>, <code>ExternalFetchManager</code></td>
<td>Long-lived tasks on the main server queue</td>
</tr>
<tr>
<td>State</td>
<td>The database (accounts, domains, message metadata and settings, since 6.3.4 including the <code>[Settings]</code> keys), one file per message, and <code>hMailServer.ini</code> as the bootstrap</td>
<td>The database stays small next to the store</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>The handover that matters for capacity:</strong> an SMTP session never delivers anything. The final <code>250</code> is sent from a worker on the asynchronous task queue once the message is written, and delivery happens later on a delivery thread, so the accepting side and the delivering side run out separately. <a href="/topic/28219">Diagnosing stalled mail</a> takes each half in turn; <a href="/topic/28243">How email works</a> follows one message through both.</p>
<h3><a class="anchor-offset" name="the-pools-their-sizes-and-what-a-full-one-looks-like"></a>The pools, their sizes, and what a full one looks like</h3>
<p dir="auto">Seven work queues are created at startup, and the two HTTP listeners have workers of their own. The first column is the <code>queue</code> label of <code>hmailserver_workqueue_depth{queue}</code> on the metrics endpoint, which counts tasks accepted and not yet started; the last row is not a work queue and has no label.</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Queue</th>
<th>Threads</th>
<th>Sized by</th>
<th>What runs on it</th>
<th>When it is full</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>IOCPQueue</code></td>
<td>15</td>
<td><code>tcpipthreads</code></td>
<td>Every socket read, write and TLS handshake for SMTP, POP3 and IMAP</td>
<td>New connections are accepted but nothing progresses; clients time out mid-command</td>
</tr>
<tr>
<td><code>Asynchronous task queue</code></td>
<td>15</td>
<td><code>MaxNumberOfAsynchronousTasks</code></td>
<td>Message finalization, which sends the final <code>250</code></td>
<td>Senders sit after <code>CRLF.CRLF</code> with no reply</td>
</tr>
<tr>
<td><code>Name lookup queue</code></td>
<td>15</td>
<td>the same setting</td>
<td>Blocking reverse-DNS lookups for live sessions</td>
<td>Reverse names become "Unknown", so a dead reverse zone cannot stall acknowledgements</td>
</tr>
<tr>
<td><code>SMTP delivery queue</code></td>
<td>10</td>
<td><code>maxdelivertythreads</code></td>
<td>The delivery of one queued message</td>
<td>The queue grows and mail is late; nothing is lost, since the sender already has its <code>250</code></td>
</tr>
<tr>
<td><code>External fetch queue</code></td>
<td>15</td>
<td><code>MaxNumberOfExternalFetchThreads</code></td>
<td>One run per fetch account</td>
<td>Fetch accounts fall behind their schedule</td>
</tr>
<tr>
<td><code>Maintenance queue</code></td>
<td>5, fixed</td>
<td>nothing</td>
<td>One-shot scheduled tasks; a backup started over REST</td>
<td>A slow sweep delays the other one-shot sweeps</td>
</tr>
<tr>
<td><code>Server queue</code></td>
<td>4, fixed</td>
<td>nothing</td>
<td><code>Scheduler</code>, <code>IOService</code>, <code>SMTPDeliveryManager</code>, <code>ExternalFetchManager</code></td>
<td>Cannot fill in normal operation: each task holds one slot for the life of the server</td>
</tr>
<tr>
<td><code>HttpServer</code> workers</td>
<td>4 per listener, fixed</td>
<td>nothing</td>
<td>One REST or web-services request each</td>
<td>Requests queue behind the four; SMTP is unaffected</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>Where the four sizes are set.</strong> On Windows, the Control Panel's <strong>Maintenance → Performance</strong> page, <em>Threads</em> tab, holds the COM <code>Settings</code> properties <code>TCPIPThreads</code>, <code>MaxAsynchronousThreads</code> and <code>MaxDeliveryThreads</code>, and the <code>[Settings]</code> key <code>MaxNumberOfExternalFetchThreads</code>. On either platform the first three are in the server settings group: the Control Deck's Settings view, <code>PUT /api/v1/settings</code> with <code>tcpip_threads</code>, <code>max_asynchronous_threads</code> and <code>max_delivery_threads</code>, or <code>hmctl settings set</code>. The fourth goes through <code>/api/v1/settings/ini/{name}</code> (administrator password only), <code>hmctl ini set</code>, or on Linux <code>hmailserver --set-setting</code> as root. Since 6.3.4 the database is the settings store, so do not edit the <code>[Settings]</code> line in <code>hMailServer.ini</code>: a line edited there is ignored in favour of the stored value. <a href="/topic/28222">Settings: when a save takes effect</a> covers the store, what becomes of the file's line (HM5804) and when each key applies. The tab also shows <code>WorkerThreadPriority</code>, read-only: the server stores that value and never reads it.</p>
<p dir="auto"><strong>When a new size takes effect.</strong> Since 6.3.4 a save applies most settings at once, but <code>MaxNumberOfExternalFetchThreads</code> waits for a reinitialise, because the queue's size is set when the fetch manager is built; <code>GET /api/v1/server/settings/pending</code> lists it until then. For the other three the documents leave a gap: the Control Panel reports a save of its COM settings as "applied immediately", while the Architecture page has the pools created when the servers start, and no document says when a changed count reaches a running pool. Until one does, treat all four alike: after saving, reinitialise (the Control Panel's Reinitialize or <strong>Apply now</strong>, <code>POST /api/v1/server/reinitialize</code>, or <code>hmctl api POST /api/v1/server/reinitialize</code>) or restart the service. A reinitialise stops and starts every service in place, ends the Control Deck's session, and ends a drain.</p>
<pre><code class="language-bash"># The REST listener on this machine: read the server settings group,
# then give delivery 25 threads (or: hmctl settings set --set max_delivery_threads=25)
curl -u Administrator:pw http://127.0.0.1:8443/api/v1/settings
curl -u Administrator:pw -X PUT -H "Content-Type: application/json" \
     -d '{"max_delivery_threads":25}' http://127.0.0.1:8443/api/v1/settings

# The fetch pool is a [Settings] key; it waits for a reinitialise
hmctl ini set MaxNumberOfExternalFetchThreads 20
hmctl api POST /api/v1/server/reinitialize
</code></pre>
<p dir="auto"><strong>Two asynchronous threads are kept back.</strong> Finalization runs the spam tests and event scripts, which wait on things outside the process, so <code>AsyncQueueReservedThreads</code> (2) keeps that many threads free of it: with the defaults at most 13 finalizations run at once. A task waiting for a slot holds no thread and is counted by <code>hmailserver_workqueue_blocking_tasks_waiting{queue}</code>; a count that stays above zero means something those tasks depend on is slow. On Windows the key is on <strong>Server limits &amp; expert settings</strong>, card <em>Timeouts and queue bounds</em>; anywhere, <code>hmctl ini set</code>.</p>
<p dir="auto"><strong>Only two queues report a stall</strong>: the asynchronous and name lookup queues write the "every thread busy" report that <a href="/topic/28219">Diagnosing stalled mail</a> reads. The others are left out deliberately, since their tasks are long-lived by design, so a full <code>IOCPQueue</code>, <code>SMTP delivery queue</code> or <code>External fetch queue</code> shows only in <code>hmailserver_workqueue_depth{queue}</code> and in its symptoms.</p>
<h3><a class="anchor-offset" name="the-database-connections-every-pool-shares"></a>The database connections every pool shares</h3>
<p dir="auto">The deliveries, the sign-ins and the rest of the server share one pool of database connections, <code>NumberOfConnections</code> in the <code>[Database]</code> section of <code>hMailServer.ini</code>, 5 as shipped. A wait for one longer than <code>DBConnectionAcquireTimeout</code> (60 seconds) fails. In <code>hmailserver_db_connections{state}</code>, <code>available</code> pinned at zero with <code>busy</code> at the pool size is saturation, and every mail path is then waiting out that timeout.</p>
<ul>
<li><strong>Raise it with the delivery threads.</strong> The relay profile sets <code>maxdelivertythreads</code> to 25 and the sender profile to 50, and each tells you to raise <code>NumberOfConnections</code> to about the delivery thread count.</li>
<li><strong>The built-in database has one connection.</strong> On Windows, <code>NumberOfConnections</code> is forced to 1 for <code>MSSQLCE</code>. Before You Install calls the built-in engine adequate for anything up to a few dozen mailboxes, and its single connection the first thing to change if the server feels slow under concurrency. Linux has no built-in database; it uses PostgreSQL or MariaDB. <a href="/topic/28228">Choosing a database</a> covers the choice.</li>
<li><strong>It is a bootstrap key.</strong> <code>[Database]</code> stays in the file, never in the database, and its keys wait for a restart. On Windows the Performance page's <em>Database</em> tab edits it, on the server machine only. On Linux:</li>
</ul>
<pre><code class="language-bash">sudoedit /etc/hmailserver/hMailServer.ini   # [Database] NumberOfConnections=25
sudo systemctl restart hmailserver
</code></pre>
<h3><a class="anchor-offset" name="connections-and-requests-the-ceilings-in-front-of-the-pools"></a>Connections and requests: the ceilings in front of the pools</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Where</th>
<th>Limit</th>
<th>As shipped</th>
<th>Set on</th>
</tr>
</thead>
<tbody>
<tr>
<td>SMTP sessions</td>
<td><code>MaxSMTPConnections</code></td>
<td>0, no cap</td>
<td><strong>Connections &amp; protocols → Protocols</strong>, SMTP tab; <code>max_smtp_connections</code></td>
</tr>
<tr>
<td>IMAP sessions</td>
<td><code>MaxIMAPConnections</code></td>
<td>0, no cap</td>
<td>The IMAP tab; <code>max_imap_connections</code></td>
</tr>
<tr>
<td>POP3 sessions</td>
<td><code>MaxPOP3Connections</code></td>
<td>not given in the documents; <code>GET /api/v1/settings</code> shows it</td>
<td>The POP3 tab; <code>max_pop3_connections</code></td>
</tr>
<tr>
<td>Recipients in one message</td>
<td>50,000</td>
<td>50,000</td>
<td>No setting is named; beyond it, <code>550 Too many recipients</code></td>
</tr>
<tr>
<td>REST listener, with the webmail and the Deck</td>
<td>64 connections, closed at accept before any TLS handshake; 4 workers; 64 KB a request (16 MB, with 300 seconds, on the two attachment routes); 30 seconds a request; 300 seconds a connection</td>
<td>fixed</td>
<td>no key</td>
</tr>
<tr>
<td>Web-services listener</td>
<td>128 connections; 4 workers; 64 KB a request; 15 seconds a request; 120 seconds a connection</td>
<td>fixed</td>
<td>no key</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>The webmail shares the REST listener</strong>: its users, the Control Deck and every script that calls the API meet the same 64 connections and four workers. Its request rate is in <a href="/topic/28264">the topic on the REST API</a>. Outbound, since 6.3.4, <code>MaxOutboundConnsPerDestination</code> and <code>MaxOutboundConnsPerTenant</code> (both 0, off) cap sessions per destination and per sending domain; a tenant share larger than the delivery thread count is no share at all (<a href="/topic/28259">Outbound shaping and IP warm-up</a>).</p>
<h3><a class="anchor-offset" name="scheduled-work"></a>Scheduled work</h3>
<p dir="auto">The <code>Scheduler</code> polls its recurring tasks once a minute; one-shot tasks go through the <code>Maintenance queue</code> at once. External fetch is not one of them: the <code>ExternalFetchManager</code> runs its own one-minute loop. <code>Roadmap.md</code> recorded in August 2026 that a due task runs on the scheduler's own thread, so one long task delays the others, and that the real period is the interval plus the run time. The tasks, grouped by cadence:</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Task</th>
<th>Cadence</th>
<th>Registered</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>GreyListCleanerTask</code></td>
<td>every <code>GreylistingRecordExpirationInterval</code> minutes (240 as shipped)</td>
<td>when SMTP is on</td>
</tr>
<tr>
<td><code>RemoveExpiredRecords</code>, <code>WorkQueueHealthTask</code></td>
<td>every minute</td>
<td>always; the second writes the stall report</td>
</tr>
<tr>
<td><code>TlsRptReporterTask</code>, <code>DmarcRptReporterTask</code></td>
<td>hourly</td>
<td>always; each sends only when its from-address is set</td>
</tr>
<tr>
<td><code>LogRetentionTask</code>, <code>MailboxRetentionTask</code></td>
<td>start + 6 hours</td>
<td>always</td>
</tr>
<tr>
<td><code>ArchiveRetentionTask</code>, <code>IMAPExpungeRetentionTask</code></td>
<td>start + 12 hours</td>
<td>always</td>
</tr>
<tr>
<td><code>MetricsHistoryTask</code></td>
<td>start + every minute</td>
<td>always</td>
</tr>
<tr>
<td><code>UpdateCheckTask</code></td>
<td>start + every 15 minutes</td>
<td>always; does nothing until <code>UpdateCheckEnabled=1</code></td>
</tr>
<tr>
<td><code>MessageStoreConsistencyTask</code>, <code>DiskSpaceMonitorTask</code></td>
<td>start + hourly</td>
<td>always</td>
</tr>
<tr>
<td><code>BackupScheduleTask</code></td>
<td>a one-minute tick against the wall clock</td>
<td>only when a schedule is set</td>
</tr>
<tr>
<td><code>DirectorySyncScheduleTask</code></td>
<td>start + every <code>[LDAP] SyncScheduleMinutes</code></td>
<td>only when that is set</td>
</tr>
<tr>
<td><code>AcmeRenewalTask</code></td>
<td>start + hourly</td>
<td>only when <code>AcmeEnabled=1</code></td>
</tr>
</tbody>
</table>
<h3><a class="anchor-offset" name="sizing-the-machine"></a>Sizing the machine</h3>
<p dir="auto"><strong>Memory.</strong> Before You Install asks for 2 GB as a minimum on Windows, more for a busy server. It is guidance; nothing enforces it, and memory per session has not been measured.</p>
<p dir="auto"><strong>Disk.</strong> Size it for how much mail you will keep, not how much you have today. The store is <code>Data\</code> under the program folder on Windows and <code>/var/lib/hmailserver</code> on Linux, one file per message. For scale, the webmail bench's hundred thousand messages, 5 % of them with an attachment of 20 to 512 KB, are 1,323,987,827 bytes. Below <code>MinimumFreeDiskSpaceMB</code> (100) new mail is refused temporarily, <code>452 4.3.1</code> over SMTP and <code>NO [UNAVAILABLE]</code> to an IMAP <code>APPEND</code>, so senders retry; below <code>DiskSpaceWarningThresholdMB</code> (1024) the server logs a warning and keeps accepting.</p>
<p dir="auto"><strong>Antivirus.</strong> On Windows, exclude <code>Data\</code>, <code>Database\</code> and <code>Temp\</code> from real-time scanning. A scanner holding a message file open is a documented cause of delivery that silently does nothing; the server detects one shape of it and logs error 5760. Before You Install names no exclusions for Linux, where the store is <code>/var/lib/hmailserver</code> with its <code>temp</code> and <code>database</code> subdirectories.</p>
<p dir="auto"><strong>Durability.</strong> <code>MessageStoreFsync</code> (0 as shipped) flushes the spool file to disk before the <code>250</code>, and a failed flush refuses the message. The published-numbers method runs with it on and labels the shipped default "not durable". Set it on Windows on <strong>Server limits &amp; expert settings</strong> (card <em>Message store durability</em>), or anywhere with <code>hmctl ini set</code>.</p>
<h3><a class="anchor-offset" name="a-folder-of-a-hundred-thousand-messages-in-the-webmail"></a>A folder of a hundred thousand messages in the webmail</h3>
<p dir="auto">Every webmail path reads the folder's shared message collection, the one IMAP, POP3 and delivery use: one small object per message. Until 6.3.4 opening a folder copied the whole of it, under the lock IMAP sessions and delivery wait on, for every page of 200. Since 6.3.4:</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Operation</th>
<th>What it does now</th>
<th>What still grows with the folder</th>
</tr>
</thead>
<tbody>
<tr>
<td>Open, <code>GET /api/v1/me/folders/{id}/messages</code></td>
<td>One pass under the lock counts the folder and copies only the page of 200; each row's file head is read twice, not three times</td>
<td>That pass; and the first open after a start, or after thirty idle minutes in the cache, reads every row of the folder from the database, as an IMAP <code>SELECT</code> does</td>
</tr>
<tr>
<td>Scroll</td>
<td>Older and Newer by <code>before_uid</code>; from three pages up, Oldest in one request (<code>oldest_before_uid</code>)</td>
<td>Every page costs what the first costs, wherever it is in the folder: the one pass that counts the folder</td>
</tr>
<tr>
<td>Search</td>
<td>At most 2,000 message files and about two and a half seconds a request, then answers where to go on from; across every folder it walks the mailbox newest first and answers <code>next_before_id</code>; with <code>IndexerFullText</code> and message indexing on (off as shipped), a message the index rules out is passed without opening its file</td>
<td><code>Performance.md</code> does not say</td>
</tr>
<tr>
<td>Select-all and one action</td>
<td>The selection goes to <code>POST /api/v1/me/folders/{id}/bulk</code>: at most 1,000 messages a call for a flag, 500 for a move or a delete, nothing new taken on after about two and a half seconds</td>
<td>A changed flag is a row written, a move is a file copied, and a selection narrowed to an inbox tab reads the head of every message</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>Junk over a whole folder is a hundred thousand lessons.</strong> With SpamAssassin on, each message moved into or out of Junk queues one lesson, as the same move over IMAP does. In the Settings Reference the lesson on a move is <code>SpamAssassinLearnOnMove</code> (off as shipped), run as a task on the asynchronous work queue.</p>
<p dir="auto"><strong>A move holds the mail twice, briefly</strong>: original and copy, both counted against the quota, for no longer than one slice of the work.</p>
<p dir="auto"><strong>Not changed.</strong> The Storage, Subscriptions and Scheduled views still copy each folder they look at; emptying Junk or Trash copies the folder once per 500 messages removed; a quick step over a whole-folder selection still reads at most five thousand messages.</p>
<p dir="auto"><strong>For other callers of <code>GET /api/v1/me/search</code></strong>, it now answers <code>complete: false, more: true</code> with <code>next_before_id</code> whenever it is not the end, and its hits come newest first across every folder, where they came folder by folder.</p>
<p dir="auto"><strong>Over IMAP</strong>, one <code>SEARCH</code> or <code>SORT</code> is bounded by <code>IMAPSearchTimeout</code> (60 seconds) and <code>IMAPSearchMaxMegabytes</code> (2048 MB examined). <a href="/topic/28191">The webmail portal at /portal</a> covers the rest of the client.</p>
<h3><a class="anchor-offset" name="what-has-not-been-measured"></a>What has not been measured</h3>
<p dir="auto"><strong>The webmail at a hundred thousand.</strong> <code>Performance.md</code> has the method and a results table for the Windows bench (SQL Server Compact, 100,000 messages in the inbox, the full-text index off and on). Every cell reads <em>to be measured on the bench</em>; nothing was estimated. Its tools, <code>build/perf/seed-folder.py</code> and <code>build/perf/webmail-timing.py</code>, are in the repository and also run against a Linux server. Record the machine, database, message store, index state and build with any numbers.</p>
<p dir="auto"><strong>How much the server carries.</strong> <code>PublishedNumbers.md</code> defines messages in and out per second, latency percentiles, IMAP sessions per core with every operation's 95th percentile under 200 ms, memory per session and Dovecot's imaptest, measured against Postfix and Dovecot on the same machine under ten fairness rules. Its results say <strong>Not measured yet</strong>, and until they are filled the first line of <code>Roadmap2.md</code> is a goal, not a claim. The load generator, in the repository since 6.3.4, is <code>build/perf/load/loadgen.py</code>; a run in which the generator was busy for more than 85 per cent of it gives only a floor and is not published. The Windows bench gives hMailServer's own numbers only, not to be compared with the Linux table.</p>
<pre><code class="language-bash">python build/perf/load/loadgen.py --help
python build/perf/load/loadgen.py self-test   # proves the generator, says nothing about any server
</code></pre>
<p dir="auto">Size from the ceilings above, watch the queue depths and the database pool, and treat any throughput figure quoted elsewhere as unmeasured by the project.</p>
<h3><a class="anchor-offset" name="what-it-does-not-do"></a>What it does not do</h3>
<ul>
<li>No document gives a rule for sizing the pools to a machine; the only sized examples are the relay and sender profiles' 25 and 50 delivery threads.</li>
<li>The main server queue, the maintenance queue and the HTTP listeners' workers, connection caps and deadlines are fixed; no key changes them.</li>
</ul>
<h3><a class="anchor-offset" name="where-to-read-more"></a>Where to read more</h3>
<ul>
<li>Wiki: <a href="https://gitlab.com/hmailserver/hmailserver/-/wikis/Architecture" rel="nofollow ugc">Architecture</a>, <a href="https://gitlab.com/hmailserver/hmailserver/-/wikis/Before-You-Install" rel="nofollow ugc">Before You Install</a>, <a href="https://gitlab.com/hmailserver/hmailserver/-/wikis/Control-Panel-Reference" rel="nofollow ugc">Control Panel Reference</a> section 7.8, <a href="https://gitlab.com/hmailserver/hmailserver/-/wikis/Settings-Reference" rel="nofollow ugc">Settings Reference</a>, <a href="https://gitlab.com/hmailserver/hmailserver/-/wikis/The-REST-API" rel="nofollow ugc">The REST API</a> section 8, <a href="https://gitlab.com/hmailserver/hmailserver/-/wikis/APIs-Reference" rel="nofollow ugc">APIs Reference</a> section 1 and <a href="https://gitlab.com/hmailserver/hmailserver/-/wikis/Monitoring-and-Health" rel="nofollow ugc">Monitoring and Health</a>.</li>
<li>Documents: <a href="https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/Performance.md" rel="nofollow ugc">Performance.md</a>, <a href="https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/PublishedNumbers.md" rel="nofollow ugc">PublishedNumbers.md</a>, <a href="https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/SettingsApply.md" rel="nofollow ugc">SettingsApply.md</a>, <a href="https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/Profiles.md" rel="nofollow ugc">Profiles.md</a> and <a href="https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/OutboundShaping.md" rel="nofollow ugc">OutboundShaping.md</a>.</li>
<li>The public documentation: <a href="https://www.progressiverobot.com/hmailserver-documentation/#3-before-you-install-the-checklist" rel="nofollow ugc">Before you install</a>, <a href="https://www.progressiverobot.com/hmailserver-documentation/#35-a-database" rel="nofollow ugc">A database</a> and <a href="https://www.progressiverobot.com/hmailserver-documentation/#163-prometheus-metrics-and-health-probes" rel="nofollow ugc">Prometheus metrics and health probes</a>.</li>
<li>On this forum: <a href="/topic/28219">Diagnosing stalled mail</a>, <a href="/topic/28220">Reading the logs</a>, <a href="/topic/28272">Monitoring and health</a>, <a href="/topic/28254">The webmail in depth</a>, <a href="/topic/28192">The Control Deck</a> and <a href="/topic/28189">hMailServer on Linux</a>. Without a GitLab account, a bug or a question can go to the Service Desk address <a href="mailto:contact-project+hmailserver-hmailserver-86730559-issue-@incoming.gitlab.com" rel="nofollow ugc">contact-project+hmailserver-hmailserver-86730559-issue-@incoming.gitlab.com</a>, which GitLab files as a confidential issue; the replies arrive by email.</li>
</ul>
]]></description><link>https://www.hmailserver.co.uk/topic/28238/how-the-service-is-built-and-what-runs-out-first-pools-connections-large-folders</link><generator>RSS for Node</generator><lastBuildDate>Fri, 06 Nov 2026 09:05:55 GMT</lastBuildDate><atom:link href="https://www.hmailserver.co.uk/topic/28238.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 27 Sep 2026 19:20:13 GMT</pubDate><ttl>60</ttl></channel></rss>