# Poem Web Framework: A Rust HTTP Framework With OpenAPI, gRPC and MCP Crates

> Poem is a Rust web framework whose workspace splits HTTP, OpenAPI, gRPC, AWS Lambda and MCP server support into separate crates. It suits teams that want one routing model across all of those targets; it is the wrong pick if you need an HTTP framework with no proc-macro layer.

**poem-web/poem** — A full-featured and easy-to-use web framework with the Rust programming language.

- Repository: https://github.com/poem-web/poem
- Stars: 4,443 · Forks: 360
- Language: Rust
- License: Apache-2.0
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/poem-web-poem

## What Poem Web solves, and who it is built for

Poem is a web framework for the Rust programming language. The repository describes it as "full-featured and easy-to-use", and the workspace layout shows what "full-featured" means in practice: HTTP routing lives in the poem crate, OpenAPI support in poem-openapi, gRPC in poem-grpc, AWS Lambda integration in poem-lambda, and an MCP server implementation in poem-mcpserver. That split is the actual product decision. Instead of one large crate with feature flags for every transport, Poem ships a small core and lets you pull in the protocol surface you need.

The audience is Rust developers building services that need more than a router. If you are writing an HTTP API and also want to publish an OpenAPI document, or you want the same handler style for a gRPC service, or you want to deploy to AWS Lambda without rewriting your routes, the workspace gives you a crate for each of those. The community use list in the README includes a distributed task scheduler, a cloud-native data warehouse, an SSH bastion host, an image server and a Layer 1 blockchain, which suggests the framework is used for long-running backend services rather than only for small demos.

It is not aimed at people who want to avoid macros. The repository contains poem-derive, poem-openapi-derive and poem-mcpserver-macros, so attributes and derive macros are part of how routes and schemas are declared. If you prefer a framework where routing is expressed purely through function calls and trait implementations, that design choice will feel like overhead.

## How the Poem workspace is put together

The root Cargo.toml declares a workspace with resolver 2 and lists ten members: poem-derive, poem, poem-openapi-derive, poem-openapi, poem-lambda, poem-grpc-build, poem-grpc, poem-mcpserver, poem-mcpserver-macros and poem-worker. The workspace package section sets edition to 2024 and rust-version to 1.85, and the README badge states rustc 1.85.0+.

Shared dependencies are pinned once in the workspace.dependencies table and inherited by members. That table shows tokio 1.39.1 for the async runtime, http 1.0.0 for the HTTP types, rustls 0.23 and tokio-rustls 0.26 for TLS (with a comment saying they are updated together), serde and serde_json for serialisation, plus sonic-rs, quick-xml, serde_urlencoded and base64 for other formats. The workspace also depends on poem itself at version 3.1.12, poem-openapi-derive at 5.1.15, poem-grpc-build at 0.5.9 and poem-mcpserver-macros at 0.3.1. Those version numbers are the workspace's own internal pins, not a promise about what you will resolve from crates.io.

The data flow is the ordinary one for a Rust HTTP service: a request arrives, the server matches it against the routes you registered, extractors pull typed data out of the request, your handler runs as an async function, and a response is serialised back. What Poem adds is the macro layer on top. poem-derive supplies the route attributes, poem-openapi-derive generates schema and document code from your types, and poem-mcpserver-macros does the equivalent for MCP tool definitions. The separate build crate, poem-grpc-build, is what turns proto definitions into Rust code for the gRPC side.

There is one structural detail worth noticing. Because poem-openapi depends on poem-openapi-derive, and poem-mcpserver depends on poem-mcpserver-macros, the macro crates are not optional extras you can avoid by picking a different feature set. Choosing the OpenAPI crate means choosing its derive crate too.

## Getting the Poem crate into a project

The repository does not include a step-by-step install section. What it does provide is the crate table: poem, poem-lambda, poem-openapi, poem-grpc and poem-mcpserver each carry a crates.io badge and a link to their own README, and the README points readers to the examples directory for usage. So the documented route into the project is the published crates plus the per-crate README files and the examples tree.

Dependency declarations follow the workspace pattern shown in the root Cargo.toml, where members inherit from the workspace table rather than repeating versions. A dependency entry for the core crate, using the version the workspace itself pins, looks like this:

```toml
[dependencies]
poem = { version = "3.1.12", default-features = false }
```

The workspace declares poem with default-features set to false, so enabling features is a deliberate step rather than a default. Read the poem crate README for the feature list before copying this line, because the root Cargo.toml only shows the pin, not what the features do.

The workspace also shows how the macro crates appear as dependencies, which matters if you add the OpenAPI or MCP surface:

```toml
poem-openapi-derive = { path = "poem-openapi-derive", version = "5.1.15" }
poem-mcpserver-macros = { path = "poem-mcpserver-macros", version = "0.3.1" }
```

Those two lines use path dependencies because they are written from inside the repository. In your own project you would depend on the published poem-openapi and poem-mcpserver crates instead and let them bring their derive crates in. The repository's examples directory is the place to look for working handler code: it is split into subdirectories for openapi, grpc, mcpserver and poem, and there is also a disabled directory, which suggests some examples are kept but not built by default.

One practical constraint: the workspace targets edition 2024 with rust-version 1.85, so a toolchain older than 1.85 will not build these crates. Check your rustc version before adding the dependency, because the failure appears at build time rather than at resolution time.

## Where Poem Web gets in your way

The macro layer is the first limitation. Routes, OpenAPI schemas and MCP tools are all declared through proc macros, and proc-macro expansion is harder to debug than ordinary function calls. When a derive does not produce what you expect, the error messages come from generated code, and you cannot step through them the way you would step through a hand-written router. Projects that treat macro-generated code as a maintenance risk should weigh that before adopting the OpenAPI or MCP crates specifically, even if they are comfortable with the core HTTP crate.

Version skew across the workspace is the second issue. The crates move at different speeds: the workspace pins poem at 3.1.12 and poem-openapi-derive at 5.1.15, which is a major-version gap between the core crate and the OpenAPI derive crate. Each crate has its own CHANGELOG file in its own directory, and the root README links to them individually. That means an upgrade is not a single version bump you can reason about from one file. If you depend on poem, poem-openapi and poem-grpc together, you should read three changelogs and check that the resolved versions are compatible before you update.

Third, the README does not document a rollback path for a bad upgrade, and it does not describe a migration procedure between major versions. The repository has a SECURITY.md, which indicates a security reporting process exists, but the README itself is a component table, a list of community users, a link to examples and licence text. Anyone who needs documented upgrade and rollback procedures will have to build them from the per-crate CHANGELOG files. That is a real gap for teams running long-lived services.

Finally, the release list shows v2.0.0 dated 2022-05-31 and poem-openapi 2.0.0-alpha.1 dated 2022-05-15. Those are the recent releases as recorded, and they are years behind the version numbers pinned in the workspace Cargo.toml. The practical consequence is that release notes are not a reliable guide to what the current code does. The CHANGELOG files and the examples directory are.

## Poem against Axum: two different bets on macros

The most common comparison for Poem is Axum, another Rust HTTP framework built on the same tower and hyper layer of the ecosystem. The difference that matters is not performance, which neither README documents in a comparable way, but how much of the API surface is generated by macros.

Poem leans on derive and attribute macros for routing, OpenAPI schemas and MCP tool definitions. That is what makes it possible for one set of handler signatures to produce an HTTP endpoint and a matching OpenAPI document, or an MCP tool, without you writing the schema by hand. The cost is that the macro crates are part of your dependency graph and part of your compile times, and that errors surface in generated code.

Axum takes the other approach: routing is composed from typed function calls and extractor traits, with no framework-specific derive macro in the core path. You get more explicit code and errors that point at your own source lines, and you give up the automatic schema generation that Poem's OpenAPI crate provides. If your service needs a published OpenAPI document that stays in sync with the handlers, Poem's approach removes a class of drift; if you do not need that document, Axum's explicitness is easier to reason about.

The choice also depends on transports. Poem ships poem-grpc and poem-lambda as first-party crates in the same workspace, so an HTTP service, a gRPC service and a Lambda deployment can share the workspace dependency table. If you only need HTTP, that breadth is unused weight in your Cargo.toml.

## Maintenance, licensing and what an upgrade costs

The repository is not archived, and the last push was on 2026-09-22. The workspace is on edition 2024 and requires rustc 1.85 or newer, which puts it on a recent toolchain rather than a conservative one. Because the crates are versioned independently, the upgrade cost is proportional to how many of them you depend on. A project using only the poem crate tracks one CHANGELOG. A project using poem, poem-openapi, poem-grpc and poem-mcpserver tracks four, and the workspace pins show that their version numbers do not move in lockstep.

Licensing is dual. The README states the project is licensed under either the Apache License, Version 2.0 or the MIT license, at your option, with both licence files present at the repository root (LICENSE-APACHE and LICENSE-MIT). The workspace package metadata records the same choice as "MIT OR Apache-2.0". The contributing section adds a term worth reading before you send patches: unless you explicitly state otherwise, any contribution you intentionally submit for inclusion is licensed as Apache. That is a default inbound licence term, and if you or your employer care about the licence of your contributions, read the full text in the README rather than relying on this summary. Nothing here is legal advice.

On maintenance signals, the README lists community projects built on Poem, including poem-casbin for access control middleware and poem-grants for endpoint authorisation. Those live in other repositories, so their release cadence is not tied to this one. If you depend on either, check them separately.

## Conclusion

Adopt Poem if you already write Rust and want HTTP, OpenAPI and gRPC handlers built from the same route and extractor model, and you are willing to accept proc macros and an edition 2024 toolchain of rustc 1.85 or newer. Do not adopt it if you want a framework with no macro layer, or if you need an HTTP framework that runs on a stable toolchain older than 1.85. Before committing, check the documentation for the poem crate version you actually resolve, confirm which crates you need from the workspace table, and read the CHANGELOG in the crate directory you depend on rather than the repository root.

## FAQ

### What is the Poem Rust framework?

Poem is a web framework written in Rust, described in its README as full-featured and easy-to-use. The repository is a workspace whose main components are the poem HTTP crate plus separate crates for OpenAPI, gRPC, AWS Lambda and MCP server support.

### Where do I get the Poem crate?

The README's component table links each crate to crates.io, including poem, poem-lambda, poem-openapi, poem-grpc and poem-mcpserver. The README also points to the examples directory in the repository for usage.

### What Rust version does Poem require?

The workspace Cargo.toml sets rust-version to 1.85, and the README badge states rustc 1.85.0+. The workspace also targets edition 2024, so an older toolchain will fail at build time.

### What licence is Poem released under?

The README states the project is licensed under either the Apache License, Version 2.0 or the MIT license, at your option, with LICENSE-APACHE and LICENSE-MIT at the repository root. The contributing section says contributions are licensed as Apache unless you explicitly state otherwise.

## Sources

- [Issues](https://github.com/poem-web/poem/issues)
- [License: Apache-2.0](https://github.com/poem-web/poem/blob/master/LICENSE)
- [poem-web/poem on GitHub](https://github.com/poem-web/poem)
- [README](https://github.com/poem-web/poem/blob/master/README.md)
- [Releases](https://github.com/poem-web/poem/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/poem-web-poem
