CosId, distributed ID generation without a network call per ID
Universal, flexible, high-performance distributed ID generator. | 通用、灵活、高性能的分布式 ID 生成器
At a glance
- What is it?
- CosId is a Java library for generating globally unique IDs inside the process, coordinating through a store you already run so that machine ids and segment ranges are leased ahead of time. It offers three generators with different trade-offs, and the version matrix shows this is a project that has changed shape across major versions.
- Who is it for?
- CosId suits a Java service that needs collision-free IDs across replicas and would rather not make a network call per ID, and it suits teams already on Spring Boot who can pick the store they already operate. It does not suit an application that only needs a random UUID, and it does not suit a team unwilling to run a coordination store, since the uniqueness guarantee depends on that store being reachable at startup.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Java, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Why the coordination happens before the ID, not during it
The problem CosId addresses is stated in the project's own framing: every replica of a service needs IDs, primary keys, order numbers and event ids, that never collide with those of the other replicas. The obvious solutions each have a cost. A database sequence serializes on the database. A central allocator makes every ID cost a network call. A random UUID is collision-free but is a long opaque string, and it does not tell you anything about when it was created.
CosId's answer is to move the coordination out of the hot path. IDs are generated inside your process with no network call per ID, and the coordination that keeps them unique is done up front: it leases a distinct machine id to every Snowflake instance from a store you already run, takes ranges of segment IDs ahead of time, and handles clocks that move backwards.
That last item is the one most ID generators gloss over. A Snowflake-style ID encodes time in its high bits, so if the system clock steps backwards, two nodes can mint the same ID. The project lists clock handling as a first-class feature and lists clock synchronization among its repository topics, which tells you the failure mode was considered rather than discovered later by users.
The audience is a backend team on Java, often on Spring Boot, running several replicas of a service, who want a stable, sortable, numeric identifier without building their own allocator. The store requirement is the price of admission, and it is a price most organizations have already paid because they run Redis, a database or ZooKeeper.
Three generators, three different reasons to pick one
The project compares its generators in a table that lists the ID type, the throughput on one instance from historical JMH runs, and the situation each is meant for. The choice is not a matter of taste, it is a matter of what your IDs have to carry.
`SegmentChainId` produces a `long` that is near-sequential, and the table lists 127,439,148 ops/s on one instance. It is the default segment mode, and the case for it is short numeric keys or business numbers where a gapless-looking sequence matters more than time information.
`SnowflakeId` also produces a `long`, but time-ordered, with 4,096,000 ops/s listed as its theoretical maximum. Here the point is that the ID carries its creation time and there is no store call after startup, since the machine id is leased once and the rest is local arithmetic.
`CosIdGenerator` produces a `String` of 15 characters, time-ordered, and is the option for very many instances, up to a million machine ids. The ID is a string because the project's layout trades the compactness of a 64-bit integer for room for a very large machine id space.
That third row is worth pausing on. A million machine ids is an unusual order of magnitude, and it shows the project is aimed at deployments where the instance count is not a rounding error. The near-sequential option is the fastest of the three by a wide margin in those historical numbers, and the trade is that sequential IDs are easier to enumerate and easier to guess, which matters if they end up in a URL.
The documentation also frames the choice as a set of trade-offs rather than a ranking, with a page dedicated to why CosId exists and the trade-offs between the generators.
Segment mode trades a gap for a call
The segment mechanism is the most interesting of the three, because it is the one that changes the shape of the traffic rather than just the shape of the ID.
Instead of asking the store for a number on every call, a node leases a batch of numbers ahead of time and hands them out locally. The cost of a collision becomes a gap in the sequence. In exchange, the per-ID cost is arithmetic rather than a round trip.
The configuration for it is a small YAML block, and it shows how the pieces fit: a namespace, a segment section with a distributor whose type selects the store, and a provider section naming the ID provider and its step, the batch size.
cosid:
namespace: ${spring.application.name}
segment:
enabled: true
distributor:
type: redis
provider:
order:
step: 100The step value is the knob that decides how much work each lease does. A step of 100 means the node asks for a hundred IDs at a time, and the trade is between lease frequency and the size of the gap a restart leaves behind. The documentation points at a configuration reference that lists every property and its default, and at an operations page covering a production checklist, rolling upgrades, monitoring and troubleshooting.
The namespace matters too, because it scopes identifiers so that different services, and different generators inside one service, do not collide. In the example it is derived from the Spring application name, which is a reasonable default and also a reminder that the namespace is a correctness boundary rather than a label.
Wiring it into a Spring Boot service
The quick start is three pieces: the Gradle dependencies, the YAML configuration, and one line of Java. The dependency block uses the CosId BOM so that the version is managed in one place, and it shows the shape of the module set.
dependencies {
implementation(platform("me.ahoo.cosid:cosid-bom:$cosidVersion"))
implementation("me.ahoo.cosid:cosid-spring-boot-starter")
implementation("me.ahoo.cosid:cosid-spring-redis") // or cosid-jdbc, cosid-mongo, cosid-zookeeper, cosid-proxy
implementation("org.springframework.boot:spring-boot-starter-data-redis")
}The comment on the third line is the important part. There is one starter, `cosid-spring-boot-starter`, and then exactly one store module, chosen by you: `cosid-spring-redis`, `cosid-jdbc`, `cosid-mongo`, `cosid-zookeeper` or `cosid-proxy`. You do not get all the backends, and you do not need to implement one from scratch, but adding a second store later means adding a module and reconfiguring.
With the starter in place, obtaining an ID is a single call, and the provider is looked up by name so that different ID streams in one application, an order number and an event id, can use different generators.
long orderId = idGeneratorProvider.getRequired("order", IdGenerator.class).generate();The name passed to `getRequired` is the key from the provider section of the configuration, in this case `order`. The method name says what happens when it is missing: it throws rather than returning a null generator, which is the behaviour you want in a request path.
Beyond the core, the repository carries integration modules for the parts of a Spring application that usually need special handling: MyBatis, Spring Data JDBC, Jackson, ShardingSphere, Activiti, Flowable and Axon. ShardingSphere is worth singling out, because a sharded database changes how IDs must be allocated, and Axon and Flowable both have their own event id concepts that a shared generator can serve.
The store is a dependency, not an implementation detail
CosId supports Redis, JDBC against MySQL, MariaDB and PostgreSQL, MongoDB, ZooKeeper, a CosId proxy, or a store of your own. That list is wide, and the width is the point: the coordination layer should be something you already run.
The trade-off follows from the design. Uniqueness is not a property of the ID generator alone, it is a property of the generator plus the store plus the clock. If the store is unreachable when a node starts, that node cannot obtain a machine id or lease a segment, and the documentation's operations pages cover monitoring and troubleshooting for exactly this class of problem.
The proxy option is the one worth understanding separately, because it changes where the coordination happens. A separate CosId proxy service fronts the store, so your application talks to one endpoint instead of talking to Redis or a database directly. For an organization that wants to centralize and audit ID allocation, that is a meaningful operational choice, and the repository ships runnable examples for it alongside the Redis and ZooKeeper examples.
There is a trade-off in the other direction as well. A store you already run is a dependency you already have, but it also means the ID path depends on that infrastructure being healthy at startup, and in a Kubernetes deployment that means thinking about whether a node starting without its store should fail fast or retry. The project lists Kubernetes and cloud-native among its topics and ships a production operations guide, which suggests the deployment question is on the maintainer's mind rather than only on the user's.
The 4.0 release is a line break, not a routine bump
The version compatibility table is the most useful thing in the documentation for an adopter, and it shows a project that has changed shape. CosId 4.x pairs with Spring Boot 4.x and requires Java 17 or newer, and lives on the `main` branch. CosId 3.x also requires Java 17 and pairs with Spring Boot 4.x, and is maintained on the `3.x` branch. CosId 2.x pairs with Spring Boot 3.x, and 1.x pairs with Spring Boot 2.x and runs on Java 8.
So the current line is a Java 17 and Spring Boot 4 generation, and there is a maintenance branch for the previous major version. That is a healthy pattern for a library with integrations into many frameworks, but it also means the major version number tracks a platform generation.
The release history shows the pace. Three releases, v4.0.0, v4.0.1 and v4.0.2, all on 2026-10-12, and the last push to the repository was on 2026-10-16. The project is not archived, and it is moving quickly enough that the patch releases landing on the same day as the major one is a pattern to expect rather than a one-off.
For an existing user, the documentation points at a migration document, MIGRATION-4.0.md, and a migration guide page, and the fact that both exist for the 3.x to 4.x move tells you there is a real API change to absorb. Anyone planning an upgrade should read that document rather than assuming the semver promise covers it.
Performance claims come from one machine, so read them narrowly
The performance section is specific about its own limits, which is more than many projects manage. The numbers are described as historical JMH benchmarks run on one development notebook, a MacBook Pro M1, with Redis on the same machine. The throughput figure in the generator table is labelled the same way, as historical JMH on one instance.
That is a narrow measurement, and the project is upfront that it is one machine with a local Redis. It tells you the relative cost of the three generators, which is useful for choosing between them, and it does not tell you what a node in your cluster will do with a networked store and a real network.
There is one comparison claim, and it is attributed rather than asserted bare. The documentation states that `SegmentChainId` is about five times as fast as Meituan Leaf's segment mode, with a page dedicated to the CosId versus Leaf comparison. Leaf is the segment-mode generator most Java teams meet first, so the comparison is the relevant one for many readers, and pointing to a dedicated page rather than a table cell is the right way to present it.
Two practical warnings. The figures are historical, which means they describe a past version rather than the one you would install today. And a benchmark taken with the store on the same machine removes the network, which is precisely the part of the cost that matters in production for a generator whose whole pitch is avoiding network calls.
The rest of the repository reflects a testing orientation rather than a performance one: an integration test workflow badge, a codecov badge, a Codacy grade badge, and dedicated modules for test infrastructure, benchmark code and code coverage reporting. The `cosid-benchmark` module in the tree is where those numbers come from, so you can re-run them on your own hardware.
Apache-2.0, an active branch, and a lot of surface area
The licence is Apache-2.0, which is the permissive grant with an explicit patent clause, and the LICENSE file sits at the top of the tree. For a library that many teams embed in services, that is the expected answer and there is no copyleft obligation reaching into your application.
The maintenance picture is straightforward. The last push was on 2026-10-16, the repository is not archived, and the 3.x branch is documented as a maintenance branch, which is the term for a line that receives fixes but not new development.
The scale of the project is worth sizing up before you adopt it. The tree contains around thirty modules: the core, the BOM, the dependencies descriptor, separate modules for each store and each framework integration, modules for Jackson, ShardingSphere, Activiti, Flowable, Axon, MyBatis and Spring Data JDBC, a proxy module, benchmark, test and code coverage modules, plus a documentation site, an examples directory, a wiki and a skills directory. There is also a Gradle build with a wrapper and a renovate configuration, which indicates dependency automation.
That is a lot of surface for a library whose core job is generating a number. The breadth is defensible if you are building a Spring Boot service that needs IDs in several subsystems, since each integration is work you would otherwise write. It is overkill if you need one generator and one store, and in that case the JDBC or Redis module with the core is a much smaller thing to depend on. The number of modules is also the number of places a version upgrade touches.
Editorial conclusion
CosId suits a Java service that needs collision-free IDs across replicas and would rather not make a network call per ID, and it suits teams already on Spring Boot who can pick the store they already operate. It does not suit an application that only needs a random UUID, and it does not suit a team unwilling to run a coordination store, since the uniqueness guarantee depends on that store being reachable at startup. Verify first that the store you intend to use is one of the documented backends, that the segment step you configure is compatible with the number of instances you run, and that the machine id clock handling matches your deployment's tolerance for time moving backwards, then read MIGRATION-4.0.md before moving from the 3.x line.
Frequently asked questions
What is CosId and what problem does it solve?
CosId is a distributed ID generator for Java that produces IDs inside the process with no network call per ID. It coordinates ahead of time by leasing a machine id per Snowflake instance and taking ranges of segment IDs from a store you already run, and it also handles clocks that move backwards.
Which CosId generator should I use?
The documentation's table points at three options: SegmentChainId for short numeric keys or business numbers in near-sequential order, SnowflakeId when the ID should carry its creation time with no store call after startup, and CosIdGenerator for very many instances, up to a million machine ids, which produces a 15 character time-ordered string.
Which storage backends does CosId support?
The supported stores are Redis, JDBC against MySQL, MariaDB and PostgreSQL, MongoDB, ZooKeeper, the CosId proxy, or a store of your own. The Spring integration module for each is named in the dependency coordinates, for example cosid-spring-redis, cosid-jdbc, cosid-mongo, cosid-zookeeper or cosid-proxy.
How do I upgrade from CosId 3.x to 4.x?
The documentation points at a migration document, MIGRATION-4.0.md, and a migration guide page. The compatibility table shows 4.x requires Java 17 or newer and pairs with Spring Boot 4.x on the main branch, while 3.x stays on its own maintenance branch.
Is CosId faster than Meituan Leaf?
The project documentation states that SegmentChainId is about five times as fast as Meituan Leaf's segment mode, and links to a dedicated CosId versus Leaf comparison page. The throughput figures in the generator table are historical JMH benchmark results from a single MacBook Pro M1 with Redis on the same machine.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/ahoo-wang-cosid)Was this useful?