Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →MAX(number) + 1 can assign the same invoice number to two simultaneous requests because both can read the same maximum before either inserts a row. In PostgreSQL, a unique constraint can stop both copies from being stored, but it cannot safely generate the next number or guarantee a gapless series. Use a sequence when distinct values are enough; use a per-tenant counter row updated in the same transaction as the invoice when a committed series must be gapless.
Why does MAX()+1 give duplicate numbers?
MAX(number) + 1 is a read-then-write operation, not an atomic number allocator. Two PostgreSQL transactions can interleave like this:
- Request A reads the current maximum,
104. - Request B also reads
104, before A has inserted its invoice. - Both calculate
105. - Both attempt to insert an invoice numbered
105.
At the default isolation level, PostgreSQL does not make the separate read and insert behave as one indivisible operation. In a Now-Next test on PostgreSQL 17.10, eight concurrent sessions ran for 15 seconds: the authors report that 161,479 rows contained only 20,502 distinct MAX()+1 values. That is a result for their workload and machine, not a general duplicate rate.
What a unique constraint does—and does not do
Keep a database uniqueness constraint over the actual invoice-numbering key. For one series per tenant, that is typically (tenant_id, number); if tenants have multiple series, include the series identifier, such as (tenant_id, series, number). The constraint is the final integrity boundary: if two requests attempt the same key, one insert can succeed and the other will fail rather than store a duplicate.
Recommended Free Tools
#1 Best Overall
- Read Before You Buy — No Video Output: These adapters support charging and USB 2.0 data transfer, but cannot transmit video signals. Except for standard USB webcams (which use USB data only), they are not compatible with HDMI/DisplayPort cables, video-capable USB-C hubs, or docking stations with video output.
- Convert USB-A Ports to USB-C: Designed to connect USB-C earphones, cables, flash drives, card readers, and other USB-C accessories to standard USB-A ports. Plug-and-play with no drivers or software required.
- Aluminum Alloy Housing: Built with a sturdy aluminum alloy shell that aids in heat dissipation and protects against daily wear and scratches. Designed to maintain a stable and secure connection.
- Compact & Travel-Friendly: The ultra-compact design allows the adapter to stay plugged into your device without blocking adjacent ports or adding bulk, reducing wear and tear on your original USB ports.
- 12-Month Warranty: Backed by a 12-month manufacturer warranty for peace of mind. Designed to meet strict quality control standards for reliable everyday performance.
That failure is not number generation. The application must handle the constraint violation, and a constraint alone does not promise that the next successful invoice gets the next number or that committed numbers have no gaps.
Uniqueness and gaplessness are different requirements
Uniqueness means no two invoices in the defined series share a number. Gaplessness means the committed series has no missing numbers. A system can satisfy uniqueness while having gaps; choosing a design therefore depends on the business requirement, not just on avoiding collisions.
Rank #2
- 5-in-1 USB-C Hub: Experience comprehensive connectivity featuring a Power Delivery input, two USB-A 2.0 ports, a USB-A 3.0 port, and an HDMI port. (Note: The USB-C power delivery input port is only for connecting an external wall charger to power your laptop and cannot power peripheral devices.)
- 90W Pass-Through Charging: Achieve optimal charging with 90W pass-through power to your laptop, supported by a total input of 100W, with the hub reserving 10W for operational efficiency. (Note: Wall charger not included.)
- Quick Data Transfers: Accelerate your productivity with rapid data transfers using a high-speed 5Gbps USB 3.0 port and two 480Mbps USB 2.0 ports.
- 4K HDMI Display: Enhance your visual experience with a hub capable of delivering 4K resolution at 30Hz in both mirror and extend modes. Please note that this hub is compatible with MacBook (macOS 12 and newer), Windows 10 and 11, ChromeOS, and laptops equipped with DP Alt Mode and Power Delivery. Note: This device is not compatible with Linux.
- What You Get: Anker USB-C Hub (5-in-1, 4K HDMI), welcome guide, 18-month warranty, and our friendly customer service.
| Approach | Concurrent uniqueness | Gaps and failures | Scope and contention | Failure handling |
|---|---|---|---|---|
Bare MAX()+1 |
Not safe under concurrent requests. | Does not guarantee a gapless committed series. | Maximum is read from the chosen set of invoices; concurrent requests can race on the same set. | Without a unique constraint, duplicates can be stored. With one, colliding inserts fail. |
| PostgreSQL sequence | nextval is atomic across concurrent sessions and supplies distinct sequence values. |
Gaps can remain after an aborted transaction, a crash, or other documented sequence behavior; values are not reclaimed. | A sequence object supplies values from its configured sequence; it is not automatically scoped per tenant. | Applications must accept unused values when gaplessness is not required. |
| Counter row per tenant and series | Requests for the same counter row serialize as they update it; distinct rows serve separate tenant/series scopes. | Incrementing the counter and inserting the invoice in one transaction lets rollback undo both changes. | Requests for one series contend on its row. Different tenants or series can update different rows. | Keep the transaction short; retry or report ordinary database failures according to application policy. |
MAX()+1 under SERIALIZABLE |
Conflicting transactions may be aborted rather than commit duplicate results. | The Now-Next test reported no duplicates or gaps in its successful results, but some transactions failed after retries. | Serializable conflict handling adds work; performance depends on workload. | The application must retry serialization failures. In the cited test, retries were capped at 20. |
PostgreSQL’s documentation says, “PostgreSQL sequence objects cannot be used to obtain ‘gapless’ sequences.” It explains that nextval values are not reclaimed after an abort so concurrent transactions are not blocked while waiting for a value to be resolved. See the PostgreSQL 17 documentation on sequence manipulation functions.
How do you number invoices per tenant in PostgreSQL?
For a gapless committed series, store the last allocated number in a counter row for each tenant and series. Update that row and insert the invoice in the same transaction. If either operation fails and the transaction rolls back, the counter change rolls back too.
Rank #3
- Sleek 7-in-1 USB-C Hub: Features an HDMI port, two USB-A 3.0 ports, and a USB-C data port, each providing 5Gbps transfer speeds. It also includes a USB-C PD input port for charging up to 100W and dual SD and TF card slots, all in a compact design.
- Flawless 4K@60Hz Video with HDMI: Delivers exceptional clarity and smoothness with its 4K@60Hz HDMI port, making it ideal for high-definition presentations and entertainment. (Note: Only the HDMI port supports video projection; the USB-C port is for data transfer only.)
- Double Up on Efficiency: The two USB-A 3.0 ports and a USB-C port support a fast 5Gbps data rate, significantly boosting your transfer speeds and improving productivity.
- Fast and Reliable 85W Charging: Offers high-capacity, speedy charging for laptops up to 85W, so you spend less time tethered to an outlet and more time being productive.
- What You Get: Anker USB-C Hub (7-in-1), welcome guide, 18-month warranty, and our friendly customer service.
BEGIN;
UPDATE invoice_counters
SET last_number = last_number + 1
WHERE tenant_id = $1
AND series = $2
RETURNING last_number;
-- Use the returned value as the invoice number.
INSERT INTO invoices (tenant_id, series, number, ...)
VALUES ($1, $2, $3, ...);
COMMIT;
This pattern assumes the counter row already exists and that the application uses the number returned by the update for the insert. Enforce the invoice key with a unique constraint even when allocation is designed to be safe.
Choose the counter’s scope deliberately
If each tenant has one series, key the counter by tenant. If numbering restarts by year or tenants can issue from multiple series, include that series or year in both the counter key and invoice uniqueness key. The same scope must be used consistently in allocation, storage, and audits; otherwise a number may be unique in one part of the system but ambiguous in another.
Rank #4
- Dual Converters, Infinite Potential:Includes 2× USB C male to USB A female adapters and 2× USB A male to USB C female adapters. Perfect for a wide range of uses—tablets with Bluetooth keyboards, expand USB ports on macbook, and more. Two different converters for all your daily needs
- Next-Level 10Gbps & 3A Charging: No more slow 480Mbps, this usb to usb c adapter has a transfer speed of up to 10Gbps, allowing you to do more transferring in less time. This usb adapter fits both USB A and USB C charger, supporting up to 3A fast charging
- Upgraded Exquisite Craftsmanship: With an aluminum alloy housing and metal connector, the usbc to usb adapter is extremely durable and sturdy. Rigorously tested to withstand more than 10,000 times of plugging and unplugging, ensuring long-lasting performance
- Broad Compatible: The usb c to usb adapter widely supports all USB C/ USB A devices like laptops, tablets, cellphones, car chargers, and phone chargers. Such as compatible with MacBook Pro/Air 2023/2022, Thunderbolt 4/3 Devices,Apple MagSafe Watch 9/8/7/SE/Ultra, iPad Pro 2022/2021, Samsung Galaxy S23/S20/S10, and iPhone 17/16/15 Pro. Plug and play
- Please Note: To reach 10Gbps speed, keep the cable under 3.3 ft. For USB A Male to USB C adapters, try flipping the USB C connector. USB C Male to USB A adapters support bidirectional 10Gbps transfer within 3.3 ft
Assign the number late, then keep the transaction short
Leave drafts unnumbered if the business process allows it, and allocate a number when the invoice is finalized. Do document generation, network calls, and other slow work before opening the transaction that updates the counter. Once the counter row is locked, unrelated work extends the wait for every other request in that same series.
In the Now-Next article’s added test, with 10 ms of other work, the authors measured 94 invoices per second when that work happened after taking the counter number, versus 746 per second when it happened before. Those figures describe that test, not a general PostgreSQL performance guarantee.
Best Value
- 5-in-1 Connectivity: Equipped with a 4K HDMI port, a 5 Gbps USB-C data port, two 5 Gbps USB-A ports, and a USB C 100W PD-IN port. Note: The USB C 100W PD-IN port supports only charging and does not support data transfer devices such as headphones or speakers.
- Powerful Pass-Through Charging: Supports up to 85W pass-through charging so you can power up your laptop while you use the hub. Note: Pass-through charging requires a charger (not included). Note: To achieve full power for iPad, we recommend using a 45W wall charger.
- Transfer Files in Seconds: Move files to and from your laptop at speeds of up to 5 Gbps via the USB-C and USB-A data ports. Note: The USB C 5Gbps Data port does not support video output.
- HD Display: Connect to the HDMI port to stream or mirror content to an external monitor in resolutions of up to 4K@30Hz. Note: The USB-C ports do not support video output.
- What You Get: Anker 332 USB-C Hub (5-in-1), welcome guide, our worry-free 18-month warranty, and friendly customer service.
What the PostgreSQL comparison measured
Chris van Eijk’s Now-Next article, published 28 September 2026, reports tests with eight concurrent pgbench sessions running for 15 seconds on PostgreSQL 17.10 on one machine with default settings. These are the authors’ measurements; the article says it did not test crashes, replication, or more than eight sessions.
| Method and test case | Reported throughput | Reported numbering outcome |
|---|---|---|
| One PostgreSQL sequence, with 10% rollbacks | 12,131 invoices per second | 17,973 of 181,937 values were skipped. |
MAX(number)+1 at the default isolation level |
10,769 invoices per second | 140,977 of 161,479 rows issued a number already used; the article characterizes this as 87% of invoices in that test. |
MAX(number)+1 under SERIALIZABLE, with up to 20 retries |
1,475 invoices per second | No duplicates or gaps were reported, but 26.6% of transactions failed. |
| Counter row with one tenant | 2,143 invoices per second | No duplicates or gaps were reported in this test case. |
| Counter rows with requests spread across 1,000 tenants | 10,787 invoices per second | No duplicates or gaps were reported in this test case. |
The comparison illustrates the trade-off: one counter row serializes allocations for its series, while separate tenant rows can proceed independently. It does not establish that these rates will hold on another machine, PostgreSQL version, workload, or number of sessions. The article also reports that the serializable option had lower throughput than its counter-row cases and still had failures after the retry limit; those outcomes are specific to this test.
How should you audit an existing invoice series?
Audit the same scope your business key uses. For a tenant-specific series, partition gap checks by tenant; if each year or named series restarts numbering, include that dimension too.
-- Gaps between existing numbers within each tenant and series
WITH ordered AS (
SELECT tenant_id, series, number,
lead(number) OVER (
PARTITION BY tenant_id, series
ORDER BY number
) AS next_number
FROM invoices
)
SELECT tenant_id, series, number, next_number
FROM ordered
WHERE next_number > number + 1;
-- Repeated business keys
SELECT tenant_id, series, number, count(*)
FROM invoices
GROUP BY tenant_id, series, number
HAVING count(*) > 1;
The first query finds gaps between existing values; it does not establish whether the series starts at the expected first value. If the expected start is 1, validate the minimum separately. An audit should also apply the organization’s rules for voided or canceled invoices, drafts, and failed issuance—database rows alone do not settle those accounting policies.
Check the rules that apply to your jurisdiction
Invoice-numbering obligations vary by jurisdiction. As one specific example, the Dutch Tax and Customs Administration says: “Gebruik opeenvolgende nummers voor uw facturen, met 1 of meer reeksen. Elk factuurnummer mag maar 1 keer voorkomen.” In English: use consecutive invoice numbers, in one or more series, and use each invoice number only once. See its guidance on invoice requirements for VAT administration. This is Dutch guidance, not a statement of the rules in every country; confirm the requirements for the relevant jurisdiction and how it treats voided invoices and multiple series.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

