# Validation cost for tapir's Schema

**URL:** <https://softwaremill.community/t/validation-cost-for-tapirs-schema/538>\
**Category:** tapir\
**Created:** [February 6, 2026, 1:13pm UTC](https://softwaremill.community/t/validation-cost-for-tapirs-schema/538 "2026-02-06T13:13:13Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![susliko](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/susliko/32/345_2.png) [@susliko](https://softwaremill.community/u/susliko)\
**Post date:** [February 6, 2026, 1:13pm UTC](https://softwaremill.community/t/validation-cost-for-tapirs-schema/538/1 "2026-02-06T13:13:13Z")

</div>

Hi! I am meditating over cpu profiles of an app running in production that uses tapir (with circe for json). I can see that a noticeable amount of samples are pointing at tapir Schema `applyFieldsValidation` method. The app does not specify any custom validations for the Schema instances of its models, all the schemas are derived automatically.

Meanwhile some default validations happen all the time. What are these validations? Are they really needed if all the input structure is checked to be correct by json codec (circe in this case)?

Looking at the code of [hasValidation](https://github.com/softwaremill/tapir/blob/3d14c0689dd2401962087945ad2353d489609ec2/core/src/main/scala/sttp/tapir/Schema.scala#L298) it looks like only `SRef` provides some validations by default.

 ![image](https://europe1.discourse-cdn.com/flex005/uploads/softwaremill/original/1X/a80cdbcc7507f8d60f495f4704978c580b0318e1.png)

---

<div class="post-metadata">

**Author:** ![susliko](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/susliko/32/345_2.png) [@susliko](https://softwaremill.community/u/susliko)\
**Post date:** [February 6, 2026, 1:28pm UTC](https://softwaremill.community/t/validation-cost-for-tapirs-schema/538/2 "2026-02-06T13:28:28Z")

</div>

There is a hacky way to disable schema validation at all. But i wonder what would be a recommended approach

```java
object codec extends TapirJsonCirce:
  override implicit def circeCodec[T](
      implicit encoder: Encoder[T],
      decoder: Decoder[T],
      schema: Schema[T],
  ): JsonCodec[T] =
    val schemaWithoutValidation = new Schema(
      schema.schemaType,
      schema.name,
      schema.isOptional,
      schema.description,
      schema.default,
      schema.format,
      schema.encodedExample,
      schema.deprecated,
      schema.hidden,
      schema.validator,
      schema.attributes,
    ):
      override def applyValidation(t: T): List[ValidationError[?]] = Nil
    super.circeCodec[T](using encoder, decoder, schemaWithoutValidation)

```

---

<div class="post-metadata">

**Author:** ![adamw](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/adamw/32/28_2.png) [@adamw](https://softwaremill.community/u/adamw)\
**Post date:** [February 9, 2026, 3:40pm UTC](https://softwaremill.community/t/validation-cost-for-tapirs-schema/538/3 "2026-02-09T15:40:15Z")

</div>

Well there is this optimiziation which should only trigger validation if there’s any:

> <https://github.com/softwaremill/tapir/blob/master/core/src/main/scala/sttp/tapir/Schema.scala#L280>

This relies on `hasValidation` - maybe this should be a `lazy val`, not ` def`, to avoid recomputing. But that would need to be validated in some microbenchmark.

Can you check if your schema has `hasValidation = true`? Or what kind of validators are there in the object tree?

With `SRef`, it’s not really that validations exist - rather, at the point of checking if they DO exist, we don’t know what the reference resolves to. So the target schema might, or might not have validations. Hence the safe option is `true`, meaning in fact “I don’t know”.

Validations also do exist if `validator != Validator.pass`.

---

<div class="post-metadata">

**Author:** ![susliko](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/susliko/32/345_2.png) [@susliko](https://softwaremill.community/u/susliko)\
**Post date:** [February 10, 2026, 11:48am UTC](https://softwaremill.community/t/validation-cost-for-tapirs-schema/538/4 "2026-02-10T11:48:28Z")

</div>

Ah, i see now. In my case validators are brought by enums as we define schemas for them like this:

```auto
given TapirSchema[MyEnum] =
  TapirSchema.derivedEnumeration.defaultStringBased

```

Thanks!

Now I wonder what would be the best way to make a schema for enums so that it still provides a correct documentation, but does not introduce runtime checks.

---

<div class="post-metadata">

**Author:** ![susliko](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/susliko/32/345_2.png) [@susliko](https://softwaremill.community/u/susliko)\
**Post date:** [February 10, 2026, 1:23pm UTC](https://softwaremill.community/t/validation-cost-for-tapirs-schema/538/5 "2026-02-10T13:23:50Z")

</div>

Probably I should stick to

```auto
Schema.derivedEnumeration.defaultStringBased.copy(validator = Validator.pass)

```

---

<div class="post-metadata">

**Author:** ![adamw](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/adamw/32/28_2.png) [@adamw](https://softwaremill.community/u/adamw)\
**Post date:** [February 24, 2026, 12:52pm UTC](https://softwaremill.community/t/validation-cost-for-tapirs-schema/538/6 "2026-02-24T12:52:47Z")

</div>

See: [Skip runtime validation for derived enumeration validators by adamw · Pull Request #5088 · softwaremill/tapir · GitHub](https://github.com/softwaremill/tapir/pull/5088)
