---
title: "8: Computed and asserted fields | SurrealDB University"
description: "COMPUTED duration, ASSERT on progress, and VALUE timestamps on the activity table."
url: https://surrealdb.com/learn/schemas/page-08
---

![Course content preview](https://surrealdb.com/assets/static/course-schemas.D4CFbBhP.avif)

[Back to Courses](https://surrealdb.com/learn)

Course chapters

[Schema internals and migrations](https://surrealdb.com/learn/schemas) Internals [1: Schemaless vs. schemafull](https://surrealdb.com/learn/schemas/page-01) [2: Schema internals](https://surrealdb.com/learn/schemas/page-02) [3: Migrations](https://surrealdb.com/learn/schemas/page-03) [4: Data types](https://surrealdb.com/learn/schemas/page-04) [5: Automation](https://surrealdb.com/learn/schemas/page-05) Migrations [6: SurrealKit and the first table](https://surrealdb.com/learn/schemas/page-06) [7: Activities and seed data](https://surrealdb.com/learn/schemas/page-07) [8: Computed and asserted fields](https://surrealdb.com/learn/schemas/page-08) [9: Graph dependencies](https://surrealdb.com/learn/schemas/page-09) [10: Sync vs rollouts](https://surrealdb.com/learn/schemas/page-10) [11: Milestones](https://surrealdb.com/learn/schemas/page-11) [12: People and indexes](https://surrealdb.com/learn/schemas/page-12) [13: Events and CI](https://surrealdb.com/learn/schemas/page-13) [14: Capstone](https://surrealdb.com/learn/schemas/page-14)

# 8: Computed and asserted fields

Part [5](https://surrealdb.com/learn/schemas/page-05) introduced these field clauses in isolation. Here they land in committed schema files for the planning domain, matching the [project planning sample](https://surrealdb.com/docs/learn/schema-management/schema-design/sample-industry-schemas#project-planning) activity table.

As you go through this chapter, add each `DEFINE` statement to `database/schema/activity.surql`. You'll apply all of them together with a single `surrealkit sync` at the end.

## COMPUTED duration

Duration shouldn't be stored and maintained by application code when both endpoints already live on the record.

```surql
DEFINE FIELD duration ON activity COMPUTED end - start;
```

`COMPUTED` fields are evaluated on read (and during projections that need them), not stored at write time. That avoids stale durations when someone updates `end` without touching a separate column.

```surql
SELECT name, start, end, duration FROM activity;
```

## ASSERT progress range

Replace the bare `TYPE float` line for `progress` in `activity.surql` with a constrained range. Don't leave both definitions in the file: SurrealKit treats each `DEFINE FIELD` as one catalog object keyed by table and field name, so two `progress` lines produce duplicate metadata and can break a later `rollout`. Reach for a range `ASSERT` on numeric bounds, and a literal union when the set is categorical instead (see part [4](https://surrealdb.com/learn/schemas/page-04)).

```surql
DEFINE FIELD progress ON activity TYPE float ASSERT $value IN 0.0..=1.0;
```

Invalid writes fail at the field layer:

```surql
UPDATE activity:concrete SET progress = 1.5;
-- Field assertion failure
```

For a custom message, use `ASSERT` with `THROW`, as in part [5](https://surrealdb.com/learn/schemas/page-05).

## VALUE for rolling timestamps (preview)

The milestone table uses `VALUE` `time::now()` on `last_updated` in the docs sample. On `activity`, you might add:

```surql
DEFINE FIELD updated_at ON activity VALUE time::now();
```

`VALUE` runs on every create and update, which is useful for "last touched" columns. `DEFAULT` `time::now()` only fills in missing values on create, unless you add `ALWAYS`.

Once the three edits above are in `activity.surql`, apply them with one sync:

```bash
surrealkit sync --user root --pass secret --ns main --db main
```

Existing records pick up `COMPUTED` `duration` immediately on the next `SELECT`. `ASSERT` only applies to new writes; if legacy data already violates the range, backfill it before you tighten the field (part [3](https://surrealdb.com/learn/schemas/page-03)).

## Alter vs edit the file

On a shared database, changing a field definition is a migration:

- Local dev: edit `activity.surql` and `sync`
- Staging/production: `rollout plan` → `start` → deploy → `complete` (parts [10](https://surrealdb.com/learn/schemas/page-10)–[11](https://surrealdb.com/learn/schemas/page-11))

`ALTER FIELD` in the shell and editing the `.surql` file should describe the same end state.

## Checkpoint

| Clause | Role on `activity` |
| --- | --- |
| `COMPUTED` `duration` | Derived from `start` / `end` |
| `ASSERT` on `progress` | Enforces 0.0..=1.0 |
| `VALUE` `updated_at` | Optional audit column |

Next: model the dependency graph between activities and projects with `RELATION` tables.

Previous

7: Activities and seed data

[Previous](https://surrealdb.com/learn/schemas/page-07)

Next lesson

9: Graph dependencies

[Next lesson](https://surrealdb.com/learn/schemas/page-09)

```json
{"@context":"https://schema.org","@type":"Course","name":"Schema internals and migrations","description":"Learn how SurrealDB stores schema metadata, how DEFINE statements shape your database, and how to migrate production data safely.","url":"https://surrealdb.com/learn/schemas","inLanguage":"en","isAccessibleForFree":true,"provider":{"@type":"Organization","name":"SurrealDB","url":"https://surrealdb.com"},"hasPart":[{"@type":"LearningResource","name":"Schema internals and migrations","url":"https://surrealdb.com/learn/schemas"},{"@type":"LearningResource","name":"1: Schemaless vs. schemafull","url":"https://surrealdb.com/learn/schemas/page-01"},{"@type":"LearningResource","name":"2: Schema internals","url":"https://surrealdb.com/learn/schemas/page-02"},{"@type":"LearningResource","name":"3: Migrations","url":"https://surrealdb.com/learn/schemas/page-03"},{"@type":"LearningResource","name":"4: Data types","url":"https://surrealdb.com/learn/schemas/page-04"},{"@type":"LearningResource","name":"5: Automation","url":"https://surrealdb.com/learn/schemas/page-05"},{"@type":"LearningResource","name":"6: SurrealKit and the first table","url":"https://surrealdb.com/learn/schemas/page-06"},{"@type":"LearningResource","name":"7: Activities and seed data","url":"https://surrealdb.com/learn/schemas/page-07"},{"@type":"LearningResource","name":"8: Computed and asserted fields","url":"https://surrealdb.com/learn/schemas/page-08"},{"@type":"LearningResource","name":"9: Graph dependencies","url":"https://surrealdb.com/learn/schemas/page-09"},{"@type":"LearningResource","name":"10: Sync vs rollouts","url":"https://surrealdb.com/learn/schemas/page-10"},{"@type":"LearningResource","name":"11: Milestones","url":"https://surrealdb.com/learn/schemas/page-11"},{"@type":"LearningResource","name":"12: People and indexes","url":"https://surrealdb.com/learn/schemas/page-12"},{"@type":"LearningResource","name":"13: Events and CI","url":"https://surrealdb.com/learn/schemas/page-13"},{"@type":"LearningResource","name":"14: Capstone","url":"https://surrealdb.com/learn/schemas/page-14"}]}
```

```json
{"@context":"https://schema.org","@type":"LearningResource","name":"8: Computed and asserted fields","description":"COMPUTED duration, ASSERT on progress, and VALUE timestamps on the activity table.","url":"https://surrealdb.com/learn/schemas/page-08","learningResourceType":"lesson","isPartOf":{"@type":"Course","name":"Schema internals and migrations","url":"https://surrealdb.com/learn/schemas"},"position":11}
```

```json
{"@context":"https://schema.org","@type":"Organization","name":"SurrealDB","url":"https://surrealdb.com","logo":"https://surrealdb.com/assets/static/logo.BG7_TG2b.svg","description":"SurrealDB is the unified data layer for AI. A multi-model database for documents, graphs, vectors, and time-series.","foundingDate":"2022","legalName":"SurrealDB Ltd","identifier":{"@type":"PropertyValue","propertyID":"GB-COH","value":"13615201"},"address":{"@type":"PostalAddress","streetAddress":"3rd Floor, 1 Ashley Road","addressLocality":"Altrincham","addressRegion":"Cheshire","postalCode":"WA14 2DT","addressCountry":"GB"},"contactPoint":[{"@type":"ContactPoint","contactType":"customer support","email":"support@surrealdb.com","url":"https://surrealdb.com/contact","availableLanguage":"English"},{"@type":"ContactPoint","contactType":"sales","email":"info@surrealdb.com","url":"https://surrealdb.com/contact","availableLanguage":"English"},{"@type":"ContactPoint","contactType":"security","email":"security@surrealdb.com","url":"https://surrealdb.com/.well-known/security.txt","availableLanguage":"English"},{"@type":"ContactPoint","contactType":"legal","email":"legal@surrealdb.com","url":"https://surrealdb.com/legal","availableLanguage":"English"}],"hasCertification":[{"@type":"Certification","name":"SOC 2 Type 2"},{"@type":"Certification","name":"GDPR"},{"@type":"Certification","name":"Cyber Essentials Plus"},{"@type":"Certification","name":"ISO 27001"}],"owns":[{"@type":"SoftwareApplication","name":"SurrealDB","url":"https://surrealdb.com/surrealdb"},{"@type":"SoftwareApplication","name":"Agent Memory","url":"https://surrealdb.com/agent-memory"}],"knowsAbout":["multi-model databases","document databases","graph databases","vector search","time-series databases","SurrealQL","Agent Memory","real-time databases","embedded databases","context layer","graph ontology","distributed database","knowledge graphs","distributed transaction protocols","highly-scalable databases"],"sameAs":["https://www.wikidata.org/wiki/Q124316308","https://github.com/surrealdb/surrealdb","https://twitter.com/surrealdb","https://www.youtube.com/@surrealdb","https://www.linkedin.com/company/surrealdb","https://discord.gg/surrealdb","https://www.reddit.com/r/surrealdb","https://www.instagram.com/surrealdb","https://medium.com/surrealdb","https://dev.to/surrealdb"]}
```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://surrealdb.com"},{"@type":"ListItem","position":2,"name":"Learn","item":"https://surrealdb.com/learn"},{"@type":"ListItem","position":3,"name":"Page 08","item":"https://surrealdb.com/learn/schemas/page-08"}]}
```
