Series MapLesson 37 / 60
Focus mode active/Press Alt+Shift+R to toggle/Esc to exit
Deepen PracticeOrdered learning track

Distributed Tracing and Application Observability

Distributed tracing dengan trace, span, correlation ID, OpenTelemetry, AWS X-Ray awareness, Azure Application Insights awareness, HTTP, Kafka/RabbitMQ, cloud SDK, sampling, dan high-cardinality risk.

15 min read2830 words
PrevNext
Lesson 3760 lesson track34–50 Deepen Practice
#aws#azure#observability#distributed-tracing+7 more

Part 037 — Distributed Tracing and Application Observability

Target pembaca: Senior Java/JAX-RS backend engineer yang perlu men-debug request lintas microservice, Kubernetes, broker, database, cloud SDK, managed service, dan private connectivity.

1. Konsep inti

Distributed tracing adalah teknik observability untuk mengikuti satu operasi bisnis atau technical request ketika request itu melewati banyak komponen: API gateway, ingress, service Java/JAX-RS, database, Kafka/RabbitMQ, Redis, cloud SDK, dan service lain.

Tracing bukan pengganti log dan metric.

Tracing menjawab pertanyaan seperti:

  • request ini melewati service apa saja?
  • latency terbesar ada di layer mana?
  • call downstream mana yang gagal?
  • apakah retry terjadi?
  • apakah Kafka publish terjadi setelah HTTP request?
  • apakah cloud SDK call ke S3/Blob/Secret Manager/Key Vault timeout?
  • apakah error terjadi di service kita, dependency, network, identity, atau cloud platform?

Model observability yang matang biasanya memakai tiga sinyal utama:

SignalMenjawabContoh
LogsApa yang terjadi secara detail?error stack trace, request validation failure, SQL exception
MetricsSeberapa sering dan seberapa parah?p95 latency, error rate, queue lag, retry count
TracesDi mana dalam request path masalah terjadi?span API gateway -> service A -> PostgreSQL -> Kafka

OpenTelemetry menjadi standar de facto untuk instrumentation vendor-neutral. AWS dapat menerima trace melalui AWS X-Ray atau pipeline berbasis ADOT. Azure dapat menerima trace melalui Application Insights atau Azure Monitor OpenTelemetry pipeline.

2. Istilah penting

IstilahMakna praktis
TraceRepresentasi satu perjalanan request atau workflow end-to-end.
SpanSatu unit kerja dalam trace, misalnya HTTP handler, SQL query, Kafka publish, atau S3 upload.
Trace IDID global yang mengikat seluruh span dalam satu trace.
Span IDID satu span tertentu.
Parent spanSpan yang memanggil atau menyebabkan span lain.
Root spanSpan pertama dalam trace, biasanya entry point request.
Correlation IDID aplikasi/bisnis untuk menghubungkan log, trace, dan request. Bisa sama atau berbeda dari trace ID.
Causation IDID event atau command yang menyebabkan event lain. Penting untuk async messaging.
BaggageMetadata kontekstual yang ikut dipropagasikan. Harus dibatasi karena risiko leakage dan high cardinality.
PropagatorMekanisme membawa context tracing via HTTP header atau message header.
SamplingKeputusan menyimpan sebagian trace agar biaya dan volume tetap terkendali.

3. Mental model trace untuk Java/JAX-RS service

Service Java/JAX-RS di Kubernetes biasanya berada di tengah banyak layer:

flowchart LR Client[Client / Partner / UI] --> DNS[DNS] DNS --> Edge[WAF / Gateway / Load Balancer] Edge --> Ingress[NGINX / ALB / App Gateway] Ingress --> Service[Kubernetes Service] Service --> Pod[Java JAX-RS Pod] Pod --> DB[(PostgreSQL)] Pod --> Cache[(Redis)] Pod --> Broker[Kafka / RabbitMQ] Pod --> CloudSDK[AWS/Azure SDK] CloudSDK --> Storage[S3 / Blob] CloudSDK --> Secret[Secrets Manager / Key Vault] CloudSDK --> Config[Parameter Store / App Configuration]

Trace yang baik tidak hanya memperlihatkan HTTP handler. Trace yang baik memperlihatkan dependency graph runtime:

flowchart TD A[POST /quotes] --> B[Quote Service] B --> C[Catalog Service] B --> D[(PostgreSQL)] B --> E[(Redis)] B --> F[Kafka publish quote.created] B --> G[S3/Blob export attachment] B --> H[Key Vault/Secrets Manager lookup]

Tanpa trace, engineer sering hanya melihat "request lambat". Dengan trace, engineer bisa melihat request lambat karena:

  • DNS lookup lambat,
  • connection pool exhausted,
  • PostgreSQL query lambat,
  • Kafka publish blocking,
  • Redis timeout,
  • SDK retry ke object storage,
  • secret/config call terjadi di hot path,
  • thread pool saturated,
  • private endpoint routing bermasalah,
  • downstream service returning 503,
  • retry policy memperparah latency.

4. Apa yang harus di-instrument

Minimal instrumentation untuk service Java/JAX-RS production:

AreaYang perlu ditangkap
HTTP inboundmethod, route template, status, latency, trace ID, correlation ID
HTTP outboundtarget service, status, timeout, retry, latency
JAX-RS resourceroute handler span, business operation name
PostgreSQLquery category, latency, error, pool wait time; hindari raw SQL penuh jika mengandung data sensitif
Kafka/RabbitMQpublish/consume span, topic/queue, partition/routing key, lag context, message ID
Rediscommand category, latency, timeout, pool issue; hindari key penuh bila mengandung PII
AWS/Azure SDKservice name, operation, region, endpoint, retry count, throttling, timeout
Kubernetespod, namespace, deployment, container, node, cluster
Config/secretretrieval latency, cache hit/miss, error; jangan log value
Business operationquote creation, order submission, catalog validation, approval workflow

Jangan instrument secara naif

Instrumentation buruk bisa menjadi risiko produksi:

  • terlalu banyak span untuk operasi kecil,
  • menyimpan payload request/response,
  • menyimpan PII di attributes,
  • high-cardinality label seperti user ID, quote ID, order ID sebagai metric dimension,
  • sampling terlalu rendah sehingga incident tidak terlihat,
  • sampling terlalu tinggi sehingga biaya membengkak,
  • trace context tidak dipropagasikan ke async message,
  • trace ID tidak dicetak di log,
  • correlation ID tidak konsisten antar service.

5. Trace propagation melalui HTTP

Untuk HTTP, propagasi biasanya melalui header standar W3C Trace Context:

traceparent: 00-<trace-id>-<span-id>-<flags>
tracestate: vendor-specific-state

Prinsip production:

  • ingress/gateway tidak boleh membuang tracing headers tanpa alasan;
  • service harus melanjutkan trace context yang diterima;
  • outbound HTTP client harus mengirim trace context ke downstream;
  • log harus menyertakan trace ID dan correlation ID;
  • reverse proxy harus menjaga header penting selama aman;
  • header internal tidak boleh dipakai sebagai authorization tanpa validasi.

Contoh flow:

sequenceDiagram participant C as Client participant G as Gateway/APIM participant Q as Quote Service participant Cg as Catalog Service participant P as PostgreSQL C->>G: POST /quotes + correlation-id G->>Q: traceparent + correlation-id Q->>Cg: traceparent + correlation-id Q->>P: DB span Q-->>G: response G-->>C: response

6. Trace propagation melalui Kafka dan RabbitMQ

Async messaging lebih sulit daripada HTTP karena workflow tidak selalu punya immediate response.

Untuk Kafka/RabbitMQ:

  • trace context harus dimasukkan ke message headers;
  • consumer harus mengekstrak trace context dari headers;
  • producer span dan consumer span harus memiliki hubungan sebab-akibat;
  • correlation ID dan causation ID harus menjadi bagian dari message metadata;
  • retry, dead-letter, reprocessing, dan outbox pattern harus terlihat.

Contoh metadata message:

traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
x-correlation-id: corr-20260711-quote-81f2
x-causation-id: cmd-submit-quote-9b21
x-message-id: evt-quote-created-44ae

Untuk event-driven system, jangan menganggap trace sama dengan transaksi sinkron.

Satu HTTP request bisa menghasilkan event yang diproses jauh setelah response dikirim. Dalam kasus seperti ini, trace perlu menggambarkan hubungan causality, bukan hanya parent-child blocking call.

7. Trace propagation melalui cloud SDK

AWS SDK dan Azure SDK sering muncul sebagai span dependency:

  • S3.PutObject
  • S3.GetObject
  • SecretsManager.GetSecretValue
  • SSM.GetParameter
  • KMS.Decrypt
  • BlobClient.Upload
  • SecretClient.GetSecret
  • ConfigurationClient.GetConfigurationSetting

Hal yang perlu terlihat:

  • service cloud yang dipanggil,
  • operation name,
  • region,
  • endpoint host,
  • status/error code,
  • latency,
  • retry count,
  • throttling,
  • timeout,
  • credential resolution error,
  • private endpoint DNS result jika tersedia dari log/network diagnostic.

Cloud SDK call yang tampak kecil bisa menjadi akar masalah besar bila terjadi di hot path.

Contoh buruk:

POST /orders
  -> read secret from Key Vault on every request
  -> read feature flag from App Configuration on every request
  -> upload attachment to Blob with default timeout
  -> retry 3x without business timeout budget

Contoh lebih aman:

POST /orders
  -> use cached secret/config
  -> bounded timeout for object upload
  -> retry with jitter only for safe operation
  -> expose dependency metric and trace span

8. AWS implementation awareness

Di AWS, tracing bisa melibatkan beberapa opsi:

  • OpenTelemetry SDK atau Java agent,
  • AWS Distro for OpenTelemetry Collector,
  • AWS X-Ray backend,
  • CloudWatch metrics/logs correlation,
  • EKS add-on atau sidecar/daemonset collector jika digunakan,
  • AWS SDK instrumentation,
  • X-Ray trace ID compatibility jika memakai X-Ray pipeline.

Mental model AWS:

flowchart LR App[Java Pod] --> OTel[OpenTelemetry SDK / Java Agent] OTel --> Collector[ADOT / OTel Collector] Collector --> XRay[AWS X-Ray] Collector --> CloudWatch[CloudWatch Metrics/Logs] Collector --> Other[Vendor Backend if approved]

AWS-specific review points:

  • Apakah instrumentation memakai OpenTelemetry atau X-Ray SDK lama?
  • Apakah X-Ray SDK/Daemon dependency masih relevan atau perlu migrasi ke OpenTelemetry?
  • Apakah collector berjalan sebagai DaemonSet, sidecar, gateway, atau managed integration?
  • Apakah collector punya IAM permission minimal?
  • Apakah trace export menggunakan private networking atau public endpoint?
  • Apakah trace sampling dikontrol centrally?
  • Apakah trace attribute tidak mengandung PII?
  • Apakah CloudWatch log menyertakan trace ID?

9. Azure implementation awareness

Di Azure, tracing umumnya terhubung ke:

  • Azure Monitor Application Insights,
  • Azure Monitor OpenTelemetry distro,
  • Azure Monitor workspace atau Log Analytics,
  • AKS monitoring integration,
  • Java agent untuk Application Insights,
  • OpenTelemetry exporter/collector.

Mental model Azure:

flowchart LR App[Java Pod] --> OTel[OpenTelemetry / Java Agent] OTel --> Collector[OTel Collector / Azure Monitor Exporter] Collector --> AI[Application Insights] Collector --> AM[Azure Monitor] AM --> LAW[Log Analytics Workspace]

Azure-specific review points:

  • Apakah menggunakan Application Insights Java agent atau OpenTelemetry SDK?
  • Apakah instrumentation key/connection string disimpan aman?
  • Apakah ingestion endpoint reachable dari private cluster?
  • Apakah telemetry melewati proxy/firewall?
  • Apakah sampling dikonfigurasi?
  • Apakah dependency telemetry untuk HTTP, JDBC, messaging, dan Azure SDK aktif?
  • Apakah role name/instance name sesuai service dan environment?
  • Apakah telemetry dipisah per environment atau bercampur?

10. Java/JAX-RS implementation concerns

Untuk Java/JAX-RS, instrumentation bisa dilakukan dengan:

  • OpenTelemetry Java agent,
  • manual instrumentation menggunakan OpenTelemetry API,
  • framework integration dari runtime yang dipakai,
  • servlet filter atau JAX-RS filter,
  • HTTP client interceptor,
  • Kafka/RabbitMQ producer/consumer interceptor,
  • JDBC instrumentation,
  • SDK-specific instrumentation.

Filter untuk correlation ID

Di JAX-RS, biasanya perlu filter untuk:

  • menerima correlation ID dari request,
  • membuat correlation ID jika belum ada,
  • memasukkannya ke logging MDC,
  • menambahkannya ke response header,
  • memastikan outbound call membawa correlation ID.

Contoh konseptual:

@Provider
public class CorrelationIdFilter implements ContainerRequestFilter, ContainerResponseFilter {
    public void filter(ContainerRequestContext requestContext) {
        String correlationId = requestContext.getHeaderString("X-Correlation-ID");
        if (correlationId == null || correlationId.isBlank()) {
            correlationId = UUID.randomUUID().toString();
        }
        MDC.put("correlationId", correlationId);
        requestContext.setProperty("correlationId", correlationId);
    }

    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
        Object correlationId = requestContext.getProperty("correlationId");
        if (correlationId != null) {
            responseContext.getHeaders().putSingle("X-Correlation-ID", correlationId.toString());
        }
        MDC.remove("correlationId");
    }
}

Catatan production:

  • validasi panjang correlation ID;
  • jangan percaya correlation ID sebagai identity;
  • jangan log header sensitif;
  • jangan menaruh PII di trace attributes;
  • gunakan route template, bukan path literal berisi ID.

11. Attribute dan cardinality discipline

Trace attributes harus membantu debugging, bukan menjadi data lake liar.

Aman dan berguna

service.name=quote-service
deployment.environment=prod
cloud.provider=aws
cloud.region=ap-southeast-1
k8s.namespace.name=quote-order-prod
http.route=/quotes/{quoteId}/submit
http.method=POST
http.status_code=202
messaging.system=kafka
messaging.destination.name=quote-events
db.system=postgresql

Berisiko tinggi

customer.email=...
customer.name=...
quote.full_payload=...
order.address=...
authorization.header=...
session.token=...
raw.sql.with.literal.values=...

High cardinality risk

High cardinality berarti nilai attribute sangat banyak dan unik. Ini bisa merusak query performance dan menaikkan biaya.

Contoh berbahaya sebagai metric dimension:

  • userId,
  • quoteId,
  • orderId,
  • sessionId,
  • jwtSub,
  • fullUrl,
  • exceptionMessage yang mengandung nilai dinamis.

Untuk trace, ID bisnis kadang berguna, tetapi harus tunduk pada privacy dan cost policy. Biasanya lebih aman menyimpan ID bisnis di log yang access-controlled, bukan sebagai indexed metric dimension.

12. Sampling strategy

Sampling mengontrol trace mana yang disimpan.

StrategyKapan dipakaiRisiko
Always onDebug sementara, lower environment, critical short windowBiaya tinggi, noise besar
Fixed ratioNormal production baselineBisa melewatkan rare failure
Tail samplingSimpan trace berdasarkan outcome, misalnya error/latency tinggiButuh collector/backend lebih matang
Route-based samplingEndpoint penting disampling lebih tinggiSalah konfigurasi bisa bias
Error-biased samplingSimpan semua error traceError rendah tapi latency tinggi bisa terlewat

Rule of thumb:

  • simpan semua error trace jika cost memungkinkan;
  • simpan trace latency tinggi;
  • sampling lebih tinggi untuk endpoint critical;
  • sampling lebih rendah untuk high-volume health check;
  • jangan sampling health check seperti traffic bisnis;
  • dokumentasikan sampling agar engineer tidak salah menyimpulkan data.

13. Failure modes

SymptomKemungkinan penyebabCara deteksi
Trace terputus antar serviceheader traceparent dibuang gateway/ingress/clientcek headers di ingress, HTTP client interceptor, service logs
Log tidak bisa dikaitkan dengan tracetrace ID tidak masuk MDC/log patterncek logback/log4j pattern dan instrumentation
Kafka consumer trace tidak terhubungtrace context tidak masuk message headersinspect message headers dan consumer instrumentation
Trace volume membengkaksampling terlalu tinggi atau health check ikut disimpancek ingestion volume per route/service
Trace attribute mengandung PIIinstrumentation menyimpan payload/header sensitifaudit attribute schema dan sample trace
Dependency latency tidak terlihatHTTP/JDBC/SDK instrumentation belum aktifcek span list dan instrumentation coverage
Cloud SDK timeout tidak terlihatSDK call tidak dibungkus span/manual instrumentationtambahkan SDK dependency spans dan metrics
Trace exporter gagalcollector unreachable, IAM/RBAC salah, endpoint blockedcek collector logs, network path, identity permission
Application melambat setelah instrumentationoverhead agent/exporter tinggicek CPU/memory, exporter backpressure, sampling
Data antar environment tercampurservice.name/environment/resource attributes salahcek resource attributes dan backend routing

14. Debugging playbook

14.1 Request lambat

Urutan debug:

  1. Cari trace berdasarkan correlation ID atau trace ID.
  2. Lihat critical path, bukan hanya total span count.
  3. Identifikasi span dengan latency terbesar.
  4. Bedakan latency service sendiri vs downstream.
  5. Cek retry count dan timeout.
  6. Korelasikan dengan metrics p95/p99.
  7. Cek log error pada trace ID yang sama.
  8. Cek apakah ada deployment/config change sebelum latency naik.

14.2 502/503/504 dari gateway atau ingress

Cek:

  • trace sampai service atau berhenti di gateway?
  • gateway punya trace span?
  • ingress meneruskan trace header?
  • backend target healthy?
  • service response timeout lebih lama dari gateway timeout?
  • apakah pod menerima request?
  • apakah application thread pool penuh?
  • apakah downstream dependency menyebabkan request menggantung?

14.3 Message hilang atau double process

Cek:

  • producer span ada?
  • message ID ada?
  • causation ID ada?
  • consumer span ada?
  • consumer group lag?
  • retry/DLQ span?
  • idempotency key?
  • apakah trace sampling menyembunyikan consumer trace?

14.4 Cloud SDK timeout

Cek:

  • span operation cloud service mana yang lambat?
  • endpoint public atau private?
  • region benar?
  • retry berapa kali?
  • error throttling atau network timeout?
  • credential refresh terjadi di request path?
  • DNS resolution ke private endpoint benar?
  • NAT/firewall/proxy ikut jalur?

15. Observability design untuk quote/order system

Untuk domain CPQ/quote/order, trace sebaiknya memodelkan operasi bisnis besar:

  • quote draft creation,
  • catalog validation,
  • pricing calculation,
  • approval workflow,
  • quote submission,
  • order creation,
  • document generation,
  • event publication,
  • status synchronization.

Contoh trace naming:

QuoteResource.submitQuote
QuoteApplicationService.validateAndSubmit
CatalogClient.getProductConfiguration
PricingClient.calculatePrice
PostgreSQL.updateQuoteStatus
KafkaProducer.publishQuoteSubmitted
BlobStorage.uploadQuotePdf

Jangan menamai semua span dengan nama teknis generik seperti execute, call, process, atau handle. Nama span harus membantu membaca dependency graph.

16. Correctness concerns

Tracing tidak boleh mengubah correctness aplikasi.

Hal yang harus dijaga:

  • instrumentation failure tidak boleh menggagalkan business request;
  • exporter backpressure tidak boleh menahan request thread;
  • manual span harus selalu ditutup;
  • async context tidak boleh bocor antar request;
  • MDC harus dibersihkan setelah request;
  • retry akibat telemetry export harus dibatasi;
  • sampling tidak boleh digunakan sebagai sumber truth untuk audit bisnis;
  • trace bukan transactional log.

17. Security, privacy, and compliance concerns

Tracing sering tanpa sadar menangkap data sensitif.

Jangan simpan:

  • token,
  • password,
  • secret value,
  • authorization header,
  • cookie,
  • PII,
  • full request body,
  • full response body,
  • raw SQL dengan literal sensitif,
  • object storage signed URL penuh,
  • SAS token,
  • presigned URL query string.

Perlu diverifikasi:

  • siapa yang bisa melihat trace,
  • retention trace,
  • masking/scrubbing policy,
  • export ke vendor eksternal,
  • data residency,
  • environment separation,
  • apakah trace menjadi compliance evidence atau hanya diagnostic signal.

18. Performance and cost concerns

Tracing punya overhead.

Sumber biaya dan overhead:

  • span volume,
  • attribute cardinality,
  • log-trace correlation indexing,
  • collector CPU/memory,
  • network egress telemetry,
  • backend ingestion,
  • retention,
  • query volume,
  • always-on debug sampling.

Production guardrails:

  • sampling policy eksplisit;
  • health check route dikecualikan atau disampling rendah;
  • payload tidak disimpan;
  • attribute allowlist;
  • exporter queue dibatasi;
  • collector resources dimonitor;
  • dashboard ingestion cost tersedia.

19. PR review checklist

Saat mereview PR yang menyentuh observability/tracing, tanyakan:

  • Apakah trace context dipropagasikan inbound dan outbound?
  • Apakah correlation ID masuk log?
  • Apakah route menggunakan template, bukan full dynamic path?
  • Apakah Kafka/RabbitMQ headers membawa trace context?
  • Apakah cloud SDK dependency terlihat sebagai span/metric?
  • Apakah timeout/retry/circuit breaker terlihat?
  • Apakah ada PII/secret/token di attributes?
  • Apakah sampling dipahami dan terdokumentasi?
  • Apakah lower environment dan production memakai resource attributes berbeda?
  • Apakah collector/exporter failure tidak mematikan service?
  • Apakah dashboard membantu incident triage?
  • Apakah alert berbasis symptom, bukan hanya telemetry pipeline health?

20. Internal verification checklist

Verifikasi di CSG/team/platform/SRE/security:

  • Apakah standar tracing menggunakan OpenTelemetry?
  • Apakah AWS memakai X-Ray, CloudWatch, ADOT, atau vendor lain?
  • Apakah Azure memakai Application Insights, Azure Monitor OpenTelemetry, Log Analytics, atau vendor lain?
  • Apakah ada standard service.name, deployment.environment, cloud.region, k8s.namespace.name?
  • Apakah trace ID masuk structured logs?
  • Apakah correlation ID header standard sudah ditentukan?
  • Apakah Kafka/RabbitMQ trace propagation sudah distandardkan?
  • Apakah cloud SDK instrumentation aktif?
  • Apakah JDBC/PostgreSQL instrumentation aktif?
  • Apakah Redis instrumentation aktif?
  • Apakah sampling policy per environment tersedia?
  • Apakah PII/secret scrubbing policy tersedia?
  • Apakah telemetry endpoint private/public/proxy?
  • Apakah collector berjalan sebagai sidecar, DaemonSet, gateway, atau managed add-on?
  • Apakah dashboard incident utama sudah ada?
  • Apakah incident notes lama menunjukkan gap observability?
  • Apakah trace data boleh digunakan sebagai compliance evidence atau hanya debugging aid?

21. Production readiness checklist

Sebuah service Java/JAX-RS dianggap siap dari sisi tracing bila:

  • inbound HTTP span tersedia;
  • outbound HTTP span tersedia;
  • PostgreSQL dependency span tersedia;
  • Kafka/RabbitMQ publish/consume span tersedia jika digunakan;
  • Redis span tersedia jika digunakan;
  • AWS/Azure SDK dependency terlihat;
  • trace ID dan correlation ID muncul di log;
  • sensitive data tidak muncul di trace;
  • sampling policy jelas;
  • telemetry failure tidak mengganggu request path;
  • collector/exporter dimonitor;
  • dashboard mendukung debugging request lambat, error, timeout, dan dependency issue;
  • runbook menjelaskan cara mencari trace dari incident alert.

22. Ringkasan mental model

Tracing yang matang bukan soal memasang agent lalu selesai.

Tracing yang matang berarti:

  • setiap request punya identity teknis yang bisa diikuti;
  • setiap dependency penting terlihat;
  • async causality tidak hilang;
  • telemetry aman dari PII/secret leakage;
  • sampling tidak menyesatkan analisis;
  • log, metric, dan trace saling menguatkan;
  • engineer bisa bergerak dari alert ke root cause dengan cepat.

Untuk senior backend engineer, kemampuan terpenting bukan hanya membaca trace, tetapi memahami kapan trace tidak lengkap, bias, salah, terlalu mahal, atau membocorkan data.

References

Lesson Recap

You just completed lesson 37 in deepen practice. Use the series map if you want to review the broader track, or continue directly into the next lesson while the context is still warm.

Continue The Track

Keep the momentum while the lesson is still fresh. Move backward for review or continue forward into the next concept.