# Competitive analysis
This document compares adotenv with common Rust `.env` parsers and loaders. The
goal is to identify concrete work, not to rank libraries on a single number.
## Comparison set
- `adotenv` 0.10.3
- `dotenvy` 0.15.7
- `dotenv` 0.15.0
- `dotenv-compat` 0.4.0
- `dotenv-ng-core` 1.0.0
- `dotenv-parser` 0.1.3
- `dotenv-linter` 4.0.0 for CLI comparison
## Method
Benchmarks use a release build on Linux x86_64. The fixture has 65,536 simple
`KEY=value` entries and a 1.4 MB source. Each library reads the source before
measurement, parses it, and builds a map where the library supports one.
- Wall time: `hyperfine`, five process runs, multiple parses per run, using the
median process time.
- Instructions: Valgrind callgrind, one parse, with a no-op baseline.
- Memory: `/proc/self/status` high-water mark and retained RSS, with a no-op
baseline.
- Binary size: stripped release binary with thin LTO for a parse-and-print
program.
- Dependencies and MSRV: crates.io metadata.
Run `python3 scripts/compare.py --update-doc` to regenerate the benchmark
section on an idle host.
## Results
Generated by `python3 scripts/compare.py`.
### Parse and map build
Per parse on the 65,536-entry fixture:
| adotenv parse | 31.9 ms | 234M | 26.6 MB | 26.6 MB |
| adotenv parse + values | 42.8 ms | 363M | 10.0 MB | 10.0 MB |
| adotenv parse + map | 38.8 ms | 301M | 32.4 MB | 14.4 MB |
| dotenvy iterator + map | 72.6 ms | 354M | 18.9 MB | 11.4 MB |
| dotenv-compat parse | 48.7 ms | 265M | 19.8 MB | 14.5 MB |
| dotenv-ng input-only | 126.8 ms | 378M | 26.5 MB | 20.5 MB |
| dotenv-parser map | 140.7 ms | 1239M | 25.3 MB | 10.6 MB |
Small-file parsing, in microseconds per parse:
| adotenv parse | 42.3 us |
| adotenv parse + values | 54.3 us |
| adotenv parse + map | 50.3 us |
| dotenvy iterator + map | 85.0 us |
| dotenv-compat parse | 59.0 us |
| dotenv-ng input-only | 74.4 us |
| dotenv-parser map | 215.3 us |
### Loader profiles
Per load on the 65,536-entry fixture:
| values-only load | 46.9 ms | 364M | 11.2 MB | 10.1 MB |
| default load | 93.9 ms | 502M | 47.7 MB | 28.0 MB |
| full-report load | 135.8 ms | 683M | 57.2 MB | 37.9 MB |
### Parse-only binaries
| adotenv | 446 KB |
| dotenv_compat | 367 KB |
| dotenv_ng | 404 KB |
| dotenv_parser | 449 KB |
| dotenvy | 386 KB |
Wall time varies with host load. Instruction counts are the stable CPU metric.
adotenv parse uses fewer instructions than every measured alternative. Its
parse-plus-map path uses more instructions than dotenv-compat and fewer than
dotenvy. adotenv also retains more document memory because it keeps spans, items
and diagnostics. The values-only projection path is the correct comparison for
applications that do not need provenance.
### Footprint
| adotenv | 0 | 1.81 |
| dotenvy | 0 | 1.56 |
| dotenv | 0 | not declared |
| dotenv-compat | 4 | 1.85 |
| dotenv-ng-core | 0 | 1.74 |
| dotenv-parser | 2 | not declared |
adotenv has no required runtime dependencies and supports `no_std` with `alloc`.
Its parse-only binary is within about 22 percent of the smallest measured binary.
## Capability matrix
| Literal parse | Yes | Yes | Yes | Yes | Yes | Yes |
| Map or iterator API | Both | Iterator | Loader | Map | Map | Map |
| Lossless source | Yes | No | No | No | No | No |
| Token spans and positions | Yes | No | No | No | No | No |
| Recovery diagnostics | Yes | Limited | No | Limited | Errors | Errors |
| Multiple syntax presets | 5 | 1 | 1 | Node | 1 | 1 |
| Verified edits and formatting | Yes | No | No | No | No | No |
| Sort, compare and examples | Yes | No | No | No | No | No |
| Reference inspection | Yes | No | No | No | No | No |
| Explicit resolution | Yes | No | No | No | Substitution | No |
| Cascade loading and provenance | Yes | Search/load | Search/load | Files | Multiple files | No |
| Values-only projection | Yes | No | No | No | No | No |
| Serde | Yes | No | No | No | No | No |
| CLI | Yes | No | No | No | No | No |
| `no_std` | Yes | No | No | No | No | No |
`dotenv-linter` is a separate CLI category. It provides lint rules and fixes but
does not expose adotenv's library model or loader provenance.
## Correctness
adotenv has a pinned conformance corpus for Node, Python, Compose and Docker
behavior. It also has parser, edit, encoding, resolution and formatting fuzz
targets.
The main gap is breadth, not absence. Add more pinned symbols and differential
checks against Node and Python, especially for malformed and multiline cases.
Keep every observation tied to a source identity and input hash.
## Documentation
adotenv has 20 public documents covering architecture, dialects, edits,
formatting, resolution, loading, serde, CLI, integrations, quality and
performance. Examples in the README are doctested.
Gaps:
- no dedicated documentation site;
- no guided tutorial or task-based examples;
- design examples are not compiled;
- no searchable API-to-task index;
- no published benchmark dashboard;
- `adotenv.github.io` is unavailable because there is no `adotenv` GitHub
organization.
A project site can use `asamarts.github.io/adotenv` now, or a custom domain, or
an `adotenv` organization if that name can be created.
## API assessment
Strengths:
- one parse result supports inspection, edits, comparison and formatting;
- policy is explicit and composable;
- errors and diagnostics are structured;
- loading and process mutation stay opt-in;
- values, origins and reports are borrowed views.
Risks:
- the public surface is broad for new users;
- similar concepts use several types (`Document`, `Entry`, `Item`, views,
`LoadedEnvironment`, `ResolvedEnvironment`);
- examples are spread across the README and design docs;
- the migration from parse to edit to load is not presented as a single guided
path.
The next step is a task-based API audit, not a redesign.
## Priorities
1. Commit a reproducible comparison harness and keep these numbers current.
2. Build a documentation site with a tutorial, task guides and search.
3. Improve values-only performance and memory measurements against the same
fixture.
4. Expand conformance and differential tests.
5. Audit common-task APIs and consolidate examples.
6. Close feature gaps only where they fit the literal, explicit design. File
encryption, implicit environment search and ambient command execution are not
automatic goals.
7. Complete the 1.0 evidence for fuzzing and external adoption.