Demo: a day in a backend engineer's workflow, walked through
On This Lesson 11 topics
Lesson Overview
So far this module has described engineering in general: the work beyond writing code, the roles in a team, the path of a feature, and the career map. In this lesson you will watch all of it happen in one small, concrete story. We follow one ticket through one working day of a backend engineer, from reading the task to watching a dashboard after the release.
The story is a demo. It is written so that you can follow it without running anything. Where there are commands or code, they are real and small, so you can see what the work looks like. You are not expected to type along, and you are not expected to know Git, testing tools, or pipelines yet: later modules teach them in detail, and each is explained briefly here, when it first appears.
The demo includes a planned mistake. The engineer forgets to run the tests before opening a pull request, and an automatic check fails. Mistakes like this are normal. What matters is that the team's process catches them cheaply, and that the engineer fixes them calmly. Seeing an ordinary mistake handled well is one of the most useful things a beginner can learn.
In the house picture, this is a day on the building site: the work order arrives, the builder asks the supervisor one question, does the job, an inspector checks it, a small defect is found and fixed, and then the new part is handed over and watched. Everything from the earlier lessons is here: the roles, the stations of a feature's path, and the habits of an engineer.
Important caution: real teams use different tools and different names. The tool names here (a ticket system, Git, a pull request, an automatic check, a dashboard) are common, but your future team may use others, and exact menus and commands depend on your operating system and tools. Treat the story as a pattern, not a recipe.
Learning Objectives
By the end of this lesson you will be able to:
- Describe the steps of a typical day on one ticket: read, clarify, branch, change, test, pull request, review, release, watch.
- Explain why an engineer asks a clarifying question before changing code.
- Explain what a branch, a commit, and a pull request are, in simple terms.
- Explain what an automatic check does and why it can fail even when the code change is small.
- Describe how to respond to a failed check and to a review comment.
- Recognize the roles from lesson 2 and the stations from lesson 3 in a real working day.
- Say what a team watches after a release and why.
Written Explanation
The setting
The company runs a food-ordering service like the one used in earlier lessons. The backend returns a description of an order when the app asks for it. Our engineer, Sam, is a junior backend engineer on a team of five. The team uses a ticket system: a list of tasks, each with a short description and a status. Sam picks up this ticket:
Ticket ORD-142: Return the customer's email in the order response.
The ticket is short on purpose. Real tickets often are. Let us follow the day, step by step.
Step 1: Read the ticket
Sam reads the ticket, then looks at what already exists. Today the order response contains the order number and the total price in cents. The frontend team wants to show "A receipt was sent to ..." with the customer's email on the confirmation screen, so they need the email in the response too.
Reading includes reading existing code. Sam finds the class that builds the order response and its test, and reads them to learn how the code is arranged. This is the reading habit from lesson 1: code is read far more often than written, and a lot of the day is reading.
Step 2: Ask one clarifying question
Before touching the code, Sam asks one question in the ticket's comments:
"Is the email returned to anyone who asks for the order, or only to the logged-in customer who owns it? I want to be sure we are not exposing someone's email to another customer."
This is the "what problem are we solving?" habit. An email is personal data, so a wrong answer would be a privacy problem, not just a bug. The product owner replies within the hour:
"Only the owner. The existing access check already makes sure only the owner can read an order, so no change is needed there."
Sam now knows that the existing check protects the data, and that the change is small. The question took two minutes. Without it, Sam might have built a second, unnecessary access check, or worse, skipped thinking about access altogether.
Step 3: Create a branch
Sam makes a branch. In Git, the version control system used by most teams, a branch is a separate line of work, so Sam can change the project without disturbing teammates who are working on other things. A typical command is:
git switch -c feature/order-customer-emailgit switch -c <name> creates a new branch and switches to it, according to Git's documentation. The branch name is a convention: this team puts a short description after feature/. (You will learn Git properly in a later module. For now, read it as "start a private copy of the work".)
Step 4: Make the change
Here is a simplified version of the code. It is a small, self-contained program so that you can see how the pieces relate. In the real service these classes would be in separate files and used by a web framework, but the shape of the work is the same.
public class OrderDemo {
static class Customer {
final String name;
final String email;
Customer(String name, String email) {
this.name = name;
this.email = email;
}
}
static class Order {
final long id;
final Customer customer;
final int totalCents;
Order(long id, Customer customer, int totalCents) {
this.id = id;
this.customer = customer;
this.totalCents = totalCents;
}
}
static class OrderResponse {
final long orderId;
final int totalCents;
final String customerEmail; // new field for ORD-142
OrderResponse(long orderId, int totalCents, String customerEmail) {
this.orderId = orderId;
this.totalCents = totalCents;
this.customerEmail = customerEmail;
}
static OrderResponse from(Order order) {
return new OrderResponse(order.id, order.totalCents, order.customer.email);
}
}
public static void main(String[] args) {
Customer customer = new Customer("Lina", "lina@example.com");
Order order = new Order(7L, customer, 1250);
OrderResponse response = OrderResponse.from(order);
System.out.println(response.orderId + " " + response.totalCents + " " + response.customerEmail);
}
}Running this prints 7 1250 lina@example.com. Before the change, OrderResponse had only two fields and a two-argument constructor. Sam added the field customerEmail, a third constructor argument, and the line that copies the email from the customer. The email is a real address that belongs to a customer, which is why the question in step 2 mattered. (The address shown is an obvious placeholder.)
Sam also adds a test: a small program that checks one behavior and reports pass or fail. The team uses JUnit 5, a common testing library for Java; its assertions are static methods of org.junit.jupiter.api.Assertions, according to the JUnit documentation.
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
class OrderResponseTest {
@Test
void responseContainsCustomerEmail() {
OrderDemo.Customer customer = new OrderDemo.Customer("Lina", "lina@example.com");
OrderDemo.Order order = new OrderDemo.Order(7L, customer, 1250);
OrderDemo.OrderResponse response = OrderDemo.OrderResponse.from(order);
assertEquals("lina@example.com", response.customerEmail);
}
}(This test needs JUnit on the project's classpath, which a real project sets up with its build tool. Do not worry about that setup now.)
Sam then commits the work. A commit is a saved snapshot of the changes, with a short message that says what changed and why:
git add .
git commit -m "Return customer email in the order response (ORD-142)"Step 5: Run the tests (the step Sam forgets)
The team's rule is: run all tests on your own computer before opening a pull request. The command depends on the project's build tool. Many Java projects use Maven or Gradle, and the command is often one of these (check the project's README for the real one):
./mvnw test
./gradlew testOn Windows the commands are usually mvnw.cmd test or gradlew.bat test. Running the whole test suite takes about a minute.
This is the planned mistake. Sam has just fixed a tricky formatting problem, feels done, and it is nearly lunchtime. Sam skips the full test run and moves on.
Step 6: Open a pull request
Sam pushes the branch to the team's shared repository (git push -u origin feature/order-customer-email) and opens a pull request. As GitHub's documentation describes it, a pull request is a proposal to merge the changes into the project, and a place where collaborators discuss and review the changes first. Sam writes a short description:
ORD-142: return customer email in the order response. Adds
customerEmailto the order response so the app can show where the receipt was sent. Access control is unchanged: only the order's owner can read the order (confirmed with the product owner on the ticket). Added a test for the new field.
A good description says what changed, why, what was checked, and what the reviewer should know. A busy reviewer reads a clear description gladly.
Step 7: The automatic check fails
Within a few minutes, the pull request shows a red mark: the team's automatic check (the continuous integration job from lesson 3) failed. This job runs on a server whenever a pull request is opened or updated. It builds the project and runs all the tests, and reports pass or fail.
Sam opens the details and reads the message. The build fails to compile an older test called OrderResponseFormatTest, which still creates the response with the old two-argument constructor:
new OrderResponse(7L, 1250) // no longer compiles: the constructor now needs three argumentsThat is exactly what a local test run would have shown, in a minute, before anyone else saw it. Nobody is upset. The check did its job: it caught a problem before it reached the main code. Sam fixes the older test by passing an email as the third argument, runs the full test suite locally this time, sees all green, commits the fix, and pushes again:
git add .
git commit -m "Update order response format test for the new constructor"
git pushThe pull request updates by itself, the check runs again, and this time it passes.
What Sam learns, and what the team's process teaches: do the cheap local check first, and read failures carefully, because the message usually says exactly what is wrong. Also, notice what did not happen: the broken code never reached users, and no one else had to stop their work.
Step 8: Respond to a review comment
A teammate, Dana, reviews the pull request and leaves one comment:
"Could we also add a test for what happens when a customer has no email (guest checkout)? What does the response show in that case?"
This is a real question about behavior. Sam checks the code: order.customer.email would be null for a guest, and the response would carry null. Whether the frontend can handle null is a decision to make. Sam replies:
"Good catch. For guests the response will contain
nullfor the email. I'll add a test for that and ask the frontend team to confirm that the screen hides the 'receipt sent' line when the email is missing."
Sam adds the test, pushes, and messages the frontend engineer. This is the handoff as a conversation from lesson 2: the backend and the frontend agree on what the response means. Dana approves the pull request.
Step 9: Merge
With the checks green and the review approved, Sam merges the pull request, which makes the change part of the main version of the project. Merging is typically a button on the pull request page. Because of the team's pipeline, merging starts the next stage automatically.
Step 10: Release and watch
The team's pipeline builds the merged code and releases it. In many teams this is done in stages: first to a small share of traffic, then to everyone, with a quick way back (a rollback) if something looks wrong. The exact method depends on the team.
Sam does not close the laptop and leave. For a short while after release, Sam looks at the team's dashboard: a screen with charts of what the service is doing. Sam watches:
- The error rate: has it gone up?
- The response time: is the order endpoint still fast?
- The logs: are there new messages about missing emails?
Everything looks normal. Sam updates the ticket to "done", with a note: "Released. Guest orders return null email; frontend informed." The loop is closed, until a user or a chart gives the team the next idea.
The whole day, in one table
| Time | What Sam does | Station (lesson 3) | Role involved (lesson 2) |
|---|---|---|---|
| 9:00 | Reads the ticket and the existing code | Requirements | Backend, product owner |
| 9:20 | Asks one clarifying question and gets an answer | Requirements | Backend, product owner |
| 9:40 | Creates a branch, changes the code, adds a test | Code | Backend |
| 11:30 | Commits; skips the full test run (the planned mistake) | Test (skipped) | Backend |
| 11:45 | Opens a pull request | Review | Backend |
| 11:55 | The automatic check fails; Sam reads the error | Test | DevOps pipeline, backend |
| 12:20 | Fixes the old test, runs everything locally, pushes | Code, Test | Backend |
| 14:00 | Responds to Dana's review comment, adds a test, tells the frontend | Review | Backend, frontend |
| 14:30 | Merges after approval | Review | Backend |
| 15:00 | Release goes out in stages | Release | DevOps pipeline |
| 15:10 | Watches the dashboard and logs | Monitor | Backend, SRE or operations |
The times are invented for the story. Real days are interrupted by meetings, questions, other tickets, and surprises.
Examples
Example 1: a clarifying question (simple)
The ticket says "show the most popular dishes". Before coding, Sam asks: "Popular by number of orders or by revenue, and over which period: today, this week, all time?" The answer ("by number of orders, last 30 days") turns a vague idea into a checkable requirement. One sentence saved days of work on the wrong thing.
Example 2: reading a failed check (practical)
A check fails with a message that says a test expected 1250 but got 1500. The engineer's reflex should not be to rerun the check hoping it passes. A better routine:
- Read the failure message to find which test failed and what was expected.
- Reproduce it locally by running that test.
- Work out whether the code or the test is wrong. Here, the code applied a 20-percent fee twice.
- Fix the cause, run the whole suite, and push.
This is careful, step-by-step problem finding applied in a team setting. Never silence a failing test just to make the mark turn green: the test is the evidence.
Example 3: a day with an interruption (realistic)
At 13:00, an alert arrives: the order endpoint is slow. Sam pauses the pull request and joins the investigation, helped by a teammate who is on call that day. Together they find that a recent change in another team's code caused the slowdown, and they ask that team to roll back. This takes two hours. Sam returns to ORD-142 at 15:00.
Real days are like this: planned work competes with production issues, and engineers learn to switch carefully. They leave a note on the paused work ("waiting for review comment reply"), so that nothing is forgotten. The ticket's release moves to the next morning. Nobody forces it out late in the day, because releasing while tired and while another incident is active is a risk the team avoids.
Backend Insight
The demo shows several things that are specific to backend work:
- Data and privacy come first. Sam's best moment was the question about the email. Backend responses can expose personal data, and the engineer is often the last person who can prevent it.
- The response is a contract. The frontend relies on the shape of the response. Adding a field is usually safe; removing or renaming one can break other teams. The test and the message to the frontend protected that contract.
- Missing values are normal. Guests with no email, empty lists, and unknown values are everyday cases. Handling them, and testing them, is a large part of backend quality.
- Automatic checks protect everybody. On a shared codebase, an automatic check is the team's safety net: it catches what one person did not run.
- You are not done at merge. Watching the dashboard after release is part of the job.
If you look back at the career map from lesson 4, notice that this entire story sits at Junior level: a small change, inside an existing design, with a reviewer's help. The same steps scale up. A Senior engineer follows the same path, with larger changes and more people to agree with.
Common Mistakes
Mistake 1: Starting to code without asking when something is unclear
- Incorrect: "The ticket is short, so I will guess what is meant."
- Correct: "I will ask one precise question first, especially when personal data or other teams are involved."
Mistake 2: Skipping the local test run
The planned mistake in this demo is real and common. Run the tests before you push, so that the cheap check happens on your own machine rather than in front of the team. The automatic check does not replace your own run; it backs it up.
Mistake 3: Making the pull request huge
A pull request with hundreds of changed lines is hard to review, and reviewers skim. Keep each pull request to one purpose and small enough to read in a short time.
Mistake 4: Arguing with or ignoring review comments
A review comment is a question or suggestion about the code. Answer it, change the code, or explain your reasoning politely. Do not ignore it, and do not take it as a personal attack.
Mistake 5: Walking away after merging
- Incorrect: "It is merged, so my work is over."
- Correct: "I watch the dashboard and logs for a while, and I tell the affected teams what to expect."
Exercises
Try each exercise yourself before opening the solutions.
Level A: Foundation
A1. Write the steps of Sam's day in order, using your own words (at least eight steps).
Show solution A1
A1. Example: read the ticket and existing code; ask a clarifying question; create a branch; change the code and add a test; commit; (skip the local tests by mistake); open a pull request; the automatic check fails; fix the old test and run everything locally; answer the review comment and add a test; merge; the release goes out; watch the dashboard.
A2. What is a pull request, in one sentence?
Show solution A2
A2. A pull request is a proposal to merge a set of changes into the main project, and a place where teammates review and discuss the changes before merging.
A3. Why did Sam ask the clarifying question before changing the code?
Show solution A3
A3. Because the email is personal data, and a wrong assumption about who may see it would be a privacy problem. The question was cheap and the answer showed the existing access check was enough.
Level B: Application
B1. The automatic check failed because an old test used a constructor that Sam had changed. Explain what Sam should do first when seeing a red mark, and what Sam should do to avoid it next time.
Show solution B1
B1. First read the failure message to see which test failed and why. Then reproduce it locally, fix the cause (here, update the old test for the new constructor), run all tests, and push. To avoid it, always run the full test suite on your own computer before opening or updating a pull request.
B2. Dana asks: "What happens for a guest with no email?" Write the reply you would send, and one test you would add (describe it in words).
Show solution B2
B2. Example reply: "For guests the response will contain null for the email. I will add a test for that, and I will ask the frontend team to confirm that the screen hides the receipt line." Example test: create an order whose customer has no email, build the response, and check that the email field is null and that the other fields are still correct.
B3. Match each step to a station from lesson 3 (idea, requirements, design, code, review, test, release, monitor): (a) reading the ticket and asking about who may see the email, (b) writing the new field and its test, (c) Dana reads the pull request, (d) the pipeline sends the new version to a small share of users, (e) Sam watches error rates on the dashboard.
Show solution B3
B3. (a) Requirements. (b) Code (with tests). (c) Review. (d) Release. (e) Monitor.
Level C: Challenge
C1. Write your own short ticket for a small backend change (for example "include the delivery fee in the order response"). Then write the one clarifying question you would ask first, two things you would test, and one thing you would watch after the release.
Show solution C1
C1. Answers vary. Example: Ticket: "Include the delivery fee in the order response." Question: "Should the fee be shown separately from the total, or included in it, and in which currency format?" Tests: an order with a fee, an order with free delivery (fee of zero). Watch: the error rate of the order endpoint and any support messages about wrong totals.
C2. Retell the demo as if the clarifying question had not been asked, and the email had been returned to any caller who knew an order number. Describe what could go wrong, which station would have caught it (if any), and what it shows about asking early.
Show solution C2
C2. Without the question, Sam might have returned the email without checking access. If the existing check did not exist, anyone who guessed an order number could read other customers' emails, which is a serious privacy problem. Tests written only for the happy path would not catch it; a good review might, but a reviewer may not think of it. The story shows that asking early is cheaper than hoping a later station catches the problem.
Mini Challenge
Write your own "day on one ticket" for a different small backend task of your choice (for example "reject orders with an empty basket" or "log a message when payment fails"). Use the same ten steps as the demo, one or two sentences each, in a table with a time column. Include:
- A clarifying question with a plausible answer.
- A planned mistake of your own (for example, forgetting to handle an empty list) and the step where the team catches it.
- One review comment and how you answer it.
- What you watch after the release.
Check your work: all ten steps appear in order, your mistake is caught by a station (a test, a check, or a review) before reaching users, and you treated the mistake as a normal event rather than a disaster. Your details are invented, so keep them plausible.
Summary & Next Lesson
Key takeaways
- A day of backend work is a path: read, clarify, branch, change, test, pull request, review, merge, release, watch.
- Asking a precise question early prevents expensive mistakes, especially around personal data and other teams.
- A branch is a private line of work, a commit is a saved snapshot, and a pull request proposes merging changes and invites review.
- Automatic checks catch what you did not run, but you should run the tests yourself first.
- A failed check is information, not failure: read it, fix the cause, and push again.
- After release, you watch errors, speed, and feedback. The loop then continues.
Next lesson
This is the last lesson of the module on engineering. You now know what engineers do, who they work with, how a feature travels, where this course leads, and how a real day looks. Before moving on, complete the module's lab, "Read job posts", which asks you to map real job requirements to the levels and modules of this course. After that, you continue to the next module in the curriculum.
Self-check
- Why does an engineer ask a clarifying question before coding?
- What is a branch?
- What does an automatic check do, and what should you do when it fails?
- Why did Sam message the frontend team after the review comment?
- What does a team watch after a release?
Show answers
- To make sure they build the right thing and avoid expensive mistakes, such as exposing personal data by accident.
- A separate line of work in version control, so you can change the project without disturbing teammates.
- It builds the project and runs the tests on a server and reports pass or fail. When it fails, read the message, reproduce the problem locally, fix the cause, run all tests, and push again.
- Because the meaning of the response had changed for guests (a missing email), and the frontend needs to handle it. Agreeing on the shape of the response is a conversation between roles.
- The error rate, response time, logs, and user or support feedback.
References
- Git, git-switch documentation. Supports the statement that
git switch -c <new-branch>creates a new branch and switches to it. The page does not state a minimum version; its changelog starts at Git 2.23, so the command is relatively recent (that is my inference). - GitHub Docs, About pull requests. Supports the description of a pull request as a proposal to merge changes that gives collaborators a place to review and discuss them, with automatic checks shown on the page.
- JUnit documentation, Writing tests: Assertions. Supports the statement that JUnit Jupiter assertions are static methods of
org.junit.jupiter.api.Assertionsand the structure of the minimal test (@Testfromorg.junit.jupiter.api). - Martin Fowler, Continuous Integration. Supports the description of an automatic build and tests that run on each change and report quickly.
- The ticket, the people, the times, the failed check, and the dashboard are invented for teaching. The demo code in the first listing is self-contained and I checked it by reading, not by running it in this session; the test listing needs JUnit configured in a real project. Build commands (
mvnw,gradlew) vary by project and operating system, so the lesson tells readers to check their project's README.
Practice
Apply this lesson with the module's lab, exercises and quiz.
Marking a lesson complete is optional and you can undo it any time. Your progress stays in this browser.